Files
Zhanglj 2ff1064de7 feat: add customer service chat, optimize case and homepage, fix api proxy
这一提交完成了多项功能升级与优化:
1.  新增全局浮动客服组件,集成腾讯云TRTC聊天能力并添加错误格式化工具
2.  新增图片资源并调整部分静态文件结构
3.  优化案例页面:重构筛选逻辑、新增空状态处理、添加加载更多功能
4.  优化首页布局:修复统计数字动画、调整移动端适配样式、优化轮播逻辑
5.  重构官方内容获取工具:添加缓存机制、优化媒体资源处理
6.  优化API代理配置,移除默认本地代理并新增环境变量配置
7.  新增页面数据恢复刷新逻辑,优化页面交互体验
8.  修复按钮组件冗余代码,调整头部导航移动端样式
2026-07-24 18:55:51 +08:00

1424 lines
35 KiB
Vue
Raw Permalink 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>
import { gsap } from 'gsap'
import SiteHeader from '~/components/site/SiteHeader.vue'
import SiteFooter from '~/components/site/SiteFooter.vue'
const pageRoot = ref(null)
const { openConsultation } = useConsultation()
const { fetchPublicMediaAsset, fetchPublicSiteConfig } = useOfficialContent()
let animationContext
const { data: siteConfigRows } = await useAsyncData('public-site-config-about', () =>
fetchPublicSiteConfig({ fresh: true })
)
function parseConfigValue(value, fallback) {
if (value == null || value === '') return fallback
if (typeof value !== 'string') return value
try {
return JSON.parse(value)
} catch {
return fallback
}
}
const siteConfig = computed(() => siteConfigRows.value || {})
const brandConfig = computed(() => parseConfigValue(siteConfig.value.BRAND_PROFILE, {}))
const contactConfig = computed(() =>
parseConfigValue(siteConfig.value.CONTACT, {
phone: '待补充',
email: '待补充',
address: '待补充'
})
)
const footerConfig = computed(() => parseConfigValue(siteConfig.value.FOOTER, {}))
const contactQrAssetId = computed(() => footerConfig.value.qrAssetId || '')
const isDirectAssetUrl = (value) =>
/^(https?:)?\/\//.test(value) || value.startsWith('/') || value.startsWith('data:image/')
const directContactQrSrc = computed(() => {
const value = String(contactQrAssetId.value || '').trim()
return value && isDirectAssetUrl(value) ? value : ''
})
const { data: contactQrAsset } = await useAsyncData(
'public-site-config-about-contact-qr',
() => {
const id = String(contactQrAssetId.value || '').trim()
if (!id || isDirectAssetUrl(id)) return null
return fetchPublicMediaAsset(id).catch(() => null)
},
{ watch: [contactQrAssetId] }
)
useRefreshNuxtDataOnResume(['public-site-config-about', 'public-site-config-about-contact-qr'])
const contactQrSrc = computed(
() =>
directContactQrSrc.value ||
contactQrAsset.value?.url ||
contactQrAsset.value?.fileUrl ||
contactQrAsset.value?.filePath ||
''
)
const contactQrAlt = computed(
() => contactQrAsset.value?.alt || contactQrAsset.value?.name || '社媒二维码'
)
useHead(() => ({
title: '关于我们|大马棒·云途全域 GEO',
meta: [
{
name: 'description',
content:
brandConfig.value.seoDescription ||
'大马棒·云途全域 GEO 是聚焦 AI 搜索增长的全链路服务商,提供可见性诊断、策略规划、内容建设、信源分发与效果复盘。'
}
]
}))
const fallbackStats = [
['1000+', '累计服务客户'],
['12+', '覆盖主流行业'],
['5 万', '真人内容生产网络'],
['5000+', '权威媒体资源']
]
const stats = computed(() => {
const rows = parseConfigValue(siteConfig.value.ABOUT_STATS, [])
if (!Array.isArray(rows) || rows.length === 0) return fallbackStats
return rows
.filter((item) => item.status !== 'OFFLINE')
.sort((left, right) => (Number(left.sortOrder) || 0) - (Number(right.sortOrder) || 0))
.map((item) => [
item.value || item.metricValue || '',
item.label || item.metricLabel || item.title || ''
])
.filter((item) => item[0] || item[1])
})
const fallbackServiceFlow = [
['01', '可见性诊断', '测试品牌在主流 AI 平台中的认知、提及与推荐表现。'],
['02', '策略规划', '围绕业务目标、用户问题与行业特征确定 GEO 路径。'],
['03', '内容建设', '把真实业务信息转化为用户愿意读、AI 能识别的内容。'],
['04', '信源分发', '匹配权威媒体、垂直平台与真实讨论场景。'],
['05', '效果复盘', '持续监测覆盖率、推荐率、流量与咨询线索质量。']
]
const serviceFlow = computed(() => {
const rows = parseConfigValue(siteConfig.value.ABOUT_SERVICE_FLOW, [])
if (!Array.isArray(rows) || rows.length === 0) return fallbackServiceFlow
return rows
.filter((item) => item.status !== 'OFFLINE')
.sort((left, right) => (Number(left.sortOrder) || 0) - (Number(right.sortOrder) || 0))
.map((item, index) => [
item.step || item.number || String(index + 1).padStart(2, '0'),
item.title || item.heading || '',
item.description || item.body || ''
])
.filter((item) => item[1] || item[2])
})
const fallbackTimeline = [
{
year: '2023',
title: '核心团队组建',
events: ['深耕内容营销与搜索优化领域', '开始搭建分布式真人内容生产体系']
},
{
year: '2024',
title: '推出云途全域服务品牌',
events: ['真人内容生产网络突破 2 万人', '合作媒体超过 3000 家']
},
{
year: '2025',
title: '系统进入 GEO 赛道',
events: [
'累计服务客户突破 200 家,覆盖 10+ 行业',
'真人网络升级至 5 万人,媒体资源突破 5000 家'
]
},
{
year: '2026',
title: '全面升级 AI 搜索增长体系',
events: ['打通品牌曝光与营销获客闭环', '服务客户突破 1000 家,覆盖 12+ 主流行业']
}
]
const timeline = computed(() => {
const rows = parseConfigValue(siteConfig.value.ABOUT_HISTORY, [])
if (!Array.isArray(rows) || rows.length === 0) return fallbackTimeline
return rows
.filter((item) => item.status !== 'OFFLINE')
.sort((left, right) => (Number(left.sortOrder) || 0) - (Number(right.sortOrder) || 0))
.map((item) => ({
year: item.year || '',
title: item.title || '',
events:
Array.isArray(item.events) && item.events.length
? item.events
: [item.description].filter(Boolean)
}))
})
const fallbackTeamCapabilities = [
['搜索理解', '经历 PC 搜索、移动搜索到 AI 搜索的持续变化。'],
['内容运营', '理解平台规则,也理解真实用户愿意阅读和相信什么。'],
['媒体资源', '长期积累权威媒体、垂直信源与真实创作者网络。'],
['业务转化', '不止关注曝光,更关注咨询、线索质量与长期资产。']
]
const teamCapabilities = computed(() => {
const rows = parseConfigValue(siteConfig.value.ABOUT_TEAM_CAPABILITIES, [])
if (!Array.isArray(rows) || rows.length === 0) return fallbackTeamCapabilities
return rows
.filter((item) => item.status !== 'OFFLINE')
.sort((left, right) => (Number(left.sortOrder) || 0) - (Number(right.sortOrder) || 0))
.map((item) => [item.title || item.heading || '', item.description || item.body || ''])
.filter((item) => item[0] || item[1])
})
function requestDiagnosis(source) {
openConsultation({ title: '预约免费 GEO 增长诊断', source })
}
function scrollToStory() {
document.getElementById('company-story')?.scrollIntoView({ behavior: 'smooth' })
}
onMounted(async () => {
if (!pageRoot.value || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return
await nextTick()
animationContext = gsap.context(() => {
gsap.to('.about-orbit-a', { rotation: 360, duration: 34, repeat: -1, ease: 'none' })
gsap.to('.about-orbit-b', { rotation: -360, duration: 44, repeat: -1, ease: 'none' })
}, pageRoot.value)
})
onBeforeUnmount(() => animationContext?.revert())
</script>
<template>
<div ref="pageRoot" class="about-page">
<a class="skip-link" href="#main-content">跳到主要内容</a>
<SiteHeader />
<main id="main-content">
<section class="about-hero">
<div class="about-hero-mesh" aria-hidden="true"></div>
<div class="page-width about-hero-grid">
<div class="about-hero-copy">
<p class="page-eyebrow">大马棒 · 云途全域 GEO</p>
<h1>云途全域</h1>
<h2>一家帮品牌在 AI 搜索里<br /><span>被看见被信任被选择</span>的全链路服务商</h2>
<p>
大马棒让品牌在 AI
时代拥有持续增长力为使命专注打造兼具品牌声量沉淀与获客实效的增长解决方案
</p>
<div class="hero-actions">
<button
class="primary-button"
type="button"
@click="requestDiagnosis('关于我们页 Hero')"
>
认识合作方式 <AppIcon name="arrow-right" />
</button>
<button class="text-action" type="button" @click="scrollToStory">
了解我们的故事 <AppIcon name="bottom" />
</button>
</div>
</div>
<div class="about-hero-visual" aria-label="云途全域 GEO 全链路服务示意图">
<div class="about-orbit about-orbit-a">
<i v-for="index in 5" :key="`a-${index}`"></i>
</div>
<div class="about-orbit about-orbit-b">
<i v-for="index in 4" :key="`b-${index}`"></i>
</div>
<div class="about-core">
<small>YUNTU GEO</small><strong>云途全域</strong><span>AI 搜索增长</span>
</div>
<div class="about-node about-node-1"><span>01</span><strong>诊断</strong></div>
<div class="about-node about-node-2"><span>02</span><strong>策略</strong></div>
<div class="about-node about-node-3"><span>03</span><strong>内容</strong></div>
<div class="about-node about-node-4"><span>04</span><strong>分发</strong></div>
<div class="about-node about-node-5"><span>05</span><strong>复盘</strong></div>
<div class="hero-status"><span></span> 从品牌认知到咨询转化</div>
</div>
</div>
</section>
<section id="company-story" class="company-story-section">
<div class="page-width company-story-grid">
<header class="story-heading">
<p class="section-kicker">我们是谁</p>
<h2>帮助企业把公开信息沉淀为 AI 可以识别和引用的数字信任资产</h2>
</header>
<div class="story-content">
<p>
大马棒·云途全域 GEO 是国内深耕 AI 搜索增长领域的专业全链路服务商聚焦
GEO生成式引擎优化核心赛道秉持品效协同长效增长的服务理念
</p>
<p>
相比单纯追求曝光的传统内容投放我们更关注企业在 AI
回答中的是否被理解是否被信任是否被推荐”,并把内容建设与真实业务转化连接起来
</p>
<blockquote>
<span>我们的使命</span>
大马棒让品牌在 AI 时代拥有持续增长力
</blockquote>
</div>
</div>
</section>
<section class="search-change-section">
<div class="page-width search-change-grid">
<div class="change-visual">
<div class="change-track">
<div class="change-step old">
<span>过去</span><strong>搜索网页</strong>
<p>输入关键词<br />逐页比较结果</p>
</div>
<i></i>
<div class="change-step now">
<span>现在</span><strong> AI 提问</strong>
<p>直接获得总结<br />与品牌推荐</p>
</div>
</div>
<div class="change-question">哪一类方案更适合我的业务?”</div>
</div>
<div class="change-copy">
<p class="section-kicker">用户获取信息的方式变了</p>
<h2>从搜索网页逐步转向向 AI 提问</h2>
<p>
GEO
不是简单堆叠文章或批量铺稿而是围绕真实业务信息用户决策意图可信信源和内容结构系统提升品牌在主流
AI 平台中的认知准确度提及率与推荐优先级
</p>
<div class="change-principles">
<span>真实业务事实</span><span>用户决策问题</span><span>可信公开信源</span
><span>可追踪转化</span>
</div>
</div>
</div>
</section>
<section class="company-stats-section">
<div class="page-width company-stats-grid">
<header>
<p class="section-kicker">持续积累的基础能力</p>
<h2>规模不是目的是稳定交付的基础</h2>
</header>
<div class="stats-row">
<article v-for="(stat, index) in stats" :key="stat[1]">
<span>0{{ index + 1 }}</span
><strong>{{ stat[0] }}</strong>
<p>{{ stat[1] }}</p>
</article>
</div>
</div>
</section>
<section class="method-section">
<div class="page-width">
<header class="center-heading">
<p class="section-kicker method-kicker">全链路服务方法</p>
<h2> AI 可见性诊断到效果复盘</h2>
<p>每一个环节都围绕真实业务目标推进避免内容媒体和转化承接各做一段</p>
</header>
<div class="method-flow">
<article v-for="step in serviceFlow" :key="step[0]">
<div class="method-marker">{{ step[0] }}</div>
<h3>{{ step[1] }}</h3>
<p>{{ step[2] }}</p>
</article>
</div>
</div>
</section>
<section class="timeline-section">
<div class="page-width timeline-layout">
<header class="timeline-heading">
<p class="section-kicker">发展历程</p>
<h2>从内容与搜索经验走向 AI 搜索增长</h2>
<p>
平台和算法持续变化但我们做的事情始终一致让品牌在用户搜索时出现在用户选择时被信任
</p>
</header>
<div class="timeline-list">
<article
v-for="(item, index) in timeline"
:key="item.year"
:class="{ current: index === timeline.length - 1 }"
>
<div class="timeline-year">{{ item.year }}</div>
<div>
<h3>{{ item.title }}</h3>
<ul>
<li v-for="event in item.events" :key="event">{{ event }}</li>
</ul>
</div>
<span class="timeline-dot"></span>
</article>
</div>
</div>
</section>
<section class="team-section">
<div class="page-width team-grid">
<div class="team-statement">
<p class="section-kicker">团队介绍</p>
<h2>十余年里经历搜索从 PC 到移动也正在经历从传统搜索到 AI 搜索</h2>
<blockquote>
算法在变平台在变用户获取信息的方式在变帮助品牌被用户找到和信任这件事没有变
</blockquote>
</div>
<div class="team-capabilities">
<article v-for="(capability, index) in teamCapabilities" :key="capability[0]">
<span>0{{ index + 1 }}</span>
<h3>{{ capability[0] }}</h3>
<p>{{ capability[1] }}</p>
</article>
</div>
</div>
</section>
<section class="contact-section">
<div class="page-width contact-grid">
<header class="contact-heading">
<p class="section-kicker">联系我们</p>
<h2>从一次真实沟通开始</h2>
<p>说说行业现状和目标我们会先判断 GEO 是否适合当前业务阶段</p>
<button
class="primary-button small"
type="button"
@click="requestDiagnosis('关于我们联系板块')"
>
预约专属顾问 <AppIcon name="arrow-right" />
</button>
</header>
<div class="contact-details">
<dl>
<div>
<dt>咨询电话</dt>
<dd>{{ contactConfig.phone || '待补充' }}</dd>
</div>
<div>
<dt>联系邮箱</dt>
<dd>{{ contactConfig.email || '待补充' }}</dd>
</div>
<div>
<dt>办公地址</dt>
<dd>{{ contactConfig.address || '待补充' }}</dd>
</div>
</dl>
<div class="contact-qr">
<img v-if="contactQrSrc" :src="contactQrSrc" :alt="contactQrAlt" loading="lazy" />
<span v-else aria-hidden="true"></span><strong>扫码添加专属顾问</strong
><small>获取 1 1 GEO 增长诊断</small>
</div>
</div>
</div>
</section>
<section class="about-cta">
<div class="about-cta-art" aria-hidden="true"></div>
<div class="page-width about-cta-content">
<p>AI 搜索正在成为新的品牌决策入口</p>
<h2>让公开内容不再分散<br />沉淀为持续产生价值的品牌资产</h2>
<button
class="primary-button"
type="button"
@click="requestDiagnosis('关于我们页底部 CTA')"
>
预约免费 GEO 诊断 <AppIcon name="arrow-right" />
</button>
</div>
</section>
</main>
<SiteFooter />
</div>
</template>
<style scoped>
.about-page {
--about-blue: #237df0;
overflow: hidden;
color: #344359;
background: #fff;
}
.skip-link {
position: fixed;
z-index: 100;
top: 10px;
left: 10px;
padding: 10px 14px;
border-radius: 6px;
color: #fff;
background: #1f70df;
transform: translateY(-150%);
transition: transform 0.2s;
}
.skip-link:focus {
transform: translateY(0);
}
.page-eyebrow,
.section-kicker {
margin: 0;
color: var(--about-blue);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.14em;
}
.about-hero {
position: relative;
min-height: 690px;
display: grid;
align-items: center;
isolation: isolate;
background: #f1f7ff;
}
.about-hero-mesh {
position: absolute;
z-index: -1;
inset: 0;
background:
radial-gradient(circle at 80% 29%, rgba(75, 159, 255, 0.25), transparent 28%),
radial-gradient(circle at 15% 91%, rgba(98, 201, 235, 0.12), transparent 28%),
linear-gradient(110deg, #f8fbff, #e7f2ff);
}
.about-hero-mesh::after {
position: absolute;
inset: 0;
content: '';
opacity: 0.18;
background-image:
linear-gradient(rgba(54, 124, 214, 0.08) 1px, transparent 1px),
linear-gradient(90deg, rgba(54, 124, 214, 0.08) 1px, transparent 1px);
background-size: 58px 58px;
mask-image: linear-gradient(90deg, transparent 20%, #000);
}
.about-hero-grid {
min-height: 690px;
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
gap: 60px;
padding: 55px 0 62px;
}
.about-hero-copy h1 {
margin: 16px 0 0;
color: #344359;
font-size: clamp(55px, 5.4vw, 86px);
letter-spacing: -0.06em;
line-height: 1;
}
.about-hero-copy h2 {
max-width: 760px;
margin: 24px 0 0;
color: #4d5d72;
font-size: clamp(25px, 2.25vw, 37px);
letter-spacing: -0.035em;
line-height: 1.42;
}
.about-hero-copy h2 span {
color: #1978ef;
}
.about-hero-copy > p:nth-of-type(2) {
max-width: 660px;
margin: 23px 0 0;
color: #68798e;
font-size: 15px;
line-height: 1.85;
}
.hero-actions {
display: flex;
align-items: center;
gap: 25px;
margin-top: 31px;
}
.text-action {
color: #53667e;
background: transparent;
font-size: 13px;
font-weight: 600;
}
.text-action span {
display: inline-grid;
width: 28px;
height: 28px;
margin-left: 8px;
place-items: center;
border: 1px solid #bbcee4;
border-radius: 50%;
color: #237df0;
transition: 0.2s;
}
.text-action:hover span {
background: #fff;
transform: translateY(3px);
}
.about-hero-visual {
position: relative;
width: min(610px, 100%);
aspect-ratio: 1.04;
justify-self: end;
}
.about-hero-visual::before {
position: absolute;
inset: 6% 1% 0;
content: '';
border-radius: 50%;
background:
radial-gradient(
circle,
rgba(255, 255, 255, 0.95) 0 23%,
rgba(130, 194, 255, 0.21) 24% 47%,
transparent 48%
),
url('/images/lanhu/slices/hero-geo-visual@2x.png') 70% 47% / 168% auto no-repeat;
filter: drop-shadow(0 32px 48px rgba(51, 119, 204, 0.18));
mask-image: radial-gradient(ellipse, #000 50%, transparent 75%);
}
.about-orbit {
position: absolute;
z-index: 2;
top: 50%;
left: 50%;
border: 1px solid rgba(51, 133, 232, 0.3);
border-radius: 50%;
transform: translate(-50%, -50%);
}
.about-orbit-a {
width: 385px;
height: 385px;
}
.about-orbit-b {
width: 515px;
height: 515px;
border-style: dashed;
opacity: 0.7;
}
.about-orbit i {
position: absolute;
width: 12px;
height: 12px;
border: 3px solid #fff;
border-radius: 50%;
background: #2782f2;
box-shadow: 0 6px 16px rgba(35, 124, 232, 0.36);
}
.about-orbit i:nth-child(1) {
top: -6px;
left: 50%;
}
.about-orbit i:nth-child(2) {
top: 25%;
right: 1%;
background: #52c2e7;
}
.about-orbit i:nth-child(3) {
right: 12%;
bottom: 10%;
background: #736ff1;
}
.about-orbit i:nth-child(4) {
bottom: 8%;
left: 15%;
background: #4a9ef2;
}
.about-orbit i:nth-child(5) {
top: 26%;
left: 1%;
background: #69c3e7;
}
.about-core {
position: absolute;
z-index: 4;
top: 50%;
left: 50%;
width: 165px;
height: 165px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 12px solid rgba(255, 255, 255, 0.64);
border-radius: 50%;
color: #fff;
background: linear-gradient(145deg, #2b82f0, #48b8e8);
box-shadow: 0 24px 48px rgba(34, 117, 223, 0.29);
transform: translate(-50%, -50%);
}
.about-core small {
font-size: 9px;
letter-spacing: 0.14em;
opacity: 0.75;
}
.about-core strong {
margin-top: 7px;
font-size: 21px;
}
.about-core span {
margin-top: 4px;
font-size: 10px;
opacity: 0.76;
}
.about-node {
position: absolute;
z-index: 5;
width: 78px;
height: 72px;
display: grid;
place-content: center;
justify-items: center;
border: 1px solid rgba(255, 255, 255, 0.9);
border-radius: 18px 6px 18px 6px;
color: #416991;
background: rgba(255, 255, 255, 0.8);
box-shadow: 0 15px 34px rgba(55, 112, 184, 0.15);
backdrop-filter: blur(10px);
}
.about-node span {
color: #96acc4;
font-size: 8px;
}
.about-node strong {
margin-top: 4px;
font-size: 12px;
}
.about-node-1 {
top: 6%;
left: 50%;
transform: translateX(-50%);
}
.about-node-2 {
top: 29%;
right: 2%;
}
.about-node-3 {
right: 9%;
bottom: 11%;
}
.about-node-4 {
bottom: 7%;
left: 25%;
}
.about-node-5 {
top: 38%;
left: 0;
}
.hero-status {
position: absolute;
right: 7%;
bottom: 0;
display: flex;
align-items: center;
gap: 8px;
color: #74869c;
font-size: 11px;
}
.hero-status span {
width: 7px;
height: 7px;
border-radius: 50%;
background: #28a3ed;
box-shadow: 0 0 0 5px rgba(40, 163, 237, 0.12);
}
.company-story-section {
scroll-margin-top: 70px;
padding: 116px 0 132px;
}
.company-story-grid {
display: grid;
grid-template-columns: 0.8fr 1.2fr;
gap: 95px;
align-items: start;
}
.story-heading {
position: sticky;
top: 105px;
}
.story-heading h2,
.change-copy h2,
.company-stats-grid h2,
.center-heading h2,
.timeline-heading h2,
.team-statement h2,
.contact-heading h2 {
margin: 15px 0 0;
color: #344359;
font-size: clamp(32px, 3vw, 48px);
letter-spacing: -0.045em;
line-height: 1.3;
}
.story-content > p {
margin: 0 0 21px;
color: #687a90;
font-size: 15px;
line-height: 1.95;
}
.story-content blockquote {
margin: 35px 0 0;
padding: 32px 36px;
border-radius: 7px 18px 7px 18px;
color: #fff;
background: linear-gradient(135deg, #2778dc, #42afe4);
box-shadow: 0 24px 50px rgba(38, 113, 205, 0.2);
font-size: 25px;
font-weight: 600;
line-height: 1.55;
}
.story-content blockquote span {
display: block;
margin-bottom: 12px;
font-size: 9px;
font-weight: 700;
letter-spacing: 0.13em;
opacity: 0.72;
}
.search-change-section {
padding: 112px 0 128px;
background: #eef7ff;
}
.search-change-grid {
display: grid;
grid-template-columns: 1.05fr 0.95fr;
gap: 80px;
align-items: center;
}
.change-visual {
position: relative;
min-height: 430px;
padding: 55px;
border: 1px solid rgba(255, 255, 255, 0.85);
border-radius: 20px 7px 20px 7px;
background:
radial-gradient(circle at 72% 28%, rgba(81, 160, 255, 0.27), transparent 25%),
linear-gradient(145deg, #f3f9ff, #dcecff);
box-shadow:
0 26px 55px rgba(57, 119, 197, 0.12),
inset 0 1px 0 #fff;
}
.change-track {
display: grid;
grid-template-columns: 1fr 50px 1fr;
align-items: center;
gap: 15px;
}
.change-track > i {
color: #5aa2ed;
font-size: 27px;
font-style: normal;
text-align: center;
}
.change-step {
min-height: 245px;
display: flex;
flex-direction: column;
justify-content: center;
padding: 28px;
border-radius: 14px 5px 14px 5px;
background: rgba(255, 255, 255, 0.74);
}
.change-step span {
color: #8ba5c1;
font-size: 9px;
font-weight: 700;
}
.change-step strong {
margin-top: 23px;
color: #425a75;
font-size: 23px;
}
.change-step p {
margin: 12px 0 0;
color: #7b8a9c;
font-size: 12px;
line-height: 1.75;
}
.change-step.now {
color: #fff;
background: linear-gradient(145deg, #3185ed, #4eb7e7);
box-shadow: 0 18px 34px rgba(44, 128, 225, 0.2);
}
.change-step.now span,
.change-step.now p {
color: rgba(255, 255, 255, 0.75);
}
.change-step.now strong {
color: #fff;
}
.change-question {
position: absolute;
right: 55px;
bottom: 27px;
left: 55px;
color: #5980aa;
font-size: 11px;
text-align: center;
}
.change-copy > p:nth-of-type(2) {
margin: 20px 0 0;
color: #718197;
font-size: 14px;
line-height: 1.85;
}
.change-principles {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 24px;
}
.change-principles span {
padding: 8px 11px;
border-radius: 5px;
color: #557598;
background: rgba(255, 255, 255, 0.72);
font-size: 10px;
}
.company-stats-section {
padding: 110px 0 125px;
}
.company-stats-grid > header {
max-width: 760px;
}
.stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 14px;
margin-top: 55px;
}
.stats-row article {
min-height: 190px;
padding: 30px;
border-radius: 15px 5px 15px 5px;
background: #f1f6fc;
transition: 0.24s;
}
.stats-row article:hover {
background: #fff;
box-shadow: 0 20px 42px rgba(59, 117, 187, 0.12);
transform: translateY(-5px);
}
.stats-row span {
color: #98adc5;
font-size: 9px;
}
.stats-row strong {
display: block;
margin-top: 35px;
color: #277fec;
font-size: 30px;
font-variant-numeric: tabular-nums;
}
.stats-row p {
margin: 7px 0 0;
color: #718298;
font-size: 11px;
}
.method-section {
padding: 112px 0 130px;
background: #eef7ff;
}
.center-heading {
max-width: 800px;
margin: 0 auto;
text-align: center;
}
.center-heading .section-kicker {
width: 100%;
display: block;
justify-content: center;
text-align: center;
}
.center-heading .section-kicker::before {
display: none;
}
.center-heading > p:last-child {
max-width: 640px;
margin: 18px auto 0;
color: #748398;
font-size: 14px;
line-height: 1.8;
}
.method-flow {
position: relative;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 18px;
margin-top: 62px;
}
.method-flow::before {
position: absolute;
top: 27px;
right: 9%;
left: 9%;
height: 1px;
content: '';
background: linear-gradient(90deg, transparent, #75afea 12% 88%, transparent);
}
.method-flow article {
position: relative;
z-index: 2;
padding: 0 15px;
text-align: center;
}
.method-marker {
width: 55px;
height: 55px;
display: grid;
margin: 0 auto 22px;
place-items: center;
border: 7px solid rgba(255, 255, 255, 0.92);
border-radius: 50%;
color: #fff !important;
background: #358af0;
box-shadow: 0 11px 24px rgba(51, 135, 235, 0.22);
font-size: 10px;
font-weight: 700;
}
.method-flow h3 {
margin: 0;
color: #354961;
font-size: 17px;
}
.method-flow p {
margin: 11px 0 0;
color: #75869b;
font-size: 11px;
line-height: 1.7;
}
.timeline-section {
padding: 116px 0 132px;
}
.timeline-layout {
display: grid;
grid-template-columns: 0.75fr 1.25fr;
gap: 95px;
align-items: start;
}
.timeline-heading {
position: sticky;
top: 105px;
}
.timeline-heading > p:last-child {
margin: 20px 0 0;
color: #748398;
font-size: 14px;
line-height: 1.8;
}
.timeline-list {
position: relative;
}
.timeline-list::before {
position: absolute;
top: 20px;
bottom: 20px;
left: 82px;
width: 1px;
content: '';
background: linear-gradient(#b8d2ed, #488fe1);
}
.timeline-list article {
position: relative;
min-height: 180px;
display: grid;
grid-template-columns: 82px 1fr;
gap: 38px;
padding: 18px 0 30px;
}
.timeline-year {
color: #86a2c0;
font-size: 14px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.timeline-list h3 {
margin: -3px 0 0;
color: #3b5069;
font-size: 22px;
}
.timeline-list ul {
display: grid;
gap: 10px;
margin: 15px 0 0;
padding: 0;
list-style: none;
}
.timeline-list li {
position: relative;
padding-left: 14px;
color: #728298;
font-size: 12px;
line-height: 1.6;
}
.timeline-list li::before {
position: absolute;
top: 7px;
left: 0;
width: 5px;
height: 5px;
content: '';
border-radius: 50%;
background: #4a93e6;
}
.timeline-dot {
position: absolute;
top: 17px;
left: 76px;
width: 13px;
height: 13px;
border: 3px solid #fff;
border-radius: 50%;
background: #75a9df;
box-shadow: 0 0 0 1px #75a9df;
}
.timeline-list article.current .timeline-year,
.timeline-list article.current h3 {
color: #247be8;
}
.timeline-list article.current .timeline-dot {
background: #247be8;
box-shadow: 0 0 0 5px rgba(36, 123, 232, 0.12);
}
.team-section {
padding: 112px 0 128px;
background: #f1f7fd;
}
.team-grid {
display: grid;
grid-template-columns: 0.88fr 1.12fr;
gap: 80px;
align-items: center;
}
.team-statement blockquote {
margin: 30px 0 0;
padding: 27px 30px;
border-left: 3px solid #3288ec;
color: #59708b;
background: rgba(255, 255, 255, 0.66);
font-size: 16px;
line-height: 1.8;
}
.team-capabilities {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.team-capabilities article {
min-height: 180px;
padding: 28px;
border-radius: 15px 5px 15px 5px;
background: rgba(255, 255, 255, 0.78);
}
.team-capabilities span {
color: #98adc5;
font-size: 9px;
}
.team-capabilities h3 {
margin: 28px 0 0;
color: #3c526b;
font-size: 18px;
}
.team-capabilities p {
margin: 8px 0 0;
color: #75869a;
font-size: 11px;
line-height: 1.65;
}
.contact-section {
padding: 116px 0 130px;
}
.contact-grid {
display: grid;
grid-template-columns: 0.72fr 1.28fr;
gap: 90px;
align-items: center;
}
.contact-heading > p:nth-of-type(2) {
margin: 20px 0 0;
color: #748398;
font-size: 14px;
line-height: 1.8;
}
.contact-heading .primary-button {
margin-top: 27px;
}
.contact-details {
display: grid;
grid-template-columns: 1fr 210px;
gap: 28px;
padding: 42px;
border-radius: 18px 6px 18px 6px;
background: #eef6ff;
}
.contact-details dl {
margin: 0;
}
.contact-details dl > div {
display: grid;
grid-template-columns: 100px 1fr;
gap: 25px;
padding: 18px 0;
border-bottom: 1px solid #d8e6f4;
}
.contact-details dl > div:last-child {
border-bottom: 0;
}
.contact-details dt {
color: #8295ab;
font-size: 10px;
}
.contact-details dd {
margin: 0;
color: #405873;
font-size: 13px;
line-height: 1.6;
}
.contact-qr {
display: grid;
align-content: center;
justify-items: center;
text-align: center;
}
.contact-qr > span {
width: 106px;
height: 106px;
border: 8px solid #fff;
background:
linear-gradient(90deg, #1e446d 25%, transparent 25% 50%, #1e446d 50% 75%, transparent 75%) 0 0 /
18px 18px,
linear-gradient(#1e446d 25%, transparent 25% 50%, #1e446d 50% 75%, transparent 75%) 9px 9px /
18px 18px,
#fff;
}
.contact-qr strong {
margin-top: 14px;
color: #41617f;
font-size: 11px;
}
.contact-qr small {
margin-top: 5px;
color: #8294a7;
font-size: 9px;
}
.about-cta {
position: relative;
min-height: 430px;
display: grid;
place-items: center;
overflow: hidden;
isolation: isolate;
}
.about-cta-art {
position: absolute;
z-index: -1;
inset: 0;
background:
linear-gradient(rgba(247, 251, 255, 0.18), rgba(234, 246, 255, 0.46)),
url('/images/lanhu/slices/home-group105-image31@2x.png') center / cover no-repeat;
}
.about-cta-content {
display: grid;
justify-items: center;
padding: 75px 0;
text-align: center;
}
.about-cta-content > p {
width: 100%;
margin: 0;
color: #237df0;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.12em;
}
.about-cta-content h2 {
margin: 17px 0 0;
color: #2f75cc;
font-size: clamp(32px, 3.2vw, 50px);
letter-spacing: -0.045em;
line-height: 1.3;
}
.about-cta-content .primary-button {
margin-top: 29px;
}
@media (max-width: 980px) {
.about-hero,
.about-hero-grid {
min-height: auto;
}
.about-hero-grid,
.company-story-grid,
.search-change-grid,
.timeline-layout,
.team-grid,
.contact-grid {
grid-template-columns: 1fr;
}
.about-hero-grid {
padding-top: 74px;
padding-bottom: 62px;
}
.about-hero-visual {
justify-self: center;
margin-top: 20px;
}
.company-story-grid,
.timeline-layout {
gap: 45px;
}
.story-heading,
.timeline-heading {
position: static;
}
.search-change-grid {
gap: 55px;
}
.change-visual {
order: 2;
}
.timeline-heading {
max-width: 720px;
}
.team-grid,
.contact-grid {
gap: 45px;
}
.method-flow {
grid-template-columns: 1fr;
gap: 0;
}
.method-flow::before {
top: 28px;
bottom: 28px;
left: 27px;
width: 1px;
height: auto;
}
.method-flow article {
min-height: 115px;
display: grid;
grid-template-columns: 55px 1fr;
grid-template-rows: auto auto;
gap: 4px 20px;
padding: 0;
text-align: left;
}
.method-marker {
grid-row: 1 / 3;
margin: 0;
}
.method-flow p {
margin-top: 4px;
}
}
@media (max-width: 600px) {
.about-hero-grid {
padding-top: 54px;
}
.about-hero-copy h1 {
font-size: clamp(52px, 16vw, 70px);
}
.about-hero-copy h2 {
font-size: 25px;
}
.about-hero-copy h2 br {
display: none;
}
.hero-actions {
align-items: flex-start;
flex-direction: column;
gap: 18px;
}
.about-hero-visual {
aspect-ratio: 0.96;
}
.about-orbit-b {
width: 340px;
height: 340px;
}
.about-orbit-a {
width: 255px;
height: 255px;
}
.about-core {
width: 125px;
height: 125px;
border-width: 9px;
}
.about-core strong {
font-size: 17px;
}
.about-node {
width: 61px;
height: 57px;
}
.about-node strong {
font-size: 10px;
}
.company-story-section,
.search-change-section,
.company-stats-section,
.method-section,
.timeline-section,
.team-section,
.contact-section {
padding-top: 76px;
padding-bottom: 86px;
}
.story-content blockquote {
padding: 27px 23px;
font-size: 21px;
}
.change-visual {
min-height: 520px;
padding: 28px 20px;
}
.change-track {
grid-template-columns: 1fr;
}
.change-track > i {
transform: rotate(90deg);
}
.change-step {
min-height: 170px;
}
.change-question {
right: 20px;
bottom: 20px;
left: 20px;
}
.stats-row {
grid-template-columns: 1fr;
}
.stats-row article {
min-height: 145px;
}
.team-capabilities {
grid-template-columns: 1fr;
}
.team-capabilities article {
min-height: 145px;
}
.contact-details {
grid-template-columns: 1fr;
padding: 27px 20px;
}
.contact-details dl > div {
grid-template-columns: 80px 1fr;
gap: 14px;
}
.contact-qr {
padding-top: 22px;
}
.about-cta {
min-height: 390px;
}
.about-cta-content h2 br {
display: none;
}
}
</style>