Merge branch 'zhangyuanshan-20250226-mobile'
BIN
src/assets/image/home/375/de/carousel-1.png
Normal file
After Width: | Height: | Size: 407 KiB |
BIN
src/assets/image/home/375/de/carousel-2.png
Normal file
After Width: | Height: | Size: 402 KiB |
BIN
src/assets/image/home/375/de/carousel-3.png
Normal file
After Width: | Height: | Size: 451 KiB |
BIN
src/assets/image/home/375/de/carousel-4.png
Normal file
After Width: | Height: | Size: 451 KiB |
BIN
src/assets/image/home/375/icon-close.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/image/home/375/icon-language.png
Normal file
After Width: | Height: | Size: 276 B |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.8 KiB |
BIN
src/assets/image/home/768/de/carousel-1.png
Normal file
After Width: | Height: | Size: 683 KiB |
BIN
src/assets/image/home/768/de/carousel-2.png
Normal file
After Width: | Height: | Size: 655 KiB |
BIN
src/assets/image/home/768/de/carousel-3.png
Normal file
After Width: | Height: | Size: 759 KiB |
BIN
src/assets/image/home/768/de/carousel-4.png
Normal file
After Width: | Height: | Size: 749 KiB |
BIN
src/assets/image/home/768/icon-language.png
Normal file
After Width: | Height: | Size: 276 B |
@ -15,7 +15,9 @@ export default {
|
|||||||
nav: {
|
nav: {
|
||||||
home: 'Startseite',
|
home: 'Startseite',
|
||||||
company: 'Unternehmensprofil',
|
company: 'Unternehmensprofil',
|
||||||
businessintroduction: 'Geschäftsvorstellung'
|
businessintroduction: 'Geschäftsvorstellung',
|
||||||
|
please_select: 'Bitte auswählen',
|
||||||
|
confirm_select: 'Bestätigen Sie die Auswahl'
|
||||||
},
|
},
|
||||||
scroll: {
|
scroll: {
|
||||||
tip: 'Nach unten scrollen'
|
tip: 'Nach unten scrollen'
|
||||||
|
@ -15,7 +15,9 @@ export default {
|
|||||||
nav: {
|
nav: {
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
company: 'Company Overview',
|
company: 'Company Overview',
|
||||||
businessintroduction: 'Business Introduction'
|
businessintroduction: 'Business Introduction',
|
||||||
|
please_select: 'Please Select',
|
||||||
|
confirm_select: 'Confirm Selection'
|
||||||
},
|
},
|
||||||
scroll: {
|
scroll: {
|
||||||
tip: 'Scroll Down'
|
tip: 'Scroll Down'
|
||||||
|
@ -15,7 +15,9 @@ export default {
|
|||||||
"nav": {
|
"nav": {
|
||||||
"home": "ホーム",
|
"home": "ホーム",
|
||||||
"company": "会社概要",
|
"company": "会社概要",
|
||||||
"businessintroduction": "業務紹介"
|
"businessintroduction": "業務紹介",
|
||||||
|
"please_select": "選択してください",
|
||||||
|
"confirm_select": "確認選択"
|
||||||
},
|
},
|
||||||
"scroll": {
|
"scroll": {
|
||||||
"tip": "下にスクロール"
|
"tip": "下にスクロール"
|
||||||
|
@ -15,7 +15,9 @@ export default {
|
|||||||
"nav": {
|
"nav": {
|
||||||
"home": "首頁",
|
"home": "首頁",
|
||||||
"company": "公司概況",
|
"company": "公司概況",
|
||||||
"businessintroduction": "業務介紹"
|
"businessintroduction": "業務介紹",
|
||||||
|
"please_select": "請選擇",
|
||||||
|
"confirm_select": "確認選擇"
|
||||||
},
|
},
|
||||||
"scroll": {
|
"scroll": {
|
||||||
"tip": "向下滑動"
|
"tip": "向下滑動"
|
||||||
|
@ -15,7 +15,10 @@ export default {
|
|||||||
nav: {
|
nav: {
|
||||||
home: '首页',
|
home: '首页',
|
||||||
company: '公司概况',
|
company: '公司概况',
|
||||||
businessintroduction: '业务介绍'
|
businessintroduction: '业务介绍',
|
||||||
|
language_change: '语言切换',
|
||||||
|
please_select: '请选择',
|
||||||
|
confirm_select: '确认选择'
|
||||||
},
|
},
|
||||||
scroll: {
|
scroll: {
|
||||||
tip: '向下滑动'
|
tip: '向下滑动'
|
||||||
|
@ -8,28 +8,69 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-item ellipsis"" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[36px] ml-[26px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div v-if="showLanguageModal" class="language-modal">
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[102px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body">
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section class="relative pb-[1020px]">
|
<section class="relative pb-[1020px]">
|
||||||
<div class="absolute top-[0px] right-[0px]">
|
<div class="absolute top-[0px] right-[0px]">
|
||||||
@ -541,20 +582,27 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NDivider } from "naive-ui";
|
import { NDivider } from "naive-ui";
|
||||||
import { onUnmounted, ref, onMounted, reactive, nextTick, computed } from "vue";
|
import {
|
||||||
|
onUnmounted,
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
reactive,
|
||||||
|
nextTick,
|
||||||
|
watch,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
// Define component custom events
|
// Define component custom events
|
||||||
defineEmits(["sendCode"]);
|
defineEmits(["sendCode"]);
|
||||||
|
|
||||||
// Register ScrollTrigger plugin
|
// Register ScrollTrigger plugin
|
||||||
gsap.registerPlugin(ScrollTrigger);
|
gsap.registerPlugin(ScrollTrigger);
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const { transitionState } = useTransitionComposable();
|
const { transitionState } = useTransitionComposable();
|
||||||
|
|
||||||
const moveRefs = ref(
|
const moveRefs = ref(
|
||||||
@ -564,7 +612,14 @@ const moveRefs = ref(
|
|||||||
);
|
);
|
||||||
const { currentTab } = useHome();
|
const { currentTab } = useHome();
|
||||||
let ctx;
|
let ctx;
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
// Import images
|
// Import images
|
||||||
import imageshow3 from "@/assets/image/businessintroduction/375/imageshow-3.png";
|
import imageshow3 from "@/assets/image/businessintroduction/375/imageshow-3.png";
|
||||||
import imageshow4 from "@/assets/image/businessintroduction/375/imageshow-4.png";
|
import imageshow4 from "@/assets/image/businessintroduction/375/imageshow-4.png";
|
||||||
@ -594,6 +649,7 @@ let carouselAnimation = null; // Store GSAP animation instance
|
|||||||
|
|
||||||
// Listen for window size changes
|
// Listen for window size changes
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
initLanguage();
|
||||||
ctx = gsap.context(() => {
|
ctx = gsap.context(() => {
|
||||||
moveRefs.value.forEach((moveRef, index) => {
|
moveRefs.value.forEach((moveRef, index) => {
|
||||||
if (moveRef.value) {
|
if (moveRef.value) {
|
||||||
@ -678,6 +734,48 @@ const challengeItems = computed(() => [
|
|||||||
desc: t("businessintroduction.industry.challenges.items.3.desc"),
|
desc: t("businessintroduction.industry.challenges.items.3.desc"),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
// 添加语言变化的监听
|
||||||
|
watch(
|
||||||
|
() => localStorage.getItem("language"),
|
||||||
|
(newLang) => {
|
||||||
|
if (newLang) {
|
||||||
|
currentLanguage.value = newLang;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -694,7 +792,7 @@ const challengeItems = computed(() => [
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
padding: 0 138px;
|
padding: 0 102px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
.logo {
|
.logo {
|
||||||
@ -706,9 +804,8 @@ const challengeItems = computed(() => [
|
|||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 128px;
|
gap: 77px;
|
||||||
margin-right: 32px;
|
margin-left: 67px;
|
||||||
margin-left: 60px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-item {
|
.tab-item {
|
||||||
@ -716,6 +813,7 @@ const challengeItems = computed(() => [
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 61px;
|
font-size: 61px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
max-width: 251px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
@ -728,6 +826,11 @@ const challengeItems = computed(() => [
|
|||||||
color: #8b59fa;
|
color: #8b59fa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
white-space: nowrap; /* 防止文本换行 */
|
||||||
|
overflow: hidden; /* 隐藏溢出内容 */
|
||||||
|
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 113px;
|
font-size: 113px;
|
||||||
@ -832,4 +935,98 @@ const challengeItems = computed(() => [
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(230, 234, 238, 0.5) !important;
|
background-color: rgba(230, 234, 238, 0.5) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 67px 77px 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 82px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 72px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 46px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 82px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -12,24 +12,67 @@
|
|||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
|
</div>
|
||||||
|
<div class="tab-item" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/768/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[18px] ml-[13px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div
|
||||||
|
v-if="showLanguageModal"
|
||||||
|
class="language-modal"
|
||||||
|
@touchmove.prevent.stop
|
||||||
|
>
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[51px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body" @wheel.stop @touchmove.stop>
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section className="relative pb-[900px] section-first bg-[#F8F9FF]">
|
<section className="relative pb-[900px] section-first bg-[#F8F9FF]">
|
||||||
<div class="pt-[718px] relative">
|
<div class="pt-[718px] relative">
|
||||||
@ -464,13 +507,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useI18n } from "vue-i18n";
|
|
||||||
import { NDivider } from "naive-ui";
|
import { NDivider } from "naive-ui";
|
||||||
import { onUnmounted, ref, onMounted, reactive, nextTick } from "vue";
|
import { onUnmounted, ref, onMounted, reactive, watch, nextTick } from "vue";
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
|
|
||||||
// 定义组件的自定义事件
|
// 定义组件的自定义事件
|
||||||
defineEmits(["sendCode"]);
|
defineEmits(["sendCode"]);
|
||||||
@ -478,6 +528,7 @@ defineEmits(["sendCode"]);
|
|||||||
// 注册 ScrollTrigger 插件
|
// 注册 ScrollTrigger 插件
|
||||||
gsap.registerPlugin(ScrollTrigger);
|
gsap.registerPlugin(ScrollTrigger);
|
||||||
|
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { transitionState } = useTransitionComposable();
|
const { transitionState } = useTransitionComposable();
|
||||||
|
|
||||||
@ -615,6 +666,51 @@ const goToSection = (i) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 添加语言变化的监听
|
||||||
|
watch(
|
||||||
|
() => localStorage.getItem("language"),
|
||||||
|
(newLang) => {
|
||||||
|
if (newLang) {
|
||||||
|
currentLanguage.value = newLang;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -779,4 +875,98 @@ const goToSection = (i) => {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
max-height: calc(1.5em * 2);
|
max-height: calc(1.5em * 2);
|
||||||
}
|
}
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 33px 38px 55px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
overscroll-behavior: contain; /* 阻止滚动穿透 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 40px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 23px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -8,28 +8,68 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
|
</div>
|
||||||
|
<div class="tab-item ellipsis"" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[36px] ml-[26px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div v-if="showLanguageModal" class="language-modal">
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[102px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body">
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section style="background: #ffffff" className="relative">
|
<section style="background: #ffffff" className="relative">
|
||||||
<div class="relative section-first h-[3990px] box-contain pt-[2300px]">
|
<div class="relative section-first h-[3990px] box-contain pt-[2300px]">
|
||||||
@ -432,12 +472,13 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NDivider } from "naive-ui";
|
import { NDivider } from "naive-ui";
|
||||||
import { onUnmounted, ref, onMounted, reactive, nextTick } from "vue";
|
import { onUnmounted, ref, onMounted, reactive, watch, nextTick } from "vue";
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
// 定义组件的自定义事件
|
// 定义组件的自定义事件
|
||||||
defineEmits(["sendCode"]);
|
defineEmits(["sendCode"]);
|
||||||
|
|
||||||
@ -453,7 +494,16 @@ const moveRefs = ref(
|
|||||||
);
|
);
|
||||||
const { currentTab } = useHome();
|
const { currentTab } = useHome();
|
||||||
let ctx;
|
let ctx;
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
|
const router = useRouter();
|
||||||
// 导入图片
|
// 导入图片
|
||||||
import carouselShow1 from "@/assets/image/companyprofil/375/carouselShow-1.png";
|
import carouselShow1 from "@/assets/image/companyprofil/375/carouselShow-1.png";
|
||||||
import carouselShow2 from "@/assets/image/companyprofil/375/carouselShow-2.png";
|
import carouselShow2 from "@/assets/image/companyprofil/375/carouselShow-2.png";
|
||||||
@ -527,6 +577,7 @@ const handleResize = () => {
|
|||||||
|
|
||||||
// 监听窗口大小变化
|
// 监听窗口大小变化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
initLanguage();
|
||||||
ctx = gsap.context(() => {
|
ctx = gsap.context(() => {
|
||||||
moveRefs.value.forEach((moveRef, index) => {
|
moveRefs.value.forEach((moveRef, index) => {
|
||||||
if (moveRef.value) {
|
if (moveRef.value) {
|
||||||
@ -720,8 +771,7 @@ const handleDragEnd = (e) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
const router = useRouter();
|
|
||||||
const handleCarouselClick = (item, event) => {
|
const handleCarouselClick = (item, event) => {
|
||||||
// 检查事件类型是否为点击
|
// 检查事件类型是否为点击
|
||||||
if (event.type === "click") {
|
if (event.type === "click") {
|
||||||
@ -735,6 +785,48 @@ const handleCarouselClick = (item, event) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
// 添加语言变化的监听
|
||||||
|
watch(
|
||||||
|
() => localStorage.getItem("language"),
|
||||||
|
(newLang) => {
|
||||||
|
if (newLang) {
|
||||||
|
currentLanguage.value = newLang;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -752,7 +844,7 @@ const handleCarouselClick = (item, event) => {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
padding: 0 138px;
|
padding: 0 102px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
.logo {
|
.logo {
|
||||||
@ -764,16 +856,17 @@ const handleCarouselClick = (item, event) => {
|
|||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 128px;
|
gap: 77px;
|
||||||
margin-right: 32px;
|
margin-left: 67px;
|
||||||
margin-left: 60px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.tab-item {
|
.tab-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 61px;
|
font-size: 61px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
max-width: 251px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
@ -786,7 +879,11 @@ const handleCarouselClick = (item, event) => {
|
|||||||
color: #8b59fa;
|
color: #8b59fa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
white-space: nowrap; /* 防止文本换行 */
|
||||||
|
overflow: hidden; /* 隐藏溢出内容 */
|
||||||
|
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||||
|
}
|
||||||
.title {
|
.title {
|
||||||
font-size: 113px;
|
font-size: 113px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -899,4 +996,98 @@ const handleCarouselClick = (item, event) => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(230, 234, 238, 0.5) !important;
|
background-color: rgba(230, 234, 238, 0.5) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 67px 77px 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 82px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 72px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 46px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 82px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -12,24 +12,67 @@
|
|||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
|
</div>
|
||||||
|
<div class="tab-item" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/768/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[18px] ml-[13px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div
|
||||||
|
v-if="showLanguageModal"
|
||||||
|
class="language-modal"
|
||||||
|
@touchmove.prevent.stop
|
||||||
|
>
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[51px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body" @wheel.stop @touchmove.stop>
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section style="background: #ffffff" className="relative">
|
<section style="background: #ffffff" className="relative">
|
||||||
<div
|
<div
|
||||||
@ -409,15 +452,21 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NDivider } from "naive-ui";
|
import { NDivider } from "naive-ui";
|
||||||
import { onUnmounted, ref, onMounted, reactive, nextTick } from "vue";
|
import { onUnmounted, ref, onMounted, reactive, nextTick, watch } from "vue";
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
// 初始化 i18n
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
|
|
||||||
// 定义组件的自定义事件
|
// 定义组件的自定义事件
|
||||||
defineEmits(["sendCode"]);
|
defineEmits(["sendCode"]);
|
||||||
@ -727,6 +776,51 @@ const handleCarouselClick = (item, event) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 添加语言变化的监听
|
||||||
|
watch(
|
||||||
|
() => localStorage.getItem("language"),
|
||||||
|
(newLang) => {
|
||||||
|
if (newLang) {
|
||||||
|
currentLanguage.value = newLang;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -886,4 +980,98 @@ const handleCarouselClick = (item, event) => {
|
|||||||
width: 1px;
|
width: 1px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 33px 38px 55px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
overscroll-behavior: contain; /* 阻止滚动穿透 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 40px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 23px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -8,28 +8,68 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis""
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
|
</div>
|
||||||
|
<div class="tab-item ellipsis"" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[36px] ml-[26px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div v-if="showLanguageModal" class="language-modal">
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[102px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body">
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section
|
<section
|
||||||
className="section-first"
|
className="section-first"
|
||||||
@ -224,10 +264,20 @@ import {
|
|||||||
reactive,
|
reactive,
|
||||||
nextTick,
|
nextTick,
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
|
watch,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
pageTitleNo: "",
|
pageTitleNo: "",
|
||||||
});
|
});
|
||||||
@ -238,13 +288,57 @@ const route = useRoute();
|
|||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
state.pageTitleNo = route.query.titleNo;
|
state.pageTitleNo = route.query.titleNo;
|
||||||
});
|
});
|
||||||
onMounted(() => {});
|
onMounted(() => {
|
||||||
|
initLanguage();
|
||||||
|
});
|
||||||
onUnmounted(() => {});
|
onUnmounted(() => {});
|
||||||
|
|
||||||
const handleTabClick = (tab) => {
|
const handleTabClick = (tab) => {
|
||||||
currentTab.value = tab;
|
currentTab.value = tab;
|
||||||
router.push("/" + tab);
|
router.push("/" + tab);
|
||||||
};
|
};
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
// 添加语言变化的监听
|
||||||
|
watch(
|
||||||
|
() => localStorage.getItem("language"),
|
||||||
|
(newLang) => {
|
||||||
|
if (newLang) {
|
||||||
|
currentLanguage.value = newLang;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -253,7 +347,6 @@ const handleTabClick = (tab) => {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 260px;
|
height: 260px;
|
||||||
@ -262,7 +355,7 @@ const handleTabClick = (tab) => {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
padding: 0 138px;
|
padding: 0 102px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
.logo {
|
.logo {
|
||||||
@ -274,13 +367,17 @@ const handleTabClick = (tab) => {
|
|||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 128px;
|
gap: 77px;
|
||||||
margin-right: 32px;
|
margin-left: 67px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.tab-item {
|
.tab-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
font-size: 61px;
|
font-size: 61px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
max-width: 251px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
@ -293,6 +390,12 @@ const handleTabClick = (tab) => {
|
|||||||
color: #8b59fa;
|
color: #8b59fa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
white-space: nowrap; /* 防止文本换行 */
|
||||||
|
overflow: hidden; /* 隐藏溢出内容 */
|
||||||
|
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 113px;
|
font-size: 113px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -323,4 +426,98 @@ const handleTabClick = (tab) => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(230, 234, 238, 0.5) !important;
|
background-color: rgba(230, 234, 238, 0.5) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 67px 77px 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 82px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 72px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 46px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 82px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -12,24 +12,67 @@
|
|||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ $t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
|
</div>
|
||||||
|
<div class="tab-item" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/768/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[18px] ml-[13px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div
|
||||||
|
v-if="showLanguageModal"
|
||||||
|
class="language-modal"
|
||||||
|
@touchmove.prevent.stop
|
||||||
|
>
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[51px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body" @wheel.stop @touchmove.stop>
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<section
|
<section
|
||||||
className="section-first"
|
className="section-first"
|
||||||
@ -223,6 +266,7 @@ import {
|
|||||||
onMounted,
|
onMounted,
|
||||||
reactive,
|
reactive,
|
||||||
nextTick,
|
nextTick,
|
||||||
|
watch,
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
@ -230,9 +274,20 @@ const state = reactive({
|
|||||||
pageTitleNo: "",
|
pageTitleNo: "",
|
||||||
});
|
});
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { currentTab } = useHome();
|
const { currentTab } = useHome();
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
state.pageTitleNo = route.query.titleNo;
|
state.pageTitleNo = route.query.titleNo;
|
||||||
});
|
});
|
||||||
@ -242,6 +297,51 @@ const handleTabClick = (tab) => {
|
|||||||
currentTab.value = tab;
|
currentTab.value = tab;
|
||||||
router.push("/" + tab);
|
router.push("/" + tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 添加语言变化的监听
|
||||||
|
watch(
|
||||||
|
() => localStorage.getItem("language"),
|
||||||
|
(newLang) => {
|
||||||
|
if (newLang) {
|
||||||
|
currentLanguage.value = newLang;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -320,4 +420,98 @@ const handleTabClick = (tab) => {
|
|||||||
width: 1px;
|
width: 1px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 33px 38px 55px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
overscroll-behavior: contain; /* 阻止滚动穿透 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 40px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 23px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -6,30 +6,71 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis"
|
||||||
:class="{ active: currentTab === 'home' }"
|
:class="{ active: currentTab === 'home' }"
|
||||||
@click="handleTabClick('home')"
|
@click="handleTabClick('home')"
|
||||||
>
|
>
|
||||||
{{ t("home.nav.home") }}
|
{{ t("home.nav.home") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis"
|
||||||
:class="{ active: currentTab === 'companyprofil' }"
|
:class="{ active: currentTab === 'companyprofil' }"
|
||||||
@click="handleTabClick('companyprofil')"
|
@click="handleTabClick('companyprofil')"
|
||||||
>
|
>
|
||||||
{{ t("home.nav.company") }}
|
{{ t("home.nav.company") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item ellipsis"
|
||||||
:class="{ active: currentTab === 'businessintroduction' }"
|
:class="{ active: currentTab === 'businessintroduction' }"
|
||||||
@click="handleTabClick('businessintroduction')"
|
@click="handleTabClick('businessintroduction')"
|
||||||
>
|
>
|
||||||
{{ t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-item ellipsis" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[36px] ml-[26px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div v-if="showLanguageModal" class="language-modal">
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[102px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body">
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<main ref="main">
|
<main ref="main">
|
||||||
<div class="scroll-down" :class="{ hide: !scrollDownVisible }">
|
<div class="scroll-down ellipsis" :class="{ hide: !scrollDownVisible }">
|
||||||
{{ t("home.scroll.tip") }}
|
{{ t("home.scroll.tip") }}
|
||||||
</div>
|
</div>
|
||||||
<section className="panel first-panel">
|
<section className="panel first-panel">
|
||||||
@ -106,7 +147,7 @@
|
|||||||
{{ t("home.section3.features.data.title") }}
|
{{ t("home.section3.features.data.title") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-[#455363] text-[72px] mt-[72px] line-4 max-w-[1024px] break-words"
|
class="text-[#455363] text-[72px] line-3 mt-[72px] max-w-[1024px] break-words"
|
||||||
>
|
>
|
||||||
{{ t("home.section3.features.data.desc") }}
|
{{ t("home.section3.features.data.desc") }}
|
||||||
</div>
|
</div>
|
||||||
@ -124,7 +165,7 @@
|
|||||||
{{ t("home.section3.features.ai.title") }}
|
{{ t("home.section3.features.ai.title") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-[#455363] text-[72px] mt-[72px] line-4 max-w-[1024px] break-words"
|
class="text-[#455363] text-[72px] line-3 mt-[72px] max-w-[1024px] break-words"
|
||||||
>
|
>
|
||||||
{{ t("home.section3.features.ai.desc") }}
|
{{ t("home.section3.features.ai.desc") }}
|
||||||
</div>
|
</div>
|
||||||
@ -142,7 +183,7 @@
|
|||||||
{{ t("home.section3.features.cloud.title") }}
|
{{ t("home.section3.features.cloud.title") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-[#455363] text-[72px] mt-[72px] line-4 max-w-[1024px] break-words"
|
class="text-[#455363] text-[72px] line-3 mt-[72px] max-w-[1024px] break-words"
|
||||||
>
|
>
|
||||||
{{ t("home.section3.features.cloud.desc") }}
|
{{ t("home.section3.features.cloud.desc") }}
|
||||||
</div>
|
</div>
|
||||||
@ -160,7 +201,7 @@
|
|||||||
{{ t("home.section3.features.cooperation.title") }}
|
{{ t("home.section3.features.cooperation.title") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-[#455363] text-[72px] mt-[72px] line-4 max-w-[1024px] break-words"
|
class="text-[#455363] text-[72px] line-3 mt-[72px] max-w-[1024px] break-words"
|
||||||
>
|
>
|
||||||
{{ t("home.section3.features.cooperation.desc") }}
|
{{ t("home.section3.features.cooperation.desc") }}
|
||||||
</div>
|
</div>
|
||||||
@ -178,7 +219,7 @@
|
|||||||
{{ t("home.section3.features.promotion.title") }}
|
{{ t("home.section3.features.promotion.title") }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-[#455363] text-[72px] mt-[72px] line-4 max-w-[1024px] break-words"
|
class="text-[#455363] text-[72px] line-3 mt-[72px] max-w-[1024px] break-words"
|
||||||
>
|
>
|
||||||
{{ t("home.section3.features.promotion.desc") }}
|
{{ t("home.section3.features.promotion.desc") }}
|
||||||
</div>
|
</div>
|
||||||
@ -307,6 +348,14 @@ const scrollThreshold = 50; // 添加滚动阈值
|
|||||||
let lastScrollTime = 0; // 添加最后滚动时间记录
|
let lastScrollTime = 0; // 添加最后滚动时间记录
|
||||||
const scrollDownVisible = ref(true);
|
const scrollDownVisible = ref(true);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
|
|
||||||
// 导入所有语言的轮播图
|
// 导入所有语言的轮播图
|
||||||
const carouselImages = {
|
const carouselImages = {
|
||||||
@ -338,6 +387,12 @@ const carouselImages = {
|
|||||||
new URL("@/assets/image/home/375/zh-TW/carousel-4.jpg", import.meta.url)
|
new URL("@/assets/image/home/375/zh-TW/carousel-4.jpg", import.meta.url)
|
||||||
.href,
|
.href,
|
||||||
],
|
],
|
||||||
|
de: [
|
||||||
|
new URL("@/assets/image/home/375/de/carousel-1.png", import.meta.url).href,
|
||||||
|
new URL("@/assets/image/home/375/de/carousel-2.png", import.meta.url).href,
|
||||||
|
new URL("@/assets/image/home/375/de/carousel-3.png", import.meta.url).href,
|
||||||
|
new URL("@/assets/image/home/375/de/carousel-4.png", import.meta.url).href,
|
||||||
|
],
|
||||||
};
|
};
|
||||||
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
const currentCarouselImages = computed(() => {
|
const currentCarouselImages = computed(() => {
|
||||||
@ -896,6 +951,38 @@ watch(
|
|||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -912,7 +999,7 @@ watch(
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
padding: 0 138px;
|
padding: 0 102px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
.logo {
|
.logo {
|
||||||
@ -924,9 +1011,8 @@ watch(
|
|||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 128px;
|
gap: 77px;
|
||||||
margin-right: 32px;
|
margin-left: 67px;
|
||||||
margin-left: 60px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-item {
|
.tab-item {
|
||||||
@ -934,6 +1020,7 @@ watch(
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 61px;
|
font-size: 61px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
max-width: 251px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
@ -946,7 +1033,11 @@ watch(
|
|||||||
color: #8b59fa;
|
color: #8b59fa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
white-space: nowrap; /* 防止文本换行 */
|
||||||
|
overflow: hidden; /* 隐藏溢出内容 */
|
||||||
|
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||||
|
}
|
||||||
.title {
|
.title {
|
||||||
font-size: 113px;
|
font-size: 113px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -1189,17 +1280,6 @@ watch(
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-track {
|
|
||||||
display: flex;
|
|
||||||
will-change: transform;
|
|
||||||
cursor: grab;
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-item {
|
.carousel-item {
|
||||||
width: 785px;
|
width: 785px;
|
||||||
margin-right: 73px;
|
margin-right: 73px;
|
||||||
@ -1242,12 +1322,106 @@ watch(
|
|||||||
.panel:last-child .parallax-bg {
|
.panel:last-child .parallax-bg {
|
||||||
height: 100%; // 第四个面板的背景初始高度
|
height: 100%; // 第四个面板的背景初始高度
|
||||||
}
|
}
|
||||||
.line-4 {
|
.line-3 {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 4;
|
-webkit-line-clamp: 3;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
max-height: calc(1.5em * 4);
|
max-height: calc(1.5em * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 67px 77px 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 82px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 72px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 113px 77px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 46px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 82px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -29,8 +29,52 @@
|
|||||||
>
|
>
|
||||||
{{ t("home.nav.businessintroduction") }}
|
{{ t("home.nav.businessintroduction") }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-item" @click="handleLanguageChange">
|
||||||
|
{{ currentLanguageLabel }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/768/icon-language.png"
|
||||||
|
alt="language"
|
||||||
|
class="w-[18px] ml-[13px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<!-- 语言选择模态框 - 使用纯div实现 -->
|
||||||
|
<div
|
||||||
|
v-if="showLanguageModal"
|
||||||
|
class="language-modal"
|
||||||
|
@touchmove.prevent.stop
|
||||||
|
>
|
||||||
|
<div class="language-modal-backdrop" @click="closeLanguageModal"></div>
|
||||||
|
<div class="language-modal-content">
|
||||||
|
<div class="modal-header font-semibold flex items-center">
|
||||||
|
{{ t("home.nav.please_select") }}
|
||||||
|
<img
|
||||||
|
src="@/assets/image/home/375/icon-close.png"
|
||||||
|
alt="close"
|
||||||
|
class="close-btn w-[51px]"
|
||||||
|
@click="closeLanguageModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-body" @wheel.stop @touchmove.stop>
|
||||||
|
<div
|
||||||
|
v-for="option in languageOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="language-option"
|
||||||
|
:class="{ active: selectedLanguage === option.value }"
|
||||||
|
@click="selectedLanguage = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="language-modal-footer">
|
||||||
|
<button class="confirm-btn" @click="confirmLanguageChange">
|
||||||
|
{{ t("home.nav.confirm_select") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<main ref="main">
|
<main ref="main">
|
||||||
<div class="scroll-down" :class="{ hide: !scrollDownVisible }">
|
<div class="scroll-down" :class="{ hide: !scrollDownVisible }">
|
||||||
{{ t("home.scroll.tip") }}
|
{{ t("home.scroll.tip") }}
|
||||||
@ -58,10 +102,14 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="text-[#10253E] text-[90px] leading-[115px] font-semibold">
|
<div
|
||||||
|
class="text-[#10253E] text-[90px] leading-[115px] font-semibold px-[40px]"
|
||||||
|
>
|
||||||
{{ t("home.section2.title1") }}
|
{{ t("home.section2.title1") }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[#10253E] text-[90px] leading-[115px] font-semibold">
|
<div
|
||||||
|
class="text-[#10253E] text-[90px] leading-[115px] font-semibold px-[40px]"
|
||||||
|
>
|
||||||
{{ t("home.section2.title2") }}
|
{{ t("home.section2.title2") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -270,9 +318,10 @@ import gsap from "gsap";
|
|||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import { useHome } from "@/store/home/index.js";
|
import { useHome } from "@/store/home/index.js";
|
||||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||||
import { useI18n } from "vue-i18n";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
|
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { transitionState } = useTransitionComposable();
|
const { transitionState } = useTransitionComposable();
|
||||||
const main = ref();
|
const main = ref();
|
||||||
@ -284,7 +333,14 @@ let isScrolling = false; // 添加滚动状态标记
|
|||||||
const scrollThreshold = 50; // 添加滚动阈值
|
const scrollThreshold = 50; // 添加滚动阈值
|
||||||
let lastScrollTime = 0; // 添加最后滚动时间记录
|
let lastScrollTime = 0; // 添加最后滚动时间记录
|
||||||
const scrollDownVisible = ref(true);
|
const scrollDownVisible = ref(true);
|
||||||
const { t } = useI18n();
|
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||||
|
const {
|
||||||
|
languageOptions,
|
||||||
|
currentLanguageLabel,
|
||||||
|
changeLanguage,
|
||||||
|
initLanguage,
|
||||||
|
currentLang,
|
||||||
|
} = useLanguage();
|
||||||
|
|
||||||
// 导入所有语言的轮播图
|
// 导入所有语言的轮播图
|
||||||
const carouselImages = {
|
const carouselImages = {
|
||||||
@ -316,12 +372,15 @@ const carouselImages = {
|
|||||||
new URL("@/assets/image/home/768/zh-TW/carousel-4.jpg", import.meta.url)
|
new URL("@/assets/image/home/768/zh-TW/carousel-4.jpg", import.meta.url)
|
||||||
.href,
|
.href,
|
||||||
],
|
],
|
||||||
|
de: [
|
||||||
|
new URL("@/assets/image/home/768/de/carousel-1.png", import.meta.url).href,
|
||||||
|
new URL("@/assets/image/home/768/de/carousel-2.png", import.meta.url).href,
|
||||||
|
new URL("@/assets/image/home/768/de/carousel-3.png", import.meta.url).href,
|
||||||
|
new URL("@/assets/image/home/768/de/carousel-4.png", import.meta.url).href,
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
const currentLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
const currentCarouselImages = computed(() => {
|
|
||||||
return carouselImages[currentLanguage.value] || carouselImages.zh;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加语言变化的监听
|
// 添加语言变化的监听
|
||||||
watch(
|
watch(
|
||||||
@ -334,6 +393,10 @@ watch(
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const currentCarouselImages = computed(() => {
|
||||||
|
return carouselImages[currentLanguage.value] || carouselImages.zh;
|
||||||
|
});
|
||||||
|
|
||||||
const handleTabClick = (tab) => {
|
const handleTabClick = (tab) => {
|
||||||
currentTab.value = tab;
|
currentTab.value = tab;
|
||||||
router.push("/" + tab);
|
router.push("/" + tab);
|
||||||
@ -947,6 +1010,38 @@ watch(
|
|||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 语言选择模态框相关变量
|
||||||
|
const showLanguageModal = ref(false);
|
||||||
|
// 默认选中的语言,从localStorage获取,如果没有则默认为简体中文
|
||||||
|
const selectedLanguage = ref(localStorage.getItem("language") || "zh");
|
||||||
|
|
||||||
|
// 打开语言选择模态框
|
||||||
|
const handleLanguageChange = () => {
|
||||||
|
showLanguageModal.value = true;
|
||||||
|
// 打开时设置当前选中的语言
|
||||||
|
selectedLanguage.value = localStorage.getItem("language") || "zh";
|
||||||
|
// 禁止背景滚动
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确认语言选择
|
||||||
|
const confirmLanguageChange = () => {
|
||||||
|
changeLanguage(selectedLanguage.value);
|
||||||
|
// 更新轮播图
|
||||||
|
currentLanguage.value = selectedLanguage.value;
|
||||||
|
// 关闭模态框
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭语言选择模态框
|
||||||
|
const closeLanguageModal = () => {
|
||||||
|
showLanguageModal.value = false;
|
||||||
|
// 恢复背景滚动
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -1243,17 +1338,6 @@ watch(
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-track {
|
|
||||||
display: flex;
|
|
||||||
will-change: transform;
|
|
||||||
cursor: grab;
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-item {
|
.carousel-item {
|
||||||
width: 785px;
|
width: 785px;
|
||||||
margin-right: 73px;
|
margin-right: 73px;
|
||||||
@ -1291,4 +1375,99 @@ watch(
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
max-height: calc(1.5em * 1);
|
max-height: calc(1.5em * 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 语言选择模态框样式 */
|
||||||
|
.language-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
touch-action: none; /* 防止触摸事件影响背景 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 90vh; /* 最大高度为视口高度的90% */
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 1002;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden; /* 内容溢出隐藏 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding: 33px 38px 55px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #000000;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0; /* 不允许头部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-body {
|
||||||
|
padding: 10px 0;
|
||||||
|
overflow-y: auto; /* 只有内容区域可滚动 */
|
||||||
|
-webkit-overflow-scrolling: touch; /* 为iOS设备提供平滑滚动 */
|
||||||
|
flex: 1; /* 内容区域填充剩余空间 */
|
||||||
|
overscroll-behavior: contain; /* 阻止滚动穿透 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-option:hover,
|
||||||
|
.language-option.active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #8b59f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-modal-footer {
|
||||||
|
padding: 40px 38px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0; /* 不允许底部收缩 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b59f7;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 23px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:hover {
|
||||||
|
background-color: #7a48e6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|