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: {
|
||||
home: 'Startseite',
|
||||
company: 'Unternehmensprofil',
|
||||
businessintroduction: 'Geschäftsvorstellung'
|
||||
businessintroduction: 'Geschäftsvorstellung',
|
||||
please_select: 'Bitte auswählen',
|
||||
confirm_select: 'Bestätigen Sie die Auswahl'
|
||||
},
|
||||
scroll: {
|
||||
tip: 'Nach unten scrollen'
|
||||
|
@ -15,7 +15,9 @@ export default {
|
||||
nav: {
|
||||
home: 'Home',
|
||||
company: 'Company Overview',
|
||||
businessintroduction: 'Business Introduction'
|
||||
businessintroduction: 'Business Introduction',
|
||||
please_select: 'Please Select',
|
||||
confirm_select: 'Confirm Selection'
|
||||
},
|
||||
scroll: {
|
||||
tip: 'Scroll Down'
|
||||
|
@ -15,7 +15,9 @@ export default {
|
||||
"nav": {
|
||||
"home": "ホーム",
|
||||
"company": "会社概要",
|
||||
"businessintroduction": "業務紹介"
|
||||
"businessintroduction": "業務紹介",
|
||||
"please_select": "選択してください",
|
||||
"confirm_select": "確認選択"
|
||||
},
|
||||
"scroll": {
|
||||
"tip": "下にスクロール"
|
||||
|
@ -15,7 +15,9 @@ export default {
|
||||
"nav": {
|
||||
"home": "首頁",
|
||||
"company": "公司概況",
|
||||
"businessintroduction": "業務介紹"
|
||||
"businessintroduction": "業務介紹",
|
||||
"please_select": "請選擇",
|
||||
"confirm_select": "確認選擇"
|
||||
},
|
||||
"scroll": {
|
||||
"tip": "向下滑動"
|
||||
|
@ -15,7 +15,10 @@ export default {
|
||||
nav: {
|
||||
home: '首页',
|
||||
company: '公司概况',
|
||||
businessintroduction: '业务介绍'
|
||||
businessintroduction: '业务介绍',
|
||||
language_change: '语言切换',
|
||||
please_select: '请选择',
|
||||
confirm_select: '确认选择'
|
||||
},
|
||||
scroll: {
|
||||
tip: '向下滑动'
|
||||
|
@ -8,28 +8,69 @@
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ $t("home.nav.home") }}
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ $t("home.nav.company") }}
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === '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>
|
||||
</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>
|
||||
<section class="relative pb-[1020px]">
|
||||
<div class="absolute top-[0px] right-[0px]">
|
||||
@ -541,20 +582,27 @@
|
||||
|
||||
<script setup>
|
||||
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 { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
// Define component custom events
|
||||
defineEmits(["sendCode"]);
|
||||
|
||||
// Register ScrollTrigger plugin
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { transitionState } = useTransitionComposable();
|
||||
|
||||
const moveRefs = ref(
|
||||
@ -564,7 +612,14 @@ const moveRefs = ref(
|
||||
);
|
||||
const { currentTab } = useHome();
|
||||
let ctx;
|
||||
|
||||
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||
const {
|
||||
languageOptions,
|
||||
currentLanguageLabel,
|
||||
changeLanguage,
|
||||
initLanguage,
|
||||
currentLang,
|
||||
} = useLanguage();
|
||||
// Import images
|
||||
import imageshow3 from "@/assets/image/businessintroduction/375/imageshow-3.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
|
||||
onMounted(() => {
|
||||
initLanguage();
|
||||
ctx = gsap.context(() => {
|
||||
moveRefs.value.forEach((moveRef, index) => {
|
||||
if (moveRef.value) {
|
||||
@ -678,6 +734,48 @@ const challengeItems = computed(() => [
|
||||
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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -694,7 +792,7 @@ const challengeItems = computed(() => [
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 138px;
|
||||
padding: 0 102px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.logo {
|
||||
@ -706,9 +804,8 @@ const challengeItems = computed(() => [
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 128px;
|
||||
margin-right: 32px;
|
||||
margin-left: 60px;
|
||||
gap: 77px;
|
||||
margin-left: 67px;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
@ -716,6 +813,7 @@ const challengeItems = computed(() => [
|
||||
align-items: center;
|
||||
font-size: 61px;
|
||||
color: #000000;
|
||||
max-width: 251px;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease;
|
||||
padding: 4px 8px;
|
||||
@ -728,6 +826,11 @@ const challengeItems = computed(() => [
|
||||
color: #8b59fa;
|
||||
}
|
||||
}
|
||||
.ellipsis {
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 113px;
|
||||
@ -832,4 +935,98 @@ const challengeItems = computed(() => [
|
||||
height: 100%;
|
||||
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>
|
||||
|
@ -12,24 +12,67 @@
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ $t("home.nav.home") }}
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ $t("home.nav.company") }}
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === '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>
|
||||
</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>
|
||||
<section className="relative pb-[900px] section-first bg-[#F8F9FF]">
|
||||
<div class="pt-[718px] relative">
|
||||
@ -464,13 +507,20 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
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 { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||
const {
|
||||
languageOptions,
|
||||
currentLanguageLabel,
|
||||
changeLanguage,
|
||||
initLanguage,
|
||||
currentLang,
|
||||
} = useLanguage();
|
||||
|
||||
// 定义组件的自定义事件
|
||||
defineEmits(["sendCode"]);
|
||||
@ -478,6 +528,7 @@ defineEmits(["sendCode"]);
|
||||
// 注册 ScrollTrigger 插件
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -779,4 +875,98 @@ const goToSection = (i) => {
|
||||
text-overflow: ellipsis;
|
||||
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>
|
||||
|
@ -8,28 +8,68 @@
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ $t("home.nav.home") }}
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ $t("home.nav.company") }}
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === '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>
|
||||
</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>
|
||||
<section style="background: #ffffff" className="relative">
|
||||
<div class="relative section-first h-[3990px] box-contain pt-[2300px]">
|
||||
@ -432,12 +472,13 @@
|
||||
|
||||
<script setup>
|
||||
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 { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
// 定义组件的自定义事件
|
||||
defineEmits(["sendCode"]);
|
||||
|
||||
@ -453,7 +494,16 @@ const moveRefs = ref(
|
||||
);
|
||||
const { currentTab } = useHome();
|
||||
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 carouselShow2 from "@/assets/image/companyprofil/375/carouselShow-2.png";
|
||||
@ -527,6 +577,7 @@ const handleResize = () => {
|
||||
|
||||
// 监听窗口大小变化
|
||||
onMounted(() => {
|
||||
initLanguage();
|
||||
ctx = gsap.context(() => {
|
||||
moveRefs.value.forEach((moveRef, index) => {
|
||||
if (moveRef.value) {
|
||||
@ -720,8 +771,7 @@ const handleDragEnd = (e) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
|
||||
const handleCarouselClick = (item, event) => {
|
||||
// 检查事件类型是否为点击
|
||||
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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -752,7 +844,7 @@ const handleCarouselClick = (item, event) => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 138px;
|
||||
padding: 0 102px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.logo {
|
||||
@ -764,16 +856,17 @@ const handleCarouselClick = (item, event) => {
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 128px;
|
||||
margin-right: 32px;
|
||||
margin-left: 60px;
|
||||
gap: 77px;
|
||||
margin-left: 67px;
|
||||
}
|
||||
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 61px;
|
||||
color: #000000;
|
||||
max-width: 251px;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease;
|
||||
padding: 4px 8px;
|
||||
@ -786,7 +879,11 @@ const handleCarouselClick = (item, event) => {
|
||||
color: #8b59fa;
|
||||
}
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||
}
|
||||
.title {
|
||||
font-size: 113px;
|
||||
font-weight: 600;
|
||||
@ -899,4 +996,98 @@ const handleCarouselClick = (item, event) => {
|
||||
height: 100%;
|
||||
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>
|
||||
|
@ -12,24 +12,67 @@
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ $t("home.nav.home") }}
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ $t("home.nav.company") }}
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === '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>
|
||||
</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>
|
||||
<section style="background: #ffffff" className="relative">
|
||||
<div
|
||||
@ -409,15 +452,21 @@
|
||||
|
||||
<script setup>
|
||||
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 { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
import { useTransitionComposable } from "@/composables/transition-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
// 初始化 i18n
|
||||
const { t } = useI18n();
|
||||
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||
const {
|
||||
languageOptions,
|
||||
currentLanguageLabel,
|
||||
changeLanguage,
|
||||
initLanguage,
|
||||
currentLang,
|
||||
} = useLanguage();
|
||||
|
||||
// 定义组件的自定义事件
|
||||
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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -886,4 +980,98 @@ const handleCarouselClick = (item, event) => {
|
||||
width: 1px;
|
||||
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>
|
||||
|
@ -8,28 +8,68 @@
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ $t("home.nav.home") }}
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ $t("home.nav.company") }}
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis""
|
||||
:class="{ active: currentTab === '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>
|
||||
</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>
|
||||
<section
|
||||
className="section-first"
|
||||
@ -224,10 +264,20 @@ import {
|
||||
reactive,
|
||||
nextTick,
|
||||
onBeforeMount,
|
||||
watch,
|
||||
} from "vue";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
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({
|
||||
pageTitleNo: "",
|
||||
});
|
||||
@ -238,13 +288,57 @@ const route = useRoute();
|
||||
onBeforeMount(() => {
|
||||
state.pageTitleNo = route.query.titleNo;
|
||||
});
|
||||
onMounted(() => {});
|
||||
onMounted(() => {
|
||||
initLanguage();
|
||||
});
|
||||
onUnmounted(() => {});
|
||||
|
||||
const handleTabClick = (tab) => {
|
||||
currentTab.value = 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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -253,7 +347,6 @@ const handleTabClick = (tab) => {
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 260px;
|
||||
@ -262,7 +355,7 @@ const handleTabClick = (tab) => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 138px;
|
||||
padding: 0 102px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.logo {
|
||||
@ -274,13 +367,17 @@ const handleTabClick = (tab) => {
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 128px;
|
||||
margin-right: 32px;
|
||||
gap: 77px;
|
||||
margin-left: 67px;
|
||||
}
|
||||
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 61px;
|
||||
color: #000000;
|
||||
max-width: 251px;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease;
|
||||
padding: 4px 8px;
|
||||
@ -293,6 +390,12 @@ const handleTabClick = (tab) => {
|
||||
color: #8b59fa;
|
||||
}
|
||||
}
|
||||
.ellipsis {
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 113px;
|
||||
font-weight: 600;
|
||||
@ -323,4 +426,98 @@ const handleTabClick = (tab) => {
|
||||
height: 100%;
|
||||
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>
|
||||
|
@ -12,24 +12,67 @@
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ $t("home.nav.home") }}
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ $t("home.nav.company") }}
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === '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>
|
||||
</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>
|
||||
<section
|
||||
className="section-first"
|
||||
@ -223,6 +266,7 @@ import {
|
||||
onMounted,
|
||||
reactive,
|
||||
nextTick,
|
||||
watch,
|
||||
onBeforeMount,
|
||||
} from "vue";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
@ -230,9 +274,20 @@ const state = reactive({
|
||||
pageTitleNo: "",
|
||||
});
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { currentTab } = useHome();
|
||||
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||
const {
|
||||
languageOptions,
|
||||
currentLanguageLabel,
|
||||
changeLanguage,
|
||||
initLanguage,
|
||||
currentLang,
|
||||
} = useLanguage();
|
||||
|
||||
onBeforeMount(() => {
|
||||
state.pageTitleNo = route.query.titleNo;
|
||||
});
|
||||
@ -242,6 +297,51 @@ const handleTabClick = (tab) => {
|
||||
currentTab.value = 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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -320,4 +420,98 @@ const handleTabClick = (tab) => {
|
||||
width: 1px;
|
||||
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>
|
||||
|
@ -6,30 +6,71 @@
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis"
|
||||
:class="{ active: currentTab === 'home' }"
|
||||
@click="handleTabClick('home')"
|
||||
>
|
||||
{{ t("home.nav.home") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis"
|
||||
:class="{ active: currentTab === 'companyprofil' }"
|
||||
@click="handleTabClick('companyprofil')"
|
||||
>
|
||||
{{ t("home.nav.company") }}
|
||||
</div>
|
||||
<div
|
||||
class="tab-item"
|
||||
class="tab-item ellipsis"
|
||||
:class="{ active: currentTab === 'businessintroduction' }"
|
||||
@click="handleTabClick('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>
|
||||
</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">
|
||||
<div class="scroll-down" :class="{ hide: !scrollDownVisible }">
|
||||
<div class="scroll-down ellipsis" :class="{ hide: !scrollDownVisible }">
|
||||
{{ t("home.scroll.tip") }}
|
||||
</div>
|
||||
<section className="panel first-panel">
|
||||
@ -106,7 +147,7 @@
|
||||
{{ t("home.section3.features.data.title") }}
|
||||
</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") }}
|
||||
</div>
|
||||
@ -124,7 +165,7 @@
|
||||
{{ t("home.section3.features.ai.title") }}
|
||||
</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") }}
|
||||
</div>
|
||||
@ -142,7 +183,7 @@
|
||||
{{ t("home.section3.features.cloud.title") }}
|
||||
</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") }}
|
||||
</div>
|
||||
@ -160,7 +201,7 @@
|
||||
{{ t("home.section3.features.cooperation.title") }}
|
||||
</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") }}
|
||||
</div>
|
||||
@ -178,7 +219,7 @@
|
||||
{{ t("home.section3.features.promotion.title") }}
|
||||
</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") }}
|
||||
</div>
|
||||
@ -307,6 +348,14 @@ const scrollThreshold = 50; // 添加滚动阈值
|
||||
let lastScrollTime = 0; // 添加最后滚动时间记录
|
||||
const scrollDownVisible = ref(true);
|
||||
const { t } = useI18n();
|
||||
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||
const {
|
||||
languageOptions,
|
||||
currentLanguageLabel,
|
||||
changeLanguage,
|
||||
initLanguage,
|
||||
currentLang,
|
||||
} = useLanguage();
|
||||
|
||||
// 导入所有语言的轮播图
|
||||
const carouselImages = {
|
||||
@ -338,6 +387,12 @@ const carouselImages = {
|
||||
new URL("@/assets/image/home/375/zh-TW/carousel-4.jpg", import.meta.url)
|
||||
.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 currentCarouselImages = computed(() => {
|
||||
@ -896,6 +951,38 @@ watch(
|
||||
},
|
||||
{ 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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -912,7 +999,7 @@ watch(
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 138px;
|
||||
padding: 0 102px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.logo {
|
||||
@ -924,9 +1011,8 @@ watch(
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 128px;
|
||||
margin-right: 32px;
|
||||
margin-left: 60px;
|
||||
gap: 77px;
|
||||
margin-left: 67px;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
@ -934,6 +1020,7 @@ watch(
|
||||
align-items: center;
|
||||
font-size: 61px;
|
||||
color: #000000;
|
||||
max-width: 251px;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s ease;
|
||||
padding: 4px 8px;
|
||||
@ -946,7 +1033,11 @@ watch(
|
||||
color: #8b59fa;
|
||||
}
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: ellipsis; /* 文本溢出时显示省略号 */
|
||||
}
|
||||
.title {
|
||||
font-size: 113px;
|
||||
font-weight: 600;
|
||||
@ -1189,17 +1280,6 @@ watch(
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.carousel-track {
|
||||
display: flex;
|
||||
will-change: transform;
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
width: 785px;
|
||||
margin-right: 73px;
|
||||
@ -1242,12 +1322,106 @@ watch(
|
||||
.panel:last-child .parallax-bg {
|
||||
height: 100%; // 第四个面板的背景初始高度
|
||||
}
|
||||
.line-4 {
|
||||
.line-3 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
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>
|
||||
|
@ -29,8 +29,52 @@
|
||||
>
|
||||
{{ 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>
|
||||
</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">
|
||||
<div class="scroll-down" :class="{ hide: !scrollDownVisible }">
|
||||
{{ t("home.scroll.tip") }}
|
||||
@ -58,10 +102,14 @@
|
||||
/>
|
||||
</div>
|
||||
<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") }}
|
||||
</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") }}
|
||||
</div>
|
||||
</div>
|
||||
@ -270,9 +318,10 @@ import gsap from "gsap";
|
||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import { useHome } from "@/store/home/index.js";
|
||||
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 { transitionState } = useTransitionComposable();
|
||||
const main = ref();
|
||||
@ -284,7 +333,14 @@ let isScrolling = false; // 添加滚动状态标记
|
||||
const scrollThreshold = 50; // 添加滚动阈值
|
||||
let lastScrollTime = 0; // 添加最后滚动时间记录
|
||||
const scrollDownVisible = ref(true);
|
||||
const { t } = useI18n();
|
||||
import { useLanguage } from "@/utils/changeLanguage.js";
|
||||
const {
|
||||
languageOptions,
|
||||
currentLanguageLabel,
|
||||
changeLanguage,
|
||||
initLanguage,
|
||||
currentLang,
|
||||
} = useLanguage();
|
||||
|
||||
// 导入所有语言的轮播图
|
||||
const carouselImages = {
|
||||
@ -316,12 +372,15 @@ const carouselImages = {
|
||||
new URL("@/assets/image/home/768/zh-TW/carousel-4.jpg", import.meta.url)
|
||||
.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 currentCarouselImages = computed(() => {
|
||||
return carouselImages[currentLanguage.value] || carouselImages.zh;
|
||||
});
|
||||
|
||||
// 添加语言变化的监听
|
||||
watch(
|
||||
@ -334,6 +393,10 @@ watch(
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const currentCarouselImages = computed(() => {
|
||||
return carouselImages[currentLanguage.value] || carouselImages.zh;
|
||||
});
|
||||
|
||||
const handleTabClick = (tab) => {
|
||||
currentTab.value = tab;
|
||||
router.push("/" + tab);
|
||||
@ -947,6 +1010,38 @@ watch(
|
||||
},
|
||||
{ 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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -1243,17 +1338,6 @@ watch(
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.carousel-track {
|
||||
display: flex;
|
||||
will-change: transform;
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
width: 785px;
|
||||
margin-right: 73px;
|
||||
@ -1291,4 +1375,99 @@ watch(
|
||||
line-height: 1.5;
|
||||
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>
|
||||
|