officialWebsite/src/views/companyprofil/size1440/index.vue

831 lines
23 KiB
Vue
Raw Normal View History

2025-02-19 11:04:19 +00:00
<script setup>
2025-02-22 11:36:52 +00:00
import {
onUnmounted,
ref,
watch,
reactive,
onMounted
} 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 { useRouter } from "vue-router";
import { NDivider, NPopselect } from "naive-ui";
import { useLanguage } from "@/utils/changeLanguage.js";
2025-02-22 11:36:52 +00:00
// 注册 ScrollTrigger 插件
gsap.registerPlugin(ScrollTrigger);
const { currentTab } = useHome();
const router = useRouter();
const { transitionState } = useTransitionComposable();
const main = ref();
let ctx;
const handleTabClick = (tab) => {
currentTab.value = tab;
router.push("/" + tab);
};
const {
languageOptions,
currentLanguage,
currentLanguageLabel,
changeLanguage,
initLanguage,
currentLang,
currentBannerImages,
t
} = useLanguage();
2025-02-22 11:36:52 +00:00
// 向前滑动
const handlePrev = () => {
if (!carouselTrack.value) return;
carouselTrack.value.style.transition = "transform 0.5s ease-in-out";
currentIndex.value--;
if (currentIndex.value < 0) {
currentIndex.value = state.marqueeArr.length - 1;
}
};
// 向后滑动
const handleNext = () => {
if (!carouselTrack.value) return;
carouselTrack.value.style.transition = "transform 0.5s ease-in-out";
currentIndex.value++;
if (currentIndex.value >= state.marqueeArr.length) {
currentIndex.value = 0;
}
};
// 添加滑动相关的状态
const isDragging = ref(false);
const startX = ref(0);
const scrollLeft = ref(0);
// 处理鼠标/触摸按下事件
const handleDragStart = (e) => {
isDragging.value = true;
startX.value = e.type === "mousedown" ? e.pageX : e.touches[0].pageX;
scrollLeft.value = getSlideOffset();
// 禁用过渡效果,实现平滑拖动
if (carouselTrack.value) {
carouselTrack.value.style.transition = "none";
}
};
// 处理鼠标/触摸移动事件
const handleDragMove = (e) => {
if (!isDragging.value) return;
e.preventDefault();
const x = e.type === "mousemove" ? e.pageX : e.touches[0].pageX;
const walk = startX.value - x;
if (carouselTrack.value) {
carouselTrack.value.style.transform = `translateX(-${
scrollLeft.value + walk
}px)`;
}
};
// 处理鼠标/触摸释放事件
const handleDragEnd = (e) => {
if (!isDragging.value) return;
isDragging.value = false;
if (carouselTrack.value) {
// 恢复过渡效果
carouselTrack.value.style.transition = "transform 0.5s ease-in-out";
const x = e.type === "mouseup" ? e.pageX : e.changedTouches[0].pageX;
const walk = startX.value - x;
// 获取单个项目的宽度
const firstItem = carouselTrack.value.querySelector(".carousel-item");
if (!firstItem) return;
const itemWidth = firstItem.offsetWidth;
const itemMargin = parseInt(window.getComputedStyle(firstItem).marginRight);
const totalWidth = itemWidth + itemMargin;
// 根据滑动距离决定是否切换到下一个/上一个
if (Math.abs(walk) > totalWidth / 3) {
if (walk > 0) {
handleNext();
} else {
handlePrev();
}
} else {
// 如果滑动距离不够,回到当前位置
carouselTrack.value.style.transform = `translateX(-${getSlideOffset()}px)`;
}
}
};
// 导入图片
import carouselShow1 from "@/assets/image/companyprofil/768/carouselShow-1.png";
import carouselShow2 from "@/assets/image/companyprofil/768/carouselShow-2.png";
import carouselShow3 from "@/assets/image/companyprofil/768/carouselShow-3.png";
import carouselShow4 from "@/assets/image/companyprofil/768/carouselShow-4.png";
import carouselShow5 from "@/assets/image/companyprofil/768/carouselShow-5.png";
const state = reactive({
marqueeArr: [
{
title: t("companyprofil.news.carousel.item1.title"),
subTitle: t("companyprofil.news.carousel.item1.desc"),
imgUrl: carouselShow1,
titleNo: 1,
2025-02-22 11:36:52 +00:00
},
{
title: t("companyprofil.news.carousel.item2.title"),
subTitle: t("companyprofil.news.carousel.item2.desc"),
imgUrl: carouselShow2,
titleNo: 2,
2025-02-22 11:36:52 +00:00
},
{
title: t("companyprofil.news.carousel.item3.title"),
subTitle: t("companyprofil.news.carousel.item3.desc"),
imgUrl: carouselShow3,
titleNo: 3,
2025-02-22 11:36:52 +00:00
},
{
title: t("companyprofil.news.carousel.item4.title"),
subTitle: t("companyprofil.news.carousel.item4.desc"),
imgUrl: carouselShow4,
titleNo: 4,
2025-02-22 11:36:52 +00:00
},
{
title: t("companyprofil.news.carousel.item5.title"),
subTitle: t("companyprofil.news.carousel.item5.desc"),
imgUrl: carouselShow5,
titleNo: 5,
2025-02-22 11:36:52 +00:00
},
],
});
const carouselTrack = ref(null);
const currentIndex = ref(0);
const getVisibleItems = () => {
return state.marqueeArr;
};
// 计算实际滑动距离
const getSlideOffset = () => {
if (!carouselTrack.value) return 0;
const firstItem = carouselTrack.value.querySelector(".carousel-item");
if (!firstItem) return 0;
const itemWidth = firstItem.offsetWidth;
const itemMargin = parseInt(window.getComputedStyle(firstItem).marginRight);
const totalWidth = itemWidth + itemMargin;
return currentIndex.value * totalWidth;
};
// 定义 resize 处理函数
const handleResize = () => {
if (carouselTrack.value) {
carouselTrack.value.style.transform = `translateX(-${getSlideOffset()}px)`;
}
};
const handleCarouselClick = (item, event) => {
// 检查事件类型是否为点击
if (event.type === "click") {
event.stopPropagation(); // 阻止事件传播
event.preventDefault(); // 阻止默认行为
console.log(item);
router.push({
path: "/companyprofildetail",
query: {
titleNo: item.titleNo ,
2025-02-22 11:36:52 +00:00
},
});
}
};
onMounted(() => {
window.scrollTo(0, 0);
2025-02-22 12:17:12 +00:00
2025-02-26 07:30:41 +00:00
// 添加延迟确保DOM完全渲染并且滚动位置重置
setTimeout(() => {
2025-02-22 12:17:12 +00:00
ctx = gsap.context((self) => {
// Text animations from left
gsap.utils.toArray(".text-animate").forEach((text) => {
gsap.from(text, {
x: -100,
opacity: 0,
duration: 1,
scrollTrigger: {
trigger: text,
start: "top 80%",
end: "top 50%",
toggleActions: "play none none reverse",
2025-02-26 07:30:41 +00:00
// 添加这两个属性来控制初始状态
immediateRender: false, // 防止立即渲染
once: false, // 允许重复触发
2025-02-22 12:17:12 +00:00
},
});
});
// Image animations from right
gsap.utils.toArray(".image-animate").forEach((image) => {
gsap.from(image, {
x: 100,
opacity: 0,
duration: 1,
scrollTrigger: {
trigger: image,
start: "top 80%",
end: "top 50%",
toggleActions: "play none none reverse",
2025-02-26 07:30:41 +00:00
immediateRender: false,
once: false,
2025-02-22 12:17:12 +00:00
},
});
});
// 轮播卡片上升动画
gsap.from(".carousel-item", {
y: 100,
opacity: 0,
duration: 1.5,
stagger: 0.4,
scrollTrigger: {
trigger: ".carousel-container",
start: "top 70%",
end: "top 30%",
scrub: 2,
toggleActions: "restart pause reverse pause",
2025-02-26 07:30:41 +00:00
immediateRender: false,
once: false,
2025-02-22 12:17:12 +00:00
},
});
2025-02-26 07:30:41 +00:00
// 强制刷新ScrollTrigger以正确计算位置
ScrollTrigger.refresh();
2025-02-22 12:17:12 +00:00
}, main.value);
2025-02-26 07:30:41 +00:00
}, 100); // 短暂延迟确保DOM已渲染
2025-02-22 11:36:52 +00:00
});
onUnmounted(() => {
ctx?.revert(); // <- Easy Cleanup!
});
2025-02-19 11:04:19 +00:00
</script>
2025-02-22 11:36:52 +00:00
2025-02-19 11:04:19 +00:00
<template>
2025-02-22 11:36:52 +00:00
<header className="header">
<div class="logo">
<img src="@/assets/image/logo.png" alt="logo" />
</div>
<div class="tabs">
<div
class="tab-item"
:class="{
active: currentTab === 'home',
}"
@click="handleTabClick('home')"
>
{{ t("home.nav.home") }}
</div>
<div
class="tab-item"
:class="{
active: currentTab === 'companyprofil',
}"
@click="handleTabClick('companyprofil')"
>
{{ t("home.nav.company") }}
</div>
<div class="tab-item" :class="{
active:
currentTab === 'businessintroduction',
}" @click="
handleTabClick('businessintroduction')
">
{{ t("home.nav.businessintroduction") }}
</div>
2025-03-15 08:10:26 +00:00
<div class="tab-item" :class="{
active:
currentTab === 'investor',
}" @click="
handleTabClick('investor')
">
{{ t("home.nav.investor") }}
</div>
<div class="tab-item">
<n-popselect v-model:value="currentLanguage" :options="languageOptions"
@update:value="changeLanguage">
<div class="language-display">
{{ currentLanguageLabel }}
<span class="language-arrow"></span>
</div>
</n-popselect>
</div>
2025-02-22 11:36:52 +00:00
</div>
</header>
<main ref="main" class="height-full">
<div class="head relative">
<img src="@/assets/image/gk.png" alt="head" />
<div
class="absolute top-240px left-510px text-[#10253E] text-[54px] font-bold text-animate"
>
{{ t("companyprofil.slogan.title1") }}
</div>
<div
class="absolute top-320px left-510px text-[#10253E] text-[54px] font-bold text-animate"
>
{{ t("companyprofil.slogan.title2") }}
</div>
<div
class="absolute top-420px left-510px text-[#8B59F7] text-[20px] w-[535px] text-animate"
>
{{ t("companyprofil.slogan.desc") }}
</div>
</div>
<n-divider class="divider1" vertical />
<div class="divider2" style=""></div>
<div class="divider3" style=""></div>
<div class="divider4" style=""></div>
<n-divider class="divider5" vertical />
<div class="bg-[#F8F9FF]">
<div
class="content1 relative flex items-center justify-center z-3 pb-[100px] flex-col"
>
<div
class="text-[#8B59F7] text-[16px] absolute top-[-30px] left-[505px] text-animate"
>
{{ t("companyprofil.intro.label") }}
</div>
<div class="pl-[505px] pr-[480px] flex">
<div class="w-[411px] mr-[38px] text-animate">
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[40px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.intro.title1") }}
</div>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[40px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.intro.title2") }}
</div>
<div class="text-[#455363] text-[16px] mt-[56px]">
{{ t("companyprofil.intro.desc") }}
</div>
</div>
<div class="text-[#10253E] text-[20px] image-animate">
<img
class="w-[465px] h-[415px]"
src="@/assets/image/ship.png"
alt="company"
/>
</div>
</div>
</div>
<div
class="content2 relative flex items-center justify-center pt-[168px] bg-[#fff]"
>
<div
class="text-[#8B59F7] text-[16px] absolute top-[129px] left-[505px] text-animate"
>
{{ t("companyprofil.team.label") }}
</div>
<div class="pl-[505px] pr-[490px] flex z-3">
<div class="w-[412px] mr-[40px] text-animate">
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[40px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.team.title1") }}
</div>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[40px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.team.title2") }}
</div>
<div class="mt-[93px]">
<img
class="w-[58px] h-[58px]"
src="@/assets/image/cl.png"
alt="cl"
/>
<div
class="text-[#10253E] text-[18px] mt-[20px] font-bold relative"
>
<n-divider
class="absolute left-[-23px] top-[6px]"
style="background-color: #8b59f7"
vertical
/>{{ t("companyprofil.team.features.global.title") }}
</div>
<div class="text-[#455363] text-[16px]">
{{ t("companyprofil.team.features.global.desc") }}
</div>
</div>
<div class="mt-[68px]">
<img
class="w-[58px] h-[50px]"
src="@/assets/image/heart.png"
alt="cl"
/>
<div
class="text-[#10253E] text-[18px] mt-[20px] font-bold relative"
>
<n-divider
class="absolute left-[-23px] top-[6px]"
style="background-color: #8b59f7"
vertical
/>{{ t("companyprofil.team.features.fans.title") }}
</div>
<div class="text-[#455363] text-[16px]">
{{ t("companyprofil.team.features.fans.desc") }}
</div>
</div>
<div class="mt-[65px]">
<img
class="w-[54px] h-[52px]"
src="@/assets/image/3p.png"
alt="cl"
/>
<div
class="text-[#10253E] text-[18px] mt-[20px] font-bold relative"
>
<n-divider
class="absolute left-[-23px] top-[6px]"
style="background-color: #8b59f7"
vertical
/>{{ t("companyprofil.team.features.talent.title") }}
</div>
<div class="text-[#455363] text-[16px]">
{{ t("companyprofil.team.features.talent.desc") }}
</div>
</div>
</div>
<div class="text-[#455363] text-[16px] flex-1 image-animate">
<div>
{{ t("companyprofil.team.desc") }}
</div>
<img
class="w-[465px] h-[625px] mt-[80px]"
src="@/assets/image/randg.png"
alt="cl"
/>
</div>
</div>
</div>
<div
class="content3 relative bg-[#fff] pt-[185px] pb-[158px] overflow-hidden"
>
<n-divider class="divider1" vertical />
<div class="divider2" style=""></div>
<div class="divider3" style=""></div>
<div class="divider4" style=""></div>
<n-divider class="divider5" vertical />
<img
class="absolute top-[95px] z-3 w-[800px] h-[163px] right-[0px] image-animate"
src="@/assets/image/xlv.png"
alt="cl"
/>
<img class="absolute" src="@/assets/image/xbg.png" alt="cl" />
<div
class="relative pl-[505px] pr-[490px] flex z-3 mt-[300px] z-4 flex-col text-animate"
>
<div class="text-[#8B59F7] text-[16px]">
{{ t("companyprofil.achievement.label") }}
</div>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[40px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.achievement.title") }}
</div>
<div class="text-[#455363] w-[748px] text-[16px] mt-[30px]">
{{ t("companyprofil.achievement.desc") }}
</div>
</div>
<div class="relative pl-[505px] pr-[490px] flex z-4 mt-[100px]">
<div
class="w-[419px] mr-[30px] flex flex-col justify-center text-animate"
>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[22px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.achievement.certification.title1") }}
</div>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[22px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.achievement.certification.title2") }}
</div>
<div class="text-[#455363] text-[16px] mt-[30px]">
{{ t("companyprofil.achievement.certification.desc") }}
</div>
</div>
<div class="flex image-animate">
<img
class="w-[465px] h-[493px]"
src="@/assets/image/btable.png"
alt="cl"
/>
</div>
</div>
<div class="relative pl-[505px] pr-[490px] flex z-4 mt-[85px]">
<div
class="w-[419px] mr-[30px] flex flex-col justify-center text-animate"
>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[22px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.achievement.platform.title1") }}
</div>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[22px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.achievement.platform.title2") }}
</div>
<div class="text-[#455363] text-[16px] mt-[30px]">
{{ t("companyprofil.achievement.platform.desc") }}
</div>
</div>
<div class="flex image-animate">
<img
class="w-[465px] h-[369px]"
src="@/assets/image/huang.png"
alt="cl"
/>
</div>
</div>
</div>
<div class="content4 relative bg-[#fff] overflow-hidden">
<n-divider class="divider1" vertical />
<div class="divider2" style=""></div>
<div class="divider3" style=""></div>
<div class="divider4" style=""></div>
<n-divider class="divider5" vertical />
<div
class="relative pl-[505px] pr-[490px] flex z-3 mt-[130px] z-4 flex-col text-animate"
>
<div class="text-[#8B59F7] text-[16px]">
{{ t("companyprofil.news.label") }}
</div>
2025-02-24 02:47:53 +00:00
<div class="text-[#10253E] text-[40px] font-bold">
2025-02-22 11:36:52 +00:00
{{ t("companyprofil.news.title") }}
</div>
<div class="text-[#455363] w-[748px] text-[16px] mt-[30px]">
{{ t("companyprofil.news.desc") }}
</div>
<div class="w-full mt-[56px] flex flex-wrap justify-end">
<div class="flex flex-wrap mr-[20px]">
<div class="arrow-btn" @click="handlePrev">
<img
class="w-[38px] h-[38px]"
src="@/assets/image/companyprofil/768/icon-left.png"
/>
</div>
<div class="arrow-btn ml-[25px]" @click="handleNext">
<img
class="w-[38px] h-[38px]"
src="@/assets/image/companyprofil/768/icon-right.png"
/>
</div>
</div>
</div>
</div>
<div class="pt-[73px] pb-[103px] carousel-container px-[495px] z-14">
<div
ref="carouselTrack"
class="carousel-track"
:style="{
transform: `translateX(-${getSlideOffset()}px)`,
}"
@mousedown="handleDragStart"
@mousemove="handleDragMove"
@mouseup="handleDragEnd"
@mouseleave="handleDragEnd"
@touchstart="handleDragStart"
@touchmove="handleDragMove"
@touchend="handleDragEnd"
>
<div
v-for="(item, idx) in getVisibleItems()"
:key="idx"
class="carousel-item cursor-pointer"
@click="handleCarouselClick(item, $event)"
>
<img class="carousel-image" :src="item.imgUrl" />
<div class="carousel-content">
2025-02-24 02:47:53 +00:00
<div class="carousel-title font-bold">
2025-02-22 11:36:52 +00:00
<div>{{ item.title }}</div>
</div>
<div class="carousel-subtitle">
<div>{{ item.subTitle }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<footer>
<div class="footer-content">
<img class="copyright" src="@/assets/image/cp.png" alt="logo" />
</div>
</footer>
2025-02-19 11:04:19 +00:00
</template>
2025-02-22 11:36:52 +00:00
<style lang="scss" scoped>
.header {
width: 100%;
2025-02-24 01:17:48 +00:00
height: 65px;
2025-02-22 11:36:52 +00:00
display: flex;
justify-content: space-between;
align-items: flex-end;
position: fixed;
z-index: 10;
top: 0;
left: 0;
right: 0;
padding: 0 10rem;
2025-02-24 01:17:48 +00:00
padding-bottom: 10px;
2025-02-22 11:36:52 +00:00
}
.logo {
img {
width: 108px;
height: 33px;
}
}
.tabs {
display: flex;
gap: 32px;
margin-right: 32px;
}
.tab-item {
font-size: 16px;
color: #000000;
cursor: pointer;
transition: color 0.3s ease;
padding: 4px 8px;
&.active {
color: #8b59fa;
}
&:hover {
color: #8b59fa;
}
}
.head {
width: 100%;
background-color: #f8f9ff;
img {
width: 100%;
height: 100%;
object-fit: cover;
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
transform: translateZ(0);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
.divider1 {
position: absolute;
z-index: 3;
left: 482px;
width: 1px;
height: 100vw;
}
.divider2 {
position: absolute;
z-index: 3;
left: 720px;
width: 1px;
height: 100vw;
background-image: linear-gradient(to bottom, #e6eaee 50%, transparent 50%);
background-size: 1px 12px; // 第一个值是宽度,第二个值是虚线的总长度(实线+空白)
background-repeat: repeat-y;
}
.divider3 {
position: absolute;
z-index: 3;
left: 952px;
width: 1px;
height: 100vw;
background-image: linear-gradient(to bottom, #e6eaee 50%, transparent 50%);
background-size: 1px 12px; // 第一个值是宽度,第二个值是虚线的总长度(实线+空白)
background-repeat: repeat-y;
}
.divider4 {
position: absolute;
z-index: 3;
left: 1182px;
width: 1px;
height: 100vw;
background-image: linear-gradient(to bottom, #e6eaee 50%, transparent 50%);
background-size: 1px 15px; // 第一个值是宽度,第二个值是虚线的总长度(实线+空白)
background-repeat: repeat-y;
}
.divider5 {
position: absolute;
z-index: 3;
left: 1406px;
width: 1px;
height: 100vw;
}
.footer-content {
height: 90px;
display: flex;
justify-content: center;
align-items: center;
.copyright {
width: 232px;
height: 22pxpx;
}
}
.carousel-container {
width: 100%;
overflow: hidden;
position: relative;
}
.arrow-btn {
cursor: pointer;
}
.carousel-track {
display: flex;
transition: transform 0.5s ease-in-out;
will-change: transform;
}
.carousel-item {
width: 445px;
height: 444px;
background-color: #fff;
margin-right: 28px;
flex: 0 0 auto;
display: block;
padding: 8px 8px 18px 8px;
border-radius: 12px;
box-shadow: 0 3px 14px 1px rgba(0, 0, 0, 0.16);
will-change: transform, opacity; // 优化动画性能
}
.carousel-image {
width: 428px;
height: 259px;
object-fit: cover;
display: block;
}
.carousel-content {
padding: 0 23px 0 23px;
margin-top: 10px;
}
.carousel-title {
font-size: 20px;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.5;
max-height: calc(1.5em * 5);
}
.carousel-subtitle {
color: #455363;
margin-top: 5px;
font-size: 16px;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.5;
max-height: calc(1.5em * 5);
}
// 添加一个通用的溢出控制类
.overflow-hidden {
overflow: hidden;
}
2025-02-19 11:04:19 +00:00
2025-02-22 11:36:52 +00:00
// 为所有可能需要动画的容器添加溢出隐藏
[ref*="moveRef"] {
position: relative;
}
.language-arrow {
font-size: 12px;
margin-left: 4px;
color: #10263E;
transition: transform 0.3s ease;
}
.tab-item:hover .language-arrow {
color: #8B59F7;
}
2025-02-22 11:36:52 +00:00
</style>