1
0
Files
ag-index/nuxt-web/pages/index.vue
2026-04-20 09:45:20 +08:00

434 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import {
homeHeroSlides,
homeIndustryStats,
homePartnerRows,
homeProductFamilies,
homeServiceDomains,
homeSolutions
} from '~/data/home'
import { siteInfo } from '~/data/site'
useSeo({
title: '烟台岸基网络科技有限公司',
description: '烟台岸基网络科技有限公司深耕港航物流供应链数字化,提供航运电商、云码头、全程物流链与智慧供应链解决方案。',
keywords: '岸基网络,烟台岸基科技,智慧物流,航运电商,云码头,港口供应链,物流数字化',
canonicalPath: '/'
})
const heroRef = ref<HTMLElement | null>(null)
let heroSwiper: { destroy: (deleteInstance?: boolean, cleanStyles?: boolean) => void } | null = null
const heroInterleaveOffset = 0.5
type HeroSlideElement = HTMLElement & { progress?: number }
const updateHeroInterleave = (swiper: { slides: ArrayLike<HeroSlideElement>; width: number }) => {
for (let index = 0; index < swiper.slides.length; index += 1) {
const slide = swiper.slides[index]
const slideInner = slide.querySelector<HTMLElement>('.slide-inner')
if (!slideInner) {
continue
}
const slideProgress = slide.progress ?? 0
const innerOffset = swiper.width * heroInterleaveOffset
const innerTranslate = slideProgress * innerOffset
slideInner.style.transform = `translate3d(${innerTranslate}px, 0, 0)`
}
}
const resetHeroTransitions = (swiper: { slides: ArrayLike<HeroSlideElement> }) => {
for (let index = 0; index < swiper.slides.length; index += 1) {
swiper.slides[index].style.transition = ''
}
}
const setHeroTransitions = (swiper: { slides: ArrayLike<HeroSlideElement> }, speed: number) => {
for (let index = 0; index < swiper.slides.length; index += 1) {
const slide = swiper.slides[index]
const slideInner = slide.querySelector<HTMLElement>('.slide-inner')
slide.style.transition = `${speed}ms`
if (slideInner) {
slideInner.style.transition = `${speed}ms`
}
}
}
onMounted(async () => {
if (!heroRef.value) {
return
}
const { default: Swiper } = await import('swiper/bundle')
heroSwiper = new Swiper(heroRef.value, {
loop: true,
speed: 1000,
parallax: true,
watchSlidesProgress: true,
autoplay: {
delay: 6500,
disableOnInteraction: false
},
pagination: {
el: '.home-hero-pagination',
clickable: true
},
navigation: {
nextEl: '.home-hero-next',
prevEl: '.home-hero-prev'
},
on: {
init(this: { slides: ArrayLike<HeroSlideElement>; width: number }) {
updateHeroInterleave(this)
},
progress(this: { slides: ArrayLike<HeroSlideElement>; width: number }) {
updateHeroInterleave(this)
},
touchStart(this: { slides: ArrayLike<HeroSlideElement> }) {
resetHeroTransitions(this)
},
setTransition(this: { slides: ArrayLike<HeroSlideElement> }, speed: number) {
setHeroTransitions(this, speed)
}
}
})
})
onBeforeUnmount(() => {
heroSwiper?.destroy(true, true)
})
</script>
<template>
<div>
<section class="hero-slider hero-style-1">
<div ref="heroRef" class="swiper-container home-hero-swiper">
<div class="swiper-wrapper">
<div v-for="slide in homeHeroSlides" :key="slide.title" class="swiper-slide">
<div class="slide-inner slide-bg-image" :style="{ backgroundImage: `url(${slide.image})` }">
<div class="container">
<div class="slide-title" data-swiper-parallax="300">
<h2>{{ slide.title }}</h2>
</div>
<div class="slide-text" data-swiper-parallax="400">
<p>{{ slide.description }}</p>
</div>
<div class="clearfix" />
<div class="slide-btns" data-swiper-parallax="500">
<NuxtLink :to="slide.to" class="theme-btn-s2">了解更多</NuxtLink>
</div>
</div>
</div>
</div>
</div>
<div class="swiper-pagination home-hero-pagination" />
<div class="swiper-button-next home-hero-next" />
<div class="swiper-button-prev home-hero-prev" />
</div>
</section>
<section class="features-section">
<div class="container">
<div class="row">
<div class="col col-xs-12">
<div class="feature-grids">
<div v-for="item in homeProductFamilies" :key="item.title" class="grid home-family-card">
<div class="header">
<span class="home-feature-icon" aria-hidden="true">
<svg v-if="item.iconKey === 'commerce'" viewBox="0 0 48 48" fill="none">
<path d="M10 12h4l3 18h19l4-13H16" />
<circle cx="20" cy="37" r="2.5" />
<circle cx="34" cy="37" r="2.5" />
<path d="M19 18h17" />
<path d="M22 12V7" />
<path d="M30 12V7" />
</svg>
<svg v-else-if="item.iconKey === 'logistics'" viewBox="0 0 48 48" fill="none">
<path d="M7 15h22v14H7z" />
<path d="M29 20h6l6 6v3h-12z" />
<circle cx="16" cy="35" r="3" />
<circle cx="35" cy="35" r="3" />
<path d="M29 35h3" />
<path d="M12 20h11" />
</svg>
<svg v-else-if="item.iconKey === 'port'" viewBox="0 0 48 48" fill="none">
<path d="M11 36h26" />
<path d="M16 36V13h9v23" />
<path d="M25 16h9v20" />
<path d="M20.5 13V9" />
<path d="M12 18h9" />
<path d="M28 20h6" />
<path d="M14 28h7" />
<path d="M28 28h6" />
</svg>
<svg v-else viewBox="0 0 48 48" fill="none">
<path d="M24 8v21" />
<path d="M17 18c0 4.2 3.1 7 7 7s7-2.8 7-7" />
<path d="M13 34c3-1 6.5-2 11-2s8 1 11 2" />
<path d="M18 39h12" />
<path d="M24 29v10" />
</svg>
</span>
</div>
<div class="details">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
<NuxtLink :to="item.to" class="read-more">了解更多</NuxtLink>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="home-panorama-section section-padding">
<div class="portfolio-container home-panorama-stage">
<img src="/images/index/bk.webp" alt="港航供应链核心能力全景背景" class="home-panorama-background">
<div class="home-panorama-overlay">
<div class="container">
<div class="row">
<div class="col col-lg-6 col-lg-offset-3">
<div class="section-title-s4">
<span>港航供应链核心能力全景</span>
<h2>全栈服务生态重构供应链新格局</h2>
</div>
</div>
</div>
</div>
<img src="/images/index/top.png" alt="全栈服务生态图" class="home-panorama-image">
</div>
</div>
</section>
<section class="portfolio-section section-padding">
<div class="container">
<div class="row">
<div class="col col-lg-6 col-lg-offset-3">
<div class="section-title-s4">
<span>按业务链路快速匹配对应方案</span>
<h2>全域方案 智航港航</h2>
</div>
</div>
</div>
</div>
<div class="portfolio-container">
<div class="portfolio-grids home-solution-grid">
<NuxtLink v-for="item in homeSolutions" :key="item.title" :to="item.to" class="grid">
<div class="img-holder">
<img :src="item.image" :alt="item.title">
</div>
<div class="details">
<p class="portfolio-meta">{{ item.meta }}</p>
<h3>{{ item.title }}</h3>
<p class="portfolio-desc">{{ item.description }}</p>
<span class="portfolio-link">查看方案</span>
</div>
</NuxtLink>
</div>
</div>
</section>
<section class="services-section section-padding">
<div class="container">
<div class="row">
<div class="col col-md-5">
<div class="section-title-s2">
<span>我们的服务领域</span>
<h2>打通港航全链核心场景</h2>
</div>
</div>
<div class="col col-md-6 col-md-offset-1">
<div class="section-title-text">
<p>公司专注服务国内外物流实体中介机构金融企业货主及监管部门提供航运电商物流实施大数据平台信息化咨询等全栈式综合信息服务实现港航物流全领域全主体全链条覆盖</p>
</div>
</div>
</div>
<div class="row">
<div class="col col-xs-12">
<div class="service-grids clearfix">
<div v-for="item in homeServiceDomains" :key="item.title" class="grid">
<div class="icon">
<i :class="['fi', item.iconClass]" />
</div>
<h3>{{ item.title }}</h3>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="about-section section-padding">
<div class="container">
<div class="row">
<div class="col col-md-7">
<div class="home-map-card">
<img src="/images/map.png" alt="岸基科技业务覆盖示意图">
</div>
</div>
<div class="col col-md-5">
<div class="details home-value-copy">
<div class="section-title">
<span>我们的行业价值</span>
<h2>广覆港航全链稳居市场前列</h2>
</div>
<p>依托长达20年的行业信息化经验我们以科技驱动航运物流供应链的创新与升级目前由我们提供服务的客户其业务总量已占据全国水运货量的五分之一</p>
<div class="contact-info">
<div>
<h4>航运货物总量占比</h4>
<p class="home-share-stat"><span class="home-share-number">20</span>%</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="fun-fact-section section-padding pt0">
<div class="container">
<div class="row">
<div class="col col-xs-12">
<h2>数智驱动港航业务 全景洞察运营态势</h2>
<div class="fun-fact-grids clearfix">
<div v-for="item in homeIndustryStats" :key="item.label" class="grid home-stat-grid">
<div class="home-stat-info">
<h3 class="home-stat-heading">
<span class="home-stat-value">{{ item.value.replace('+', '') }}</span>+
</h3>
<p class="home-stat-label">{{ item.label }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="partners-section">
<div class="container">
<div class="row">
<div class="col col-lg-6 col-lg-offset-3">
<div class="section-title-s3 home-partners-title">
<span>我们的合作伙伴</span>
<h2>聚港航精锐启智慧新程</h2>
</div>
</div>
</div>
</div>
<div class="partners-marquee-wrap">
<div v-for="(row, rowIndex) in homePartnerRows" :key="rowIndex" class="row">
<div class="col col-xs-12">
<div class="partner-marquee">
<div class="partner-track">
<div class="partner-track-set">
<div v-for="logo in row" :key="`${rowIndex}-${logo}`" class="grid">
<img :src="logo" alt="合作伙伴标识" loading="lazy">
</div>
</div>
<div class="partner-track-set" aria-hidden="true">
<div v-for="logo in row" :key="`${rowIndex}-${logo}-duplicate`" class="grid">
<img :src="logo" alt="合作伙伴标识" loading="lazy">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="separator" />
</div>
</section>
<section class="cta-section-s2">
<div class="container">
<div class="row">
<div class="col col-lg-8 col-sm-8">
<div class="text">
<h2>岸基科技港航企业值得信赖的长期伙伴</h2>
<p class="home-cta-copy">我们专注打造高效能互联网 + 航运生态平台坚持以客户为中心敏捷响应需求驱动管理效能持续升级为客户创造长期持久价值</p>
</div>
</div>
<div class="col col-lg-3 col-sm-4">
<div class="contact-info">
<div class="icon">
<i class="fi ti-face-smile" />
</div>
<h5>{{ siteInfo.phone }}</h5>
<NuxtLink to="/contact" class="theme-btn-s3">联系我们</NuxtLink>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<style scoped>
.fun-fact-section .home-stat-grid {
width: 20%;
float: left;
}
.fun-fact-section .home-stat-info {
width: auto !important;
max-width: none !important;
float: none !important;
margin: 0 !important;
text-align: center;
}
.fun-fact-section .home-stat-heading {
width: auto !important;
float: none !important;
margin: 0 0 0.2em !important;
font-size: 30px !important;
line-height: 1 !important;
color: #0453fc !important;
font-weight: 700 !important;
}
.fun-fact-section .home-stat-value {
display: inline-block !important;
font-size: 70px !important;
line-height: 1 !important;
color: #0453fc !important;
font-weight: 700 !important;
}
.fun-fact-section .home-stat-label {
width: auto !important;
float: none !important;
margin: 0 !important;
font-size: 16px !important;
line-height: 1.5 !important;
color: #8c8c8c !important;
}
@media (max-width: 767px) {
.fun-fact-section .home-stat-grid {
width: 50%;
margin-bottom: 50px;
}
.fun-fact-section .home-stat-info {
padding: 0 8px;
}
.fun-fact-section .home-stat-value {
font-size: 54px !important;
}
.fun-fact-section .home-stat-label {
font-size: 15px !important;
}
}
</style>