feat:接口联调
@@ -8,6 +8,7 @@ dist/
|
||||
|
||||
# Local Codex agent skills and instructions
|
||||
.agents/
|
||||
.codex/
|
||||
skills-lock.json
|
||||
|
||||
# Local environment files
|
||||
|
||||
@@ -6,6 +6,37 @@
|
||||
font-family: 'Source Han Sans', 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
|
||||
color: #404040;
|
||||
background: #fff;
|
||||
--color-brand-primary: #1478fb;
|
||||
--color-brand-bright: #0875f9;
|
||||
--color-brand-blue: #287cf9;
|
||||
--color-brand-cyan: #00adf6;
|
||||
--color-brand-violet: #453cff;
|
||||
--gradient-action: linear-gradient(100deg, #453cff, #00adf6);
|
||||
--color-text-strong: #404040;
|
||||
--color-text-default: #525966;
|
||||
--color-text-body: #777;
|
||||
--color-text-muted: #a5a5a5;
|
||||
--color-surface-blue: #edf8ff;
|
||||
--color-surface-case: #eef9ff;
|
||||
--color-surface-soft: #f9fbff;
|
||||
--color-border-soft: #d7e9ff;
|
||||
--radius-control: 5px;
|
||||
--radius-small: 8px;
|
||||
--radius-card: 12px;
|
||||
--radius-panel: 16px;
|
||||
--radius-feature: 20px;
|
||||
--shadow-button: 0 8px 15px rgba(25, 106, 255, 0.16);
|
||||
--shadow-button-hover: 0 11px 20px rgba(25, 106, 255, 0.24);
|
||||
--shadow-card: 0 10px 24px rgba(112, 163, 255, 0.09);
|
||||
--shadow-card-hover: 0 17px 32px rgba(73, 139, 234, 0.14);
|
||||
--container-max: 1296px;
|
||||
--page-gutter-desktop: 24px;
|
||||
--page-gutter-mobile: 16px;
|
||||
--section-space-desktop: 80px;
|
||||
--section-space-mobile: 64px;
|
||||
--duration-fast: 200ms;
|
||||
--duration-normal: 320ms;
|
||||
--ease-standard: cubic-bezier(0.2, 0.75, 0.2, 1);
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@@ -1188,7 +1219,7 @@ a:focus-visible {
|
||||
.article-page
|
||||
)
|
||||
:is(.page-eyebrow, .section-kicker) {
|
||||
color: #286dae !important;
|
||||
color: #286dae;
|
||||
font-size: 14px !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: 0.08em !important;
|
||||
@@ -1267,6 +1298,19 @@ a:focus-visible {
|
||||
color: var(--inner-copy) !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
.about-page .method-flow .method-marker {
|
||||
color: #fff !important;
|
||||
}
|
||||
.about-page .center-heading .method-kicker {
|
||||
width: fit-content !important;
|
||||
display: block !important;
|
||||
margin-right: auto !important;
|
||||
margin-left: auto !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
.about-page .center-heading .method-kicker::before {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Advantages */
|
||||
.advantages-page :is(.hero-advantage-links button, .story-action, .proof-layout header > a) {
|
||||
@@ -1334,7 +1378,7 @@ a:focus-visible {
|
||||
.industry-list > article > span,
|
||||
.proof-data span
|
||||
) {
|
||||
color: var(--inner-muted) !important;
|
||||
color: var(--color-surface-soft) !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function validate() {
|
||||
if (!form.value.name.trim()) nextErrors.name = '请填写您的姓名'
|
||||
if (!form.value.company.trim()) nextErrors.company = '请填写公司名称'
|
||||
if (!form.value.contact.trim()) {
|
||||
nextErrors.contact = '请填写手机号或邮箱'
|
||||
nextErrors.contact = '请填写手机号'
|
||||
} else if (
|
||||
!/^(1\d{10}|[\w.+-]+@[\w.-]+\.[A-Za-z]{2,}|[\d\s()+-]{6,})$/.test(form.value.contact.trim())
|
||||
) {
|
||||
@@ -143,7 +143,7 @@ onBeforeUnmount(() => {
|
||||
v-model="form.contact"
|
||||
type="text"
|
||||
autocomplete="tel"
|
||||
placeholder="手机号或工作邮箱"
|
||||
placeholder="手机号"
|
||||
/>
|
||||
<small v-if="errors.contact">{{ errors.contact }}</small>
|
||||
</label>
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="ueditor-content" v-html="content"></div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.ueditor-content {
|
||||
color: #334155;
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
word-break: break-word;
|
||||
}
|
||||
.ueditor-content :deep(*) {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.ueditor-content :deep(h1),
|
||||
.ueditor-content :deep(h2),
|
||||
.ueditor-content :deep(h3),
|
||||
.ueditor-content :deep(h4),
|
||||
.ueditor-content :deep(h5),
|
||||
.ueditor-content :deep(h6) {
|
||||
margin: 46px 0 18px;
|
||||
color: #0f1e33;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.42;
|
||||
}
|
||||
.ueditor-content :deep(h2) {
|
||||
font-size: clamp(22px, 2.1vw, 28px);
|
||||
}
|
||||
.ueditor-content :deep(h3) {
|
||||
font-size: 22px;
|
||||
}
|
||||
.ueditor-content :deep(h4) {
|
||||
font-size: 19px;
|
||||
}
|
||||
.ueditor-content :deep(p) {
|
||||
margin: 0 0 22px;
|
||||
}
|
||||
.ueditor-content :deep(a) {
|
||||
color: #2f74ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
.ueditor-content :deep(a:hover) {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.ueditor-content :deep(strong),
|
||||
.ueditor-content :deep(b) {
|
||||
color: #132238;
|
||||
font-weight: 700;
|
||||
}
|
||||
.ueditor-content :deep(ul),
|
||||
.ueditor-content :deep(ol) {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin: 18px 0 28px;
|
||||
padding-left: 1.35em;
|
||||
}
|
||||
.ueditor-content :deep(li) {
|
||||
padding-left: 4px;
|
||||
line-height: 1.9;
|
||||
}
|
||||
.ueditor-content :deep(blockquote) {
|
||||
margin: 34px 0;
|
||||
padding: 24px 28px;
|
||||
border-left: 4px solid #3d7cff;
|
||||
border-radius: 0 14px 14px 0;
|
||||
color: #24364f;
|
||||
background: #f4f7ff;
|
||||
}
|
||||
.ueditor-content :deep(img) {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 34px auto;
|
||||
border-radius: 16px;
|
||||
}
|
||||
.ueditor-content :deep(table) {
|
||||
width: 100%;
|
||||
margin: 32px 0;
|
||||
overflow: hidden;
|
||||
border-collapse: collapse;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 1px #e7edf8;
|
||||
}
|
||||
.ueditor-content :deep(th),
|
||||
.ueditor-content :deep(td) {
|
||||
padding: 15px 18px;
|
||||
border: 1px solid #e7edf8;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
.ueditor-content :deep(th) {
|
||||
color: #14233a;
|
||||
background: #f3f6fc;
|
||||
font-weight: 700;
|
||||
}
|
||||
.ueditor-content :deep(hr) {
|
||||
height: 1px;
|
||||
margin: 42px 0;
|
||||
border: 0;
|
||||
background: #e6edf8;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.ueditor-content {
|
||||
font-size: 15px;
|
||||
line-height: 1.9;
|
||||
}
|
||||
.ueditor-content :deep(h2) {
|
||||
font-size: 21px;
|
||||
}
|
||||
.ueditor-content :deep(h3) {
|
||||
font-size: 19px;
|
||||
}
|
||||
.ueditor-content :deep(blockquote) {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -50,7 +50,7 @@ const sourceLabel = computed(() => {
|
||||
<div>
|
||||
<strong>联系我们</strong>
|
||||
<span class="contact-line"
|
||||
><AppIcon name="location" />成都市武侯区芯通科技大厦 B 座 9 楼</span
|
||||
><AppIcon name="location" />成都市武侯区芯通科技大厦B座9楼</span
|
||||
>
|
||||
<span class="contact-line"><AppIcon name="phone" />联系电话:待补充</span>
|
||||
<span class="contact-line"><AppIcon name="message" />商务邮箱:待补充</span>
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
const ALL_LABEL = '全部'
|
||||
const LATEST_LABEL = '最新文章'
|
||||
const FALLBACK_IMAGE = '/images/lanhu/slices/home-group95-image21@2x.png'
|
||||
|
||||
function pickUrl(asset) {
|
||||
return asset?.url || asset?.fileUrl || asset?.filePath || ''
|
||||
}
|
||||
|
||||
function buildMediaMap(media = []) {
|
||||
return new Map(media.map((asset) => [asset.id, asset]))
|
||||
}
|
||||
|
||||
function toTags(value) {
|
||||
if (Array.isArray(value)) return value.filter(Boolean)
|
||||
return String(value || '')
|
||||
.split(/[,,、\s]+/)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
function bySortAndTime(left, right) {
|
||||
const leftSort = Number.isFinite(Number(left.sortOrder)) ? Number(left.sortOrder) : 9999
|
||||
const rightSort = Number.isFinite(Number(right.sortOrder)) ? Number(right.sortOrder) : 9999
|
||||
if (leftSort !== rightSort) return leftSort - rightSort
|
||||
return String(right.updatedAt || right.publishedAt || '').localeCompare(
|
||||
String(left.updatedAt || left.publishedAt || '')
|
||||
)
|
||||
}
|
||||
|
||||
export function useOfficialContent() {
|
||||
const config = useRuntimeConfig()
|
||||
const serverApiBase = `${String(config.officialApiProxyTarget || 'http://localhost:8080').replace(/\/$/, '')}/api`
|
||||
const apiBase = import.meta.server ? serverApiBase : (config.public.officialApiBase || '/api')
|
||||
|
||||
function fetchPublicContent(type) {
|
||||
console.log(apiBase)
|
||||
return $fetch('/public/content', {
|
||||
baseURL: apiBase,
|
||||
query: { type }
|
||||
})
|
||||
}
|
||||
|
||||
function fetchHomepageSections() {
|
||||
return $fetch('/public/homepage/sections', { baseURL: apiBase })
|
||||
}
|
||||
|
||||
function fetchPublicSiteConfig() {
|
||||
return $fetch('/public/site-config', { baseURL: apiBase })
|
||||
}
|
||||
|
||||
function assetUrl(assetId, mediaMap, fallback = FALLBACK_IMAGE) {
|
||||
if (!assetId) return fallback
|
||||
return pickUrl(mediaMap.get(assetId)) || fallback
|
||||
}
|
||||
|
||||
function assetAlt(assetId, mediaMap, fallback = '') {
|
||||
if (!assetId) return fallback
|
||||
return mediaMap.get(assetId)?.alt || fallback
|
||||
}
|
||||
|
||||
function normalizeCase(item, mediaMap) {
|
||||
const metric = item.metricValue || ''
|
||||
const metricLabel = item.metricLabel || ''
|
||||
const clientName = item.isAnonymous && item.clientName ? `匿名客户:${item.clientName}` : item.clientName
|
||||
|
||||
return {
|
||||
...item,
|
||||
industry: item.industry || item.category || '未分类',
|
||||
client: clientName || '匿名客户',
|
||||
cover: item.coverUrl || assetUrl(item.coverAssetId, mediaMap),
|
||||
coverAlt: item.coverAlt || assetAlt(item.coverAssetId, mediaMap, item.title),
|
||||
summary: item.summary || item.description || '',
|
||||
description: item.description || item.summary || '',
|
||||
metric,
|
||||
metricLabel,
|
||||
metrics: [[metric, metricLabel], [item.secondary, '辅助成果']].filter((row) => row[0]),
|
||||
secondary: item.secondary || '',
|
||||
contentHtml: item.contentHtml || ''
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeArticle(item, mediaMap) {
|
||||
return {
|
||||
...item,
|
||||
category: item.category || '未分类',
|
||||
excerpt: item.summary || item.description || '',
|
||||
date: item.publishDate || item.publishedAt?.slice?.(0, 10) || '',
|
||||
readingTime: item.readingTime || '约 5 分钟',
|
||||
views: item.views || '0',
|
||||
cover: item.coverUrl || assetUrl(item.coverAssetId, mediaMap),
|
||||
coverAlt: item.coverAlt || assetAlt(item.coverAssetId, mediaMap, item.title),
|
||||
featured: Boolean(item.isFeatured),
|
||||
tags: toTags(item.tags),
|
||||
contentHtml: item.contentHtml || ''
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeWhitepaper(item, mediaMap) {
|
||||
const documentAsset = item.documentAssetId ? mediaMap.get(item.documentAssetId) : null
|
||||
|
||||
return {
|
||||
...item,
|
||||
category: item.category || '行业白皮书',
|
||||
excerpt: item.summary || item.description || '',
|
||||
cta: item.cta || '获取白皮书',
|
||||
cover: item.coverUrl || assetUrl(item.coverAssetId, mediaMap),
|
||||
documentUrl: item.documentUrl || pickUrl(documentAsset),
|
||||
documentName: item.documentName || documentAsset?.name || item.title,
|
||||
contentHtml: item.contentHtml || ''
|
||||
}
|
||||
}
|
||||
|
||||
function categoryList(items, field = 'category', extras = []) {
|
||||
const values = items.map((item) => item[field]).filter(Boolean)
|
||||
return [ALL_LABEL, ...extras, ...Array.from(new Set(values))]
|
||||
}
|
||||
|
||||
return {
|
||||
ALL_LABEL,
|
||||
LATEST_LABEL,
|
||||
bySortAndTime,
|
||||
buildMediaMap,
|
||||
fetchPublicContent,
|
||||
fetchHomepageSections,
|
||||
fetchPublicSiteConfig,
|
||||
normalizeCase,
|
||||
normalizeArticle,
|
||||
normalizeWhitepaper,
|
||||
categoryList
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
const officialApiProxyTarget = (process.env.NUXT_OFFICIAL_API_PROXY_TARGET || 'http://localhost:8080').replace(/\/$/, '')
|
||||
|
||||
export default defineNuxtConfig({
|
||||
runtimeConfig: {
|
||||
officialApiProxyTarget,
|
||||
public: {
|
||||
officialApiBase: process.env.NUXT_PUBLIC_OFFICIAL_API_BASE || '/api'
|
||||
}
|
||||
},
|
||||
future: {
|
||||
compatibilityVersion: 3
|
||||
},
|
||||
@@ -13,6 +21,14 @@ export default defineNuxtConfig({
|
||||
}
|
||||
}
|
||||
},
|
||||
nitro: {
|
||||
devProxy: {
|
||||
'/api': {
|
||||
target: `${officialApiProxyTarget}/api`,
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
app: {
|
||||
head: {
|
||||
title: '大马棒 · 云途全域 GEO',
|
||||
|
||||
@@ -5,18 +5,44 @@ import SiteFooter from '~/components/site/SiteFooter.vue'
|
||||
|
||||
const pageRoot = ref(null)
|
||||
const { openConsultation } = useConsultation()
|
||||
const { fetchPublicSiteConfig } = useOfficialContent()
|
||||
let animationContext
|
||||
|
||||
useHead({
|
||||
const { data: siteConfigRows } = await useAsyncData('public-site-config-about', () =>
|
||||
fetchPublicSiteConfig()
|
||||
)
|
||||
|
||||
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: '待补充'
|
||||
})
|
||||
)
|
||||
|
||||
useHead(() => ({
|
||||
title: '关于我们|大马棒·云途全域 GEO',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
brandConfig.value.seoDescription ||
|
||||
'大马棒·云途全域 GEO 是聚焦 AI 搜索增长的全链路服务商,提供可见性诊断、策略规划、内容建设、信源分发与效果复盘。'
|
||||
}
|
||||
]
|
||||
})
|
||||
}))
|
||||
|
||||
const stats = [
|
||||
['1000+', '累计服务客户'],
|
||||
@@ -33,7 +59,7 @@ const serviceFlow = [
|
||||
['05', '效果复盘', '持续监测覆盖率、推荐率、流量与咨询线索质量。']
|
||||
]
|
||||
|
||||
const timeline = [
|
||||
const fallbackTimeline = [
|
||||
{
|
||||
year: '2023',
|
||||
title: '核心团队组建',
|
||||
@@ -58,6 +84,22 @@ const timeline = [
|
||||
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 teamCapabilities = [
|
||||
['搜索理解', '经历 PC 搜索、移动搜索到 AI 搜索的持续变化。'],
|
||||
@@ -211,7 +253,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<section class="method-section">
|
||||
<div class="page-width">
|
||||
<header class="center-heading">
|
||||
<p class="section-kicker">全链路服务方法</p>
|
||||
<p class="section-kicker method-kicker">全链路服务方法</p>
|
||||
<h2>从 AI 可见性诊断,到效果复盘</h2>
|
||||
<p>每一个环节都围绕真实业务目标推进,避免内容、媒体和转化承接各做一段。</p>
|
||||
</header>
|
||||
@@ -289,20 +331,16 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<div class="contact-details">
|
||||
<dl>
|
||||
<div>
|
||||
<dt>公司名称</dt>
|
||||
<dd>成都大马棒传媒有限公司</dd>
|
||||
<dt>咨询电话</dt>
|
||||
<dd>{{ contactConfig.phone || '待补充' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>公司地址</dt>
|
||||
<dd>成都市武侯区芯通科技大厦 B 座 9 楼</dd>
|
||||
<dt>联系邮箱</dt>
|
||||
<dd>{{ contactConfig.email || '待补充' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>联系电话</dt>
|
||||
<dd>待补充</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>商务邮箱</dt>
|
||||
<dd>待补充</dd>
|
||||
<dt>办公地址</dt>
|
||||
<dd>{{ contactConfig.address || '待补充' }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="contact-qr">
|
||||
@@ -819,6 +857,15 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
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;
|
||||
@@ -856,7 +903,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
place-items: center;
|
||||
border: 7px solid rgba(255, 255, 255, 0.92);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
color: #fff !important;
|
||||
background: #358af0;
|
||||
box-shadow: 0 11px 24px rgba(51, 135, 235, 0.22);
|
||||
font-size: 10px;
|
||||
@@ -1104,10 +1151,13 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
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;
|
||||
|
||||
@@ -106,6 +106,20 @@ const advantages = [
|
||||
}
|
||||
]
|
||||
|
||||
const introSequenceIcons = {
|
||||
'human-content': '/images/advantages/intro-human-content.png',
|
||||
'media-network': '/images/advantages/intro-media-network.png',
|
||||
'closed-loop': '/images/advantages/intro-closed-loop.png',
|
||||
'custom-service': '/images/advantages/intro-custom-service.png'
|
||||
}
|
||||
|
||||
const capabilityImages = {
|
||||
'human-content': '/images/advantages/capability-human-content.png',
|
||||
'media-network': '/images/advantages/capability-media-network.png',
|
||||
'closed-loop': '/images/advantages/capability-closed-loop.png',
|
||||
'custom-service': '/images/advantages/capability-custom-service.png'
|
||||
}
|
||||
|
||||
const comparisonRows = [
|
||||
['核心目标', '抢排名、买点击', '蹭热度、抓眼球', '让品牌在 AI 推荐中被选中'],
|
||||
['内容逻辑', '迎合搜索规则', '什么火就写什么', '真实可信,适配 AI 搜索与用户决策'],
|
||||
@@ -120,14 +134,14 @@ const valueAddedServices = [
|
||||
title: '创始人 / 企业 IP 打造',
|
||||
text: '结合品牌调性与创始人特质,搭建差异化人设定位、内容脚本体系与长期更新规划,形成高辨识度的专属 IP。',
|
||||
items: ['人设定位', '选题与脚本', '内容生产', '长期运营'],
|
||||
image: '/images/lanhu/slices/home-group96-image22@2x.png'
|
||||
image: '/images/advantages/founder-ip-visual.png'
|
||||
},
|
||||
{
|
||||
number: '02',
|
||||
title: '短视频与直播获客',
|
||||
text: '从短视频批量产出到直播间常态化运营,配置主播、运营、投流与中控团队,覆盖拍摄、剪辑、投放和转化。',
|
||||
items: ['短视频生产', '直播运营', '投流优化', '成交承接'],
|
||||
image: '/images/lanhu/slices/home-group97-image23@2x.png'
|
||||
image: '/images/advantages/short-video-live-visual.png'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -239,10 +253,19 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
</p>
|
||||
</header>
|
||||
<div class="intro-sequence">
|
||||
<article v-for="advantage in advantages" :key="`intro-${advantage.id}`">
|
||||
<article
|
||||
v-for="advantage in advantages"
|
||||
:key="`intro-${advantage.id}`"
|
||||
:class="`intro-card--${advantage.id}`"
|
||||
>
|
||||
<span>{{ advantage.number }}</span
|
||||
><strong>{{ advantage.short }}</strong>
|
||||
<p>{{ advantage.metric }}</p>
|
||||
<img
|
||||
class="intro-sequence-icon"
|
||||
:src="introSequenceIcons[advantage.id]"
|
||||
:alt="`${advantage.short}图标`"
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
@@ -293,20 +316,10 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<span>{{ advantage.short }}能力模型</span><small>YUNTU CAPABILITY MAP</small>
|
||||
</header>
|
||||
<div class="capability-map">
|
||||
<div class="capability-center">
|
||||
<small>{{ advantage.number }}</small
|
||||
><strong>{{ advantage.short }}</strong>
|
||||
</div>
|
||||
<div
|
||||
v-for="(item, itemIndex) in advantage.visual"
|
||||
:key="item"
|
||||
class="capability-node"
|
||||
:class="`capability-node-${itemIndex + 1}`"
|
||||
>
|
||||
<span>0{{ itemIndex + 1 }}</span
|
||||
><strong>{{ item }}</strong>
|
||||
</div>
|
||||
<i v-for="line in 4" :key="line" :class="`capability-line line-${line}`"></i>
|
||||
<img
|
||||
:src="capabilityImages[advantage.id]"
|
||||
:alt="`${advantage.short}核心能力图`"
|
||||
/>
|
||||
</div>
|
||||
<div class="capability-metric">
|
||||
<strong>{{ advantage.metric }}</strong
|
||||
@@ -777,8 +790,10 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
gap: 14px;
|
||||
}
|
||||
.intro-sequence article {
|
||||
position: relative;
|
||||
min-height: 165px;
|
||||
padding: 26px;
|
||||
overflow: hidden;
|
||||
padding: 26px 118px 26px 26px;
|
||||
border-radius: 14px 5px 14px 5px;
|
||||
background: #f2f7fd;
|
||||
transition: 0.24s;
|
||||
@@ -799,12 +814,58 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
font-size: 17px;
|
||||
}
|
||||
.intro-sequence p {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
margin: 7px 0 0;
|
||||
color: #277fec;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.intro-sequence span,
|
||||
.intro-sequence strong {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.intro-sequence-icon {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 12px;
|
||||
z-index: 1;
|
||||
width: 108px;
|
||||
max-height: 128px;
|
||||
object-fit: contain;
|
||||
pointer-events: none;
|
||||
filter: drop-shadow(0 18px 26px rgba(40, 126, 235, 0.18));
|
||||
transition: transform 0.24s;
|
||||
}
|
||||
.intro-sequence article:hover .intro-sequence-icon {
|
||||
transform: translate3d(0, -4px, 0) scale(1.03);
|
||||
}
|
||||
.intro-card--human-content .intro-sequence-icon {
|
||||
right: 22px;
|
||||
bottom: 24px;
|
||||
width: 66px;
|
||||
max-height: 86px;
|
||||
}
|
||||
.intro-card--media-network .intro-sequence-icon {
|
||||
right: 16px;
|
||||
bottom: 18px;
|
||||
width: 106px;
|
||||
max-height: 112px;
|
||||
}
|
||||
.intro-card--closed-loop .intro-sequence-icon {
|
||||
right: 12px;
|
||||
bottom: 41x;
|
||||
width: 100px;
|
||||
max-height: 128px;
|
||||
}
|
||||
.intro-card--custom-service .intro-sequence-icon {
|
||||
right: 2px;
|
||||
bottom: -4px;
|
||||
width: 130px;
|
||||
max-height: 132px;
|
||||
}
|
||||
.advantage-story {
|
||||
scroll-margin-top: 80px;
|
||||
padding: 116px 0 132px;
|
||||
@@ -919,20 +980,25 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
.story-action {
|
||||
display: inline-flex;
|
||||
min-width: 164px;
|
||||
min-height: 46px;
|
||||
margin-top: 24px;
|
||||
padding: 0 0 5px;
|
||||
border-bottom: 1px solid #8eb9e9;
|
||||
color: #247be8;
|
||||
background: transparent;
|
||||
padding: 0 26px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 9px;
|
||||
white-space: nowrap;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.story-action b {
|
||||
margin-left: 8px;
|
||||
transition: margin 0.2s;
|
||||
.story-action :deep(.app-icon) {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.story-action:hover b {
|
||||
margin-left: 13px;
|
||||
.story-action:hover :deep(.app-icon) {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
.advantage-story-visual {
|
||||
position: relative;
|
||||
@@ -978,110 +1044,14 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
position: absolute;
|
||||
top: 52%;
|
||||
left: 50%;
|
||||
width: 410px;
|
||||
height: 360px;
|
||||
width: min(88%, 460px);
|
||||
height: 400px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.capability-map::before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
content: '';
|
||||
border: 1px dashed rgba(55, 137, 232, 0.34);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.capability-center {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 142px;
|
||||
height: 142px;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
justify-items: center;
|
||||
border: 11px solid rgba(255, 255, 255, 0.6);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: linear-gradient(145deg, #3185ee, #50bce7);
|
||||
box-shadow: 0 22px 42px rgba(36, 123, 225, 0.28);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.capability-center small {
|
||||
font-size: 9px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.capability-center strong {
|
||||
margin-top: 5px;
|
||||
font-size: 17px;
|
||||
}
|
||||
.capability-node {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
min-width: 110px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.92);
|
||||
border-radius: 7px;
|
||||
color: #4e7198;
|
||||
background: rgba(255, 255, 255, 0.84);
|
||||
box-shadow: 0 12px 25px rgba(54, 113, 185, 0.11);
|
||||
text-align: center;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
.capability-node span {
|
||||
display: block;
|
||||
color: #91a9c3;
|
||||
font-size: 8px;
|
||||
}
|
||||
.capability-node strong {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.capability-node-1 {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.capability-node-2 {
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.capability-node-3 {
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.capability-node-4 {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.capability-line {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 2px;
|
||||
height: 135px;
|
||||
background: linear-gradient(#5aa1ed, transparent);
|
||||
transform-origin: top;
|
||||
}
|
||||
.line-1 {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.line-2 {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.line-3 {
|
||||
transform: rotate(0);
|
||||
}
|
||||
.line-4 {
|
||||
transform: rotate(-90deg);
|
||||
.capability-map img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.capability-metric {
|
||||
position: absolute;
|
||||
@@ -1140,7 +1110,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
font-size: 11px;
|
||||
}
|
||||
.comparison-table-wrap thead th:last-child {
|
||||
color: #fff;
|
||||
color: #fff !important;
|
||||
background: #3187ee;
|
||||
}
|
||||
.comparison-table-wrap thead span {
|
||||
@@ -1193,17 +1163,26 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
}
|
||||
.value-added-image {
|
||||
position: relative;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
overflow: hidden;
|
||||
background: #e5f1ff;
|
||||
background:
|
||||
radial-gradient(circle at 28% 20%, rgba(255, 255, 255, 0.86) 0, rgba(255, 255, 255, 0) 31%),
|
||||
radial-gradient(circle at 72% 32%, rgba(96, 207, 255, 0.36) 0, rgba(96, 207, 255, 0) 34%),
|
||||
linear-gradient(135deg, #edf7ff 0%, #d8efff 48%, #f2edff 100%);
|
||||
}
|
||||
.value-added-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: min(108%, 560px);
|
||||
height: min(92%, 370px);
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 24px 34px rgba(34, 122, 229, 0.18));
|
||||
}
|
||||
.value-added-image > span {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
display: grid;
|
||||
@@ -1327,10 +1306,13 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
url('/images/lanhu/slices/home-group105-image31@2x.png') center / cover no-repeat;
|
||||
}
|
||||
.advantages-cta-content {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
padding: 75px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.advantages-cta-content > p {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: #237df0;
|
||||
font-size: 12px;
|
||||
@@ -1442,6 +1424,31 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
}
|
||||
.intro-sequence article {
|
||||
min-height: 140px;
|
||||
padding-right: 118px;
|
||||
}
|
||||
.intro-sequence-icon {
|
||||
right: 14px;
|
||||
bottom: 10px;
|
||||
width: 96px;
|
||||
max-height: 106px;
|
||||
}
|
||||
.intro-card--human-content .intro-sequence-icon {
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
width: 68px;
|
||||
}
|
||||
.intro-card--media-network .intro-sequence-icon {
|
||||
right: 14px;
|
||||
bottom: 16px;
|
||||
width: 94px;
|
||||
max-height: 100px;
|
||||
}
|
||||
.intro-card--closed-loop .intro-sequence-icon,
|
||||
.intro-card--custom-service .intro-sequence-icon {
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 108px;
|
||||
max-height: 112px;
|
||||
}
|
||||
.advantage-story-copy h2 {
|
||||
font-size: 31px;
|
||||
@@ -1450,25 +1457,9 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
min-height: 430px;
|
||||
}
|
||||
.capability-map {
|
||||
width: 310px;
|
||||
width: min(92%, 320px);
|
||||
height: 280px;
|
||||
}
|
||||
.capability-map::before {
|
||||
width: 205px;
|
||||
height: 205px;
|
||||
}
|
||||
.capability-center {
|
||||
width: 105px;
|
||||
height: 105px;
|
||||
border-width: 8px;
|
||||
}
|
||||
.capability-node {
|
||||
min-width: 83px;
|
||||
padding: 9px;
|
||||
}
|
||||
.capability-line {
|
||||
height: 100px;
|
||||
}
|
||||
.capability-metric {
|
||||
right: 18px;
|
||||
bottom: 17px;
|
||||
@@ -1486,6 +1477,10 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
.value-added-image {
|
||||
min-height: 260px;
|
||||
}
|
||||
.value-added-image img {
|
||||
width: min(112%, 430px);
|
||||
height: 230px;
|
||||
}
|
||||
.value-added-copy {
|
||||
padding: 32px 23px;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,30 @@
|
||||
<script setup>
|
||||
import SiteHeader from '~/components/site/SiteHeader.vue'
|
||||
import SiteFooter from '~/components/site/SiteFooter.vue'
|
||||
import { caseCategories, featuredCase, resultSnapshots } from '~/data/cases'
|
||||
const { ALL_LABEL, bySortAndTime, categoryList, fetchPublicContent, normalizeCase } =
|
||||
useOfficialContent()
|
||||
|
||||
const activeCategory = ref('全部')
|
||||
const activeCategory = ref(ALL_LABEL)
|
||||
const { openConsultation } = useConsultation()
|
||||
|
||||
const { data: caseRows } = await useAsyncData('public-cases', async () => {
|
||||
const rows = await fetchPublicContent('CASE')
|
||||
return rows.sort(bySortAndTime).map((item) => normalizeCase(item, new Map()))
|
||||
})
|
||||
|
||||
const cases = computed(() => caseRows.value || [])
|
||||
const caseCategories = computed(() => categoryList(cases.value, 'industry'))
|
||||
const featuredCase = computed(
|
||||
() =>
|
||||
cases.value.find((item) => item.isFeatured) ||
|
||||
cases.value.find((item) => item.isFullCase) ||
|
||||
cases.value[0] ||
|
||||
null
|
||||
)
|
||||
const resultSnapshots = computed(() =>
|
||||
cases.value.filter((item) => item.id !== featuredCase.value?.id)
|
||||
)
|
||||
|
||||
useHead({
|
||||
title: '客户案例|大马棒·云途全域 GEO',
|
||||
meta: [
|
||||
@@ -17,12 +36,13 @@ useHead({
|
||||
]
|
||||
})
|
||||
|
||||
const showFeatured = computed(
|
||||
() => activeCategory.value === '全部' || activeCategory.value === featuredCase.industry
|
||||
)
|
||||
const showFeatured = computed(() => {
|
||||
if (!featuredCase.value) return false
|
||||
return activeCategory.value === ALL_LABEL || activeCategory.value === featuredCase.value.industry
|
||||
})
|
||||
const visibleSnapshots = computed(() => {
|
||||
if (activeCategory.value === '全部') return resultSnapshots
|
||||
return resultSnapshots.filter((item) => item.industry === activeCategory.value)
|
||||
if (activeCategory.value === ALL_LABEL) return resultSnapshots.value
|
||||
return resultSnapshots.value.filter((item) => item.industry === activeCategory.value)
|
||||
})
|
||||
const hasResults = computed(() => showFeatured.value || visibleSnapshots.value.length > 0)
|
||||
|
||||
@@ -141,7 +161,7 @@ function requestCustomPlan(source) {
|
||||
<article
|
||||
v-for="(snapshot, index) in visibleSnapshots"
|
||||
:key="`${activeCategory}-${snapshot.title}`"
|
||||
:class="{ wide: index === 0 && activeCategory === '全部' }"
|
||||
:class="{ wide: index === 0 && activeCategory === ALL_LABEL }"
|
||||
>
|
||||
<div class="snapshot-image">
|
||||
<img :src="snapshot.cover" :alt="`${snapshot.industry}结果快照`" /><span>{{
|
||||
@@ -853,10 +873,13 @@ function requestCustomPlan(source) {
|
||||
url('/images/lanhu/slices/home-group105-image31@2x.png') center / cover no-repeat;
|
||||
}
|
||||
.cases-cta-content {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
padding: 75px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.cases-cta-content > p {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: #237df0;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -6,10 +6,28 @@ import SiteFooter from '~/components/site/SiteFooter.vue'
|
||||
|
||||
const pageRoot = ref(null)
|
||||
const { openConsultation: openGlobalConsultation } = useConsultation()
|
||||
const { fetchHomepageSections } = useOfficialContent()
|
||||
let animationContext
|
||||
let animationMedia
|
||||
|
||||
const logos = [
|
||||
const { data: homepageSectionRows } = await useAsyncData('public-homepage-sections', () =>
|
||||
fetchHomepageSections()
|
||||
)
|
||||
|
||||
const homepageSections = computed(() => homepageSectionRows.value || [])
|
||||
const homepageSectionMap = computed(() =>
|
||||
Object.fromEntries(homepageSections.value.map((section) => [section.key, section]))
|
||||
)
|
||||
|
||||
function homepageSection(key) {
|
||||
return homepageSectionMap.value[key] || {}
|
||||
}
|
||||
|
||||
function backgroundStyle(url) {
|
||||
return url ? { backgroundImage: `url("${url}")` } : null
|
||||
}
|
||||
|
||||
const fallbackLogos = [
|
||||
'Bond',
|
||||
'WaSun',
|
||||
'西西能源',
|
||||
@@ -23,17 +41,18 @@ const logos = [
|
||||
'SUNAC',
|
||||
'B+ WORKS'
|
||||
]
|
||||
const stats = [
|
||||
const fallbackStats = [
|
||||
['300+', '累计服务客户', '/images/lanhu/slices/home-group100-image26@2x.png'],
|
||||
['12+', '覆盖行业', '/images/lanhu/slices/home-group101-image27@2x.png'],
|
||||
['126%', '客户AI搜索曝光平均提升', '/images/lanhu/slices/home-group102-image28@2x.png'],
|
||||
['65%', '客户转化链路效率平均提升', '/images/lanhu/slices/home-group103-image29@2x.png']
|
||||
]
|
||||
const corePoints = [
|
||||
const heroBackgroundImage = '/images/lanhu/slices/hero-geo-visual@2x.png'
|
||||
const fallbackCorePoints = [
|
||||
['曝光', '打造AI搜索语境下的品牌信任声量,一次布局,长期复用'],
|
||||
['获客', '让曝光直接沉淀为可跟进的精准线索,告别无效流量']
|
||||
]
|
||||
const ringModels = [
|
||||
const fallbackRingModels = [
|
||||
{
|
||||
title: '声量资产环',
|
||||
image: '/images/lanhu/slices/home-group80-group83-image11@2x.png',
|
||||
@@ -47,18 +66,18 @@ const ringModels = [
|
||||
labels: ['AI搜索曝光', '精准流量承接', '全链路转化', '数据复盘优化']
|
||||
}
|
||||
]
|
||||
const advantageCards = [
|
||||
const fallbackAdvantageCards = [
|
||||
['全域媒体资源优势', '5000+权威官媒+10万+优质自媒体矩阵'],
|
||||
['全链路闭环优势', '行业唯一打通「纯曝光+内容资产沉淀+转化闭环」'],
|
||||
['全客群定制优势', '覆盖全类型经营主体,一对一专属定制专属方案']
|
||||
]
|
||||
const caseImages = [
|
||||
const fallbackCaseImages = [
|
||||
'/images/lanhu/slices/home-group90-image15@2x.png',
|
||||
'/images/lanhu/slices/home-group91-image16@2x.png',
|
||||
'/images/lanhu/slices/home-group92-image17@2x.png',
|
||||
'/images/lanhu/slices/home-group93-image18@2x.png'
|
||||
]
|
||||
const industryCards = [
|
||||
const fallbackIndustryCards = [
|
||||
[
|
||||
'本地生活',
|
||||
'AI搜索全域曝光提升320%月均精准线索新增80+,持续获得品牌声量与业务线索',
|
||||
@@ -75,7 +94,7 @@ const industryCards = [
|
||||
'/images/lanhu/slices/home-group36-group71-image5@2x.png'
|
||||
]
|
||||
]
|
||||
const deliverySteps = [
|
||||
const fallbackDeliverySteps = [
|
||||
[
|
||||
'需求诊断',
|
||||
'一对一沟通,分析品牌现状与增长痛点',
|
||||
@@ -103,6 +122,112 @@ const deliverySteps = [
|
||||
]
|
||||
]
|
||||
|
||||
const heroSection = computed(() => homepageSection('HERO'))
|
||||
const customerHallSection = computed(() => homepageSection('CUSTOMER_HALL'))
|
||||
const capabilitiesSection = computed(() => homepageSection('CAPABILITIES'))
|
||||
const advantagesSection = computed(() => homepageSection('ADVANTAGES'))
|
||||
const caseBlockSection = computed(() => homepageSection('CASE_BLOCK'))
|
||||
const industryBlockSection = computed(() => homepageSection('INDUSTRY_BLOCK'))
|
||||
const processSection = computed(() => homepageSection('PROCESS'))
|
||||
const testimonialSection = computed(() => homepageSection('TESTIMONIAL'))
|
||||
const bottomCtaSection = computed(() => homepageSection('BOTTOM_CTA'))
|
||||
|
||||
const heroTitle = computed(
|
||||
() => heroSection.value.title || '大马棒 · 云途全域GEO\n让品牌在AI时代拥有持续增长力'
|
||||
)
|
||||
const heroTags = computed(() =>
|
||||
heroSection.value.tags?.length
|
||||
? heroSection.value.tags
|
||||
: ['5万真人内容生产网络', '5000+自媒体资源矩阵', '全链路转化闭环']
|
||||
)
|
||||
const logos = computed(() => fallbackLogos)
|
||||
const stats = computed(() => {
|
||||
const cards = customerHallSection.value.cards
|
||||
if (!cards?.length) return fallbackStats
|
||||
return cards.map((card, index) => [
|
||||
card.value,
|
||||
card.label,
|
||||
fallbackStats[index % fallbackStats.length][2]
|
||||
])
|
||||
})
|
||||
const corePoints = computed(() => {
|
||||
const cards = capabilitiesSection.value.cards
|
||||
if (!cards?.length) return fallbackCorePoints
|
||||
|
||||
return cards.slice(0, 2).map((card, index) => [
|
||||
card.title || fallbackCorePoints[index]?.[0] || '',
|
||||
card.details?.[0]?.description || card.details?.[0]?.heading || fallbackCorePoints[index]?.[1] || ''
|
||||
])
|
||||
})
|
||||
const ringModels = computed(() => fallbackRingModels)
|
||||
const leadAdvantage = computed(() => {
|
||||
const groups = advantagesSection.value.groups || []
|
||||
const lead = groups[0]
|
||||
return {
|
||||
title: lead?.heading || '真人内容生产优势',
|
||||
bodyOne: lead?.bodyOne || '行业独家5万真人分布式内容生产网络',
|
||||
bodyTwo: lead?.bodyTwo || '用C端爆款内容思维做B端GEO,打造真实可信的AI信任型声量',
|
||||
image: advantagesSection.value.assetUrl || '/images/lanhu/slices/home-group90-image15@2x.png'
|
||||
}
|
||||
})
|
||||
const advantageCards = computed(() => {
|
||||
const groups = advantagesSection.value.groups?.slice(1)
|
||||
if (!groups?.length) return fallbackAdvantageCards
|
||||
return groups.map((group) => [
|
||||
group.heading,
|
||||
[group.bodyOne, group.bodyTwo].filter(Boolean).join(';')
|
||||
])
|
||||
})
|
||||
const caseCards = computed(() => {
|
||||
const contents = caseBlockSection.value.contents
|
||||
if (!contents?.length) {
|
||||
return fallbackCaseImages.map((image) => ({
|
||||
image,
|
||||
description: '某企业服务客户 AI搜索全域曝光提升\n320%月均精准线索新增80+'
|
||||
}))
|
||||
}
|
||||
return contents.map((item, index) => ({
|
||||
image:
|
||||
item.imageUrl ||
|
||||
item.assetUrl ||
|
||||
item.url ||
|
||||
item.image ||
|
||||
fallbackCaseImages[index % fallbackCaseImages.length],
|
||||
description: item.description || ''
|
||||
}))
|
||||
})
|
||||
const industryCards = computed(() => {
|
||||
const groups = industryBlockSection.value.groups
|
||||
if (!groups?.length) return fallbackIndustryCards
|
||||
return groups.map((group, index) => [
|
||||
group.title,
|
||||
group.description,
|
||||
group.imageUrl || fallbackIndustryCards[index % fallbackIndustryCards.length][2],
|
||||
group.tags || []
|
||||
])
|
||||
})
|
||||
const deliverySteps = computed(() => {
|
||||
const groups = processSection.value.groups
|
||||
if (!groups?.length) return fallbackDeliverySteps
|
||||
return groups.map((group, index) => [
|
||||
group.heading,
|
||||
group.body,
|
||||
fallbackDeliverySteps[index % fallbackDeliverySteps.length][2]
|
||||
])
|
||||
})
|
||||
const testimonials = computed(() => {
|
||||
const groups = testimonialSection.value.groups
|
||||
if (!groups?.length) {
|
||||
return Array.from({ length: 5 }, (_, index) => ({
|
||||
name: '数据优化:',
|
||||
date: `2026-12-${42 + index}`,
|
||||
description:
|
||||
'创作者每日必读的前沿设计趋势、设计方法论和大厂落地经验之谈,14年的行业专注,脑突入口的优质内容沉淀,为每一个从入行到进阶的设计师、创作者赋能。'
|
||||
}))
|
||||
}
|
||||
return groups
|
||||
})
|
||||
|
||||
function requestConsultation(source, title = '预约免费 GEO 增长诊断') {
|
||||
openGlobalConsultation({ title, source })
|
||||
}
|
||||
@@ -372,14 +497,21 @@ onBeforeUnmount(() => {
|
||||
<SiteHeader />
|
||||
|
||||
<main>
|
||||
<section class="hero-section">
|
||||
<div class="hero-art" aria-hidden="true"></div>
|
||||
<section class="hero-section">
|
||||
<div
|
||||
class="hero-art"
|
||||
:style="backgroundStyle(heroBackgroundImage)"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
<div class="page-width hero-content">
|
||||
<div class="hero-copy">
|
||||
<h1>大马棒 · 云途全域GEO<br />让品牌在AI时代拥有持续增长力</h1>
|
||||
<h1>
|
||||
<template v-for="(line, index) in heroTitle.split('\n')" :key="`${line}-${index}`">
|
||||
<br v-if="index" />{{ line }}
|
||||
</template>
|
||||
</h1>
|
||||
<p class="hero-points">
|
||||
<span>✓ 5万真人内容生产网络</span><span>✓ 5000+自媒体资源矩阵</span
|
||||
><span>✓ 全链路转化闭环</span>
|
||||
<span v-for="tag in heroTags" :key="tag">✓ {{ tag }}</span>
|
||||
</p>
|
||||
<div class="button-row">
|
||||
<button
|
||||
@@ -407,8 +539,8 @@ onBeforeUnmount(() => {
|
||||
|
||||
<section class="intro-section page-width">
|
||||
<SectionTitle
|
||||
>已服务<span class="blue">300+</span>全类型经营主体,覆盖<span class="blue">12+</span
|
||||
>主流行业<template #subtitle
|
||||
>{{ customerHallSection.title || '已服务300+全类型经营主体,覆盖12+主流行业'
|
||||
}}<template #subtitle
|
||||
>We Have Provided Services To Over 300 Full-spectrum Business Entities<br />Spanning
|
||||
More Than A Dozen Mainstream Industry Sectors</template
|
||||
></SectionTitle
|
||||
@@ -424,8 +556,8 @@ onBeforeUnmount(() => {
|
||||
<section id="model" class="model-section">
|
||||
<div class="page-width">
|
||||
<SectionTitle
|
||||
>独创<span class="blue">「GEO双环增长模型」</span>,实现品效协同长效增长<template
|
||||
#subtitle
|
||||
>{{ capabilitiesSection.title || '独创「GEO双环增长模型」,实现品效协同长效增长'
|
||||
}}<template #subtitle
|
||||
>Original "geo Dual-ring Growth Model" Delivers Long-term Growth Through<br />Integrated
|
||||
Brand Building And Conversion Performance</template
|
||||
></SectionTitle
|
||||
@@ -476,16 +608,15 @@ onBeforeUnmount(() => {
|
||||
<section id="advantages" class="advantages-section">
|
||||
<div class="page-width">
|
||||
<SectionTitle
|
||||
><span class="blue">四大核心</span>优势<template #subtitle
|
||||
>Four Core Advantages</template
|
||||
></SectionTitle
|
||||
>{{ advantagesSection.title || '四大核心优势'
|
||||
}}<template #subtitle>Four Core Advantages</template></SectionTitle
|
||||
>
|
||||
<div class="lead-advantage">
|
||||
<img src="/images/lanhu/slices/home-group90-image15@2x.png" alt="真人内容生产" />
|
||||
<img :src="leadAdvantage.image" :alt="leadAdvantage.title" />
|
||||
<div>
|
||||
<h3>真人内容生产优势</h3>
|
||||
<p><b>核心点:</b>行业独家5万真人分布式内容生产网络</p>
|
||||
<p><b>价值:</b>用C端爆款内容思维做B端GEO,打造真实可信的AI信任型声量</p>
|
||||
<h3>{{ leadAdvantage.title }}</h3>
|
||||
<p><b>核心点:</b>{{ leadAdvantage.bodyOne }}</p>
|
||||
<p><b>价值:</b>{{ leadAdvantage.bodyTwo }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="advantage-grid">
|
||||
@@ -508,15 +639,15 @@ onBeforeUnmount(() => {
|
||||
<div class="case-background" aria-hidden="true"></div>
|
||||
<div class="page-width case-content">
|
||||
<SectionTitle
|
||||
><span class="blue">真实落地成果</span>,见证<span class="blue">增长实效</span
|
||||
><template #subtitle
|
||||
>{{ caseBlockSection.title || '真实落地成果,见证增长实效'
|
||||
}}<template #subtitle
|
||||
>Practical Delivered Results That Demonstrate Tangible Growth Outcomes</template
|
||||
></SectionTitle
|
||||
>
|
||||
<div class="case-panel">
|
||||
<article v-for="(image, index) in caseImages" :key="image">
|
||||
<img :src="image" :alt="`客户案例 ${index + 1}`" />
|
||||
<p>某企业服务客户: AI搜索全域曝光提升<br />320%月均精准线索新增80+</p>
|
||||
<article v-for="(item, index) in caseCards" :key="`${item.image}-${index}`">
|
||||
<img :src="item.image" :alt="`客户案例 ${index + 1}`" />
|
||||
<p>{{ item.description }}</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="center-action">
|
||||
@@ -527,7 +658,8 @@ onBeforeUnmount(() => {
|
||||
|
||||
<section id="industries" class="industries-section page-width">
|
||||
<SectionTitle
|
||||
>深耕<span class="blue">12+</span>行业,定制专属GEO增长方案<template #subtitle
|
||||
>{{ industryBlockSection.title || '深耕12+行业,定制专属GEO增长方案'
|
||||
}}<template #subtitle
|
||||
>With In-depth Experience Across 12+ Industries, We Craft Exclusive Geo Growth
|
||||
Solutions<br />Tailored To Clients’ Needs</template
|
||||
></SectionTitle
|
||||
@@ -538,7 +670,11 @@ onBeforeUnmount(() => {
|
||||
<img :src="card[2]" alt="" />
|
||||
<div class="quote">“</div>
|
||||
<p>某企业服务客户:<br />{{ card[1] }}</p>
|
||||
<div class="tags"><span>#生活服务</span><span>#全域曝光</span></div>
|
||||
<div class="tags">
|
||||
<span v-for="tag in card[3] || ['生活服务', '全域曝光']" :key="`${card[0]}-${tag}`"
|
||||
>#{{ tag }}</span
|
||||
>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
@@ -546,12 +682,13 @@ onBeforeUnmount(() => {
|
||||
<section id="delivery" class="delivery-section">
|
||||
<div class="page-width">
|
||||
<SectionTitle
|
||||
><span class="blue">5步标准化</span>交付流程,透明可控效果可追溯<template #subtitle
|
||||
>{{ processSection.title || '5步标准化交付流程,透明可控效果可追溯'
|
||||
}}<template #subtitle
|
||||
>With In-depth Experience Across 12+ Industries, We Craft Exclusive Geo Growth
|
||||
Solutions<br />Tailored To Clients’ Needs</template
|
||||
></SectionTitle
|
||||
>
|
||||
<div class="delivery-banner"></div>
|
||||
<div class="delivery-banner" :style="backgroundStyle(processSection.assetUrl)"></div>
|
||||
<div class="delivery-grid">
|
||||
<article v-for="step in deliverySteps" :key="step[0]">
|
||||
<img :src="step[2]" alt="" />
|
||||
@@ -567,29 +704,34 @@ onBeforeUnmount(() => {
|
||||
<section class="testimonial-section">
|
||||
<div class="page-width">
|
||||
<SectionTitle
|
||||
>客户真实评价,见证<span class="blue">服务品质</span
|
||||
><template #subtitle
|
||||
>{{ testimonialSection.title || '客户真实评价,见证服务品质'
|
||||
}}<template #subtitle
|
||||
>Genuine Client Testimonials Attest To Our Service Quality</template
|
||||
></SectionTitle
|
||||
>
|
||||
<div class="testimonial-track">
|
||||
<article v-for="index in 5" :key="index">
|
||||
<header><span class="avatar"></span><b>数据优化:</b><time>2026-12-42</time></header>
|
||||
<p>
|
||||
创作者每日必读的前沿设计趋势、设计方法论和大厂落地经验之谈,14年的行业专注,脑突入口的优质内容沉淀,为每一个从入行到进阶的设计师、创作者赋能。
|
||||
</p>
|
||||
<article v-for="(item, index) in testimonials" :key="`${item.name}-${index}`">
|
||||
<header>
|
||||
<span class="avatar" :style="backgroundStyle(item.avatarUrl)"></span
|
||||
><b>{{ item.name }}</b
|
||||
><time>{{ item.date }}</time>
|
||||
</header>
|
||||
<p>{{ item.description }}</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta-section">
|
||||
<div class="cta-art"></div>
|
||||
<div class="cta-art" :style="backgroundStyle(bottomCtaSection.assetUrl)"></div>
|
||||
<div class="cta-content">
|
||||
<h2>
|
||||
AI搜索增长风口已至,大马棒 · 云途全域GEO助<br />力企业打造品效双闭环的长效增长体系
|
||||
{{
|
||||
bottomCtaSection.title ||
|
||||
'AI搜索增长风口已至,大马棒 · 云途全域GEO助力企业打造品效双闭环的长效增长体系'
|
||||
}}
|
||||
</h2>
|
||||
<p>免费获取1对1GEO增长诊断方案</p>
|
||||
<p>{{ bottomCtaSection.subtitle || '免费获取1对1GEO增长诊断方案' }}</p>
|
||||
<button class="primary-button" type="button" @click="requestConsultation('首页底部 CTA')">
|
||||
立即免费咨询 <b>→</b>
|
||||
</button>
|
||||
|
||||
@@ -1,12 +1,43 @@
|
||||
<script setup>
|
||||
import SiteHeader from '~/components/site/SiteHeader.vue'
|
||||
import SiteFooter from '~/components/site/SiteFooter.vue'
|
||||
import { featuredInsight, insightCategories, insights } from '~/data/insights'
|
||||
|
||||
const activeCategory = ref('全部')
|
||||
const {
|
||||
ALL_LABEL,
|
||||
LATEST_LABEL,
|
||||
bySortAndTime,
|
||||
categoryList,
|
||||
fetchPublicContent,
|
||||
normalizeArticle,
|
||||
normalizeWhitepaper
|
||||
} = useOfficialContent()
|
||||
|
||||
const activeCategory = ref(ALL_LABEL)
|
||||
const visibleCount = ref(4)
|
||||
const { openConsultation } = useConsultation()
|
||||
|
||||
const { data: pageData } = await useAsyncData('public-insights', async () => {
|
||||
const [articleRows, whitepaperRows] = await Promise.all([
|
||||
fetchPublicContent('ARTICLE'),
|
||||
fetchPublicContent('WHITEPAPER')
|
||||
])
|
||||
|
||||
return {
|
||||
articles: articleRows.sort(bySortAndTime).map((item) => normalizeArticle(item, new Map())),
|
||||
whitepapers: whitepaperRows.sort(bySortAndTime).map((item) => normalizeWhitepaper(item, new Map()))
|
||||
}
|
||||
})
|
||||
|
||||
const insights = computed(() => pageData.value?.articles || [])
|
||||
const whitepapers = computed(() => pageData.value?.whitepapers || [])
|
||||
const featuredInsight = computed(
|
||||
() => insights.value.find((item) => item.featured || item.isFeatured) || insights.value[0] || null
|
||||
)
|
||||
const featuredWhitepaper = computed(
|
||||
() => whitepapers.value.find((item) => item.isFeatured) || whitepapers.value[0] || null
|
||||
)
|
||||
const insightCategories = computed(() => categoryList(insights.value, 'category', [LATEST_LABEL]))
|
||||
|
||||
useHead({
|
||||
title: '增长洞察|大马棒·云途全域 GEO',
|
||||
meta: [
|
||||
@@ -19,9 +50,9 @@ useHead({
|
||||
})
|
||||
|
||||
const filteredInsights = computed(() => {
|
||||
const list = insights.filter((item) => !item.featured)
|
||||
if (activeCategory.value === '全部') return list
|
||||
if (activeCategory.value === '最新文章') return list.slice(0, 3)
|
||||
const list = insights.value.filter((item) => item.slug !== featuredInsight.value?.slug)
|
||||
if (activeCategory.value === ALL_LABEL) return list
|
||||
if (activeCategory.value === LATEST_LABEL) return list.slice(0, 3)
|
||||
return list.filter((item) => item.category === activeCategory.value)
|
||||
})
|
||||
const visibleInsights = computed(() => filteredInsights.value.slice(0, visibleCount.value))
|
||||
@@ -36,12 +67,25 @@ function requestDiagnosis(source) {
|
||||
}
|
||||
|
||||
function requestWhitepaper(source) {
|
||||
if (featuredWhitepaper.value?.documentUrl) {
|
||||
window.open(featuredWhitepaper.value.documentUrl, '_blank', 'noopener,noreferrer')
|
||||
return
|
||||
}
|
||||
|
||||
openConsultation({
|
||||
title: '获取 2026 AI 搜索与品牌增长观察',
|
||||
need: '行业白皮书',
|
||||
title: featuredWhitepaper.value?.title || '获取行业白皮书',
|
||||
need: featuredWhitepaper.value?.title || '行业白皮书',
|
||||
source
|
||||
})
|
||||
}
|
||||
function articleTags(article) {
|
||||
if (article.tags?.length) return article.tags
|
||||
const baseTags = ['GEO', '生成式引擎优化', 'AI搜索营销', 'SEO', '内容营销']
|
||||
if (article.slug?.includes('report')) return [...baseTags, '行业报告']
|
||||
if (article.slug?.includes('matrix')) return [...baseTags, '信源建设']
|
||||
if (article.slug?.includes('metrics')) return [...baseTags, '增长指标']
|
||||
return baseTags
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -88,7 +132,7 @@ function requestWhitepaper(source) {
|
||||
<p>AI 不只是新的流量入口,它正在改变用户理解品牌、比较方案和做出选择的方式。</p>
|
||||
</header>
|
||||
|
||||
<article class="featured-insight">
|
||||
<article v-if="featuredInsight" class="featured-insight">
|
||||
<NuxtLink :to="`/insights/${featuredInsight.slug}`" class="featured-image">
|
||||
<img :src="featuredInsight.cover" :alt="featuredInsight.title" />
|
||||
<span>EDITOR'S PICK</span>
|
||||
@@ -142,10 +186,16 @@ function requestWhitepaper(source) {
|
||||
<time>{{ article.date }}</time
|
||||
><span>{{ article.views }} 阅读</span>
|
||||
</div>
|
||||
<span class="article-category">{{ article.category }}</span>
|
||||
<h3>
|
||||
<NuxtLink :to="`/insights/${article.slug}`">{{ article.title }}</NuxtLink>
|
||||
</h3>
|
||||
<p>{{ article.excerpt }}</p>
|
||||
<div class="article-tags" aria-label="文章标签">
|
||||
<span v-for="tag in articleTags(article)" :key="`${article.slug}-${tag}`">{{
|
||||
tag
|
||||
}}</span>
|
||||
</div>
|
||||
<NuxtLink :to="`/insights/${article.slug}`" class="read-link"
|
||||
>查看详情 <AppIcon name="arrow-right"
|
||||
/></NuxtLink>
|
||||
@@ -177,12 +227,12 @@ function requestWhitepaper(source) {
|
||||
<div class="page-width whitepaper-grid">
|
||||
<div class="whitepaper-number"><span>REPORT</span><strong>2026</strong></div>
|
||||
<div class="whitepaper-copy">
|
||||
<p>行业白皮书</p>
|
||||
<h2>AI 搜索与品牌增长观察</h2>
|
||||
<span>用户行为 · 内容信源 · 衡量框架 · 行业实践</span>
|
||||
<p>{{ featuredWhitepaper?.category || '行业白皮书' }}</p>
|
||||
<h2>{{ featuredWhitepaper?.title || 'AI 搜索与品牌增长观察' }}</h2>
|
||||
<span>{{ featuredWhitepaper?.excerpt || '用户行为 · 内容信源 · 衡量框架 · 行业实践' }}</span>
|
||||
</div>
|
||||
<button type="button" @click="requestWhitepaper('增长洞察页白皮书')">
|
||||
获取白皮书 <AppIcon name="arrow-right" />
|
||||
{{ featuredWhitepaper?.cta || '获取白皮书' }} <AppIcon name="arrow-right" />
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
@@ -493,43 +543,78 @@ function requestWhitepaper(source) {
|
||||
}
|
||||
.insight-filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 75px;
|
||||
padding-bottom: 18px;
|
||||
border-bottom: 1px solid #e0e9f3;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
gap: clamp(20px, 3.2vw, 44px);
|
||||
width: min(100%, 980px);
|
||||
margin: 72px auto 0;
|
||||
padding: 0 6px;
|
||||
overflow-x: auto;
|
||||
border-bottom: 0;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.insight-filters::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.insight-filters button {
|
||||
height: 38px;
|
||||
padding: 0 17px;
|
||||
border-radius: 4px;
|
||||
color: #61758c;
|
||||
background: #f1f6fc;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
height: 54px;
|
||||
padding: 0 8px;
|
||||
border-radius: 0;
|
||||
color: #101827;
|
||||
background: transparent;
|
||||
font-size: 22px !important;
|
||||
font-weight: 500;
|
||||
transition: 0.2s;
|
||||
}
|
||||
.insight-filters button:hover,
|
||||
.insight-filters button.active {
|
||||
color: #fff;
|
||||
background: #287ff0;
|
||||
box-shadow: 0 8px 18px rgba(39, 126, 238, 0.2);
|
||||
transform: translateY(-1px);
|
||||
color: #0978ff;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
.insight-filters button::after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 2px;
|
||||
content: '';
|
||||
background: currentColor;
|
||||
opacity: 0;
|
||||
transform: scaleX(0.75);
|
||||
transition:
|
||||
opacity 0.2s,
|
||||
transform 0.2s;
|
||||
}
|
||||
.insight-filters button.active::after {
|
||||
opacity: 1;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
.article-results {
|
||||
margin-top: 40px;
|
||||
margin-top: 28px;
|
||||
}
|
||||
.article-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 28px;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
width: min(100%, 1180px);
|
||||
margin: 0 auto;
|
||||
}
|
||||
.article-grid article {
|
||||
display: grid;
|
||||
grid-template-columns: 0.85fr 1.15fr;
|
||||
min-height: 285px;
|
||||
grid-template-columns: minmax(280px, 332px) 1fr;
|
||||
gap: 48px;
|
||||
align-items: center;
|
||||
min-height: 268px;
|
||||
overflow: hidden;
|
||||
border-radius: 14px 4px 14px 4px;
|
||||
background: #f3f7fc;
|
||||
padding: 18px 48px 18px 28px;
|
||||
border: 1px solid #edf1f6;
|
||||
border-radius: 18px;
|
||||
background: linear-gradient(100deg, #fff 0%, #fff 72%, #f0f7ff 100%);
|
||||
box-shadow: 0 10px 26px rgba(43, 83, 130, 0.05);
|
||||
transition:
|
||||
transform 0.25s,
|
||||
box-shadow 0.25s,
|
||||
@@ -537,18 +622,20 @@ function requestWhitepaper(source) {
|
||||
}
|
||||
.article-grid article:hover {
|
||||
background: #fff;
|
||||
box-shadow: 0 20px 42px rgba(61, 119, 189, 0.13);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 18px 42px rgba(61, 119, 189, 0.12);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
.article-grid article.lead {
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: 1.05fr 0.95fr;
|
||||
min-height: 350px;
|
||||
grid-column: auto;
|
||||
grid-template-columns: minmax(280px, 332px) 1fr;
|
||||
min-height: 268px;
|
||||
}
|
||||
.article-cover {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
height: 232px;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 14px;
|
||||
}
|
||||
.article-cover img {
|
||||
width: 100%;
|
||||
@@ -561,40 +648,64 @@ function requestWhitepaper(source) {
|
||||
transform: scale(1.04);
|
||||
}
|
||||
.article-cover > span {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 18px;
|
||||
padding: 7px 9px;
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
background: rgba(32, 105, 200, 0.82);
|
||||
font-size: 9px;
|
||||
display: none;
|
||||
}
|
||||
.article-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 28px;
|
||||
min-width: 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
.article-grid .article-meta,
|
||||
.article-grid .read-link {
|
||||
display: none;
|
||||
}
|
||||
.article-category {
|
||||
color: #50667f;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.article-copy h3 {
|
||||
margin: 15px 0 0;
|
||||
font-size: 20px;
|
||||
line-height: 1.45;
|
||||
margin: 12px 0 0;
|
||||
color: #142033;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 1.38;
|
||||
}
|
||||
.article-grid article.lead h3 {
|
||||
font-size: 28px;
|
||||
font-size: 24px;
|
||||
}
|
||||
.article-copy h3 a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.article-copy > p {
|
||||
margin: 12px 0 0;
|
||||
color: #75859a;
|
||||
font-size: 11px;
|
||||
line-height: 1.75;
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
margin: 16px 0 0;
|
||||
color: #435776;
|
||||
font-size: 16px;
|
||||
line-height: 1.68;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
.read-link {
|
||||
align-self: flex-start;
|
||||
margin-top: 22px;
|
||||
padding-bottom: 4px;
|
||||
border-bottom: 1px solid #9bc1e9;
|
||||
.article-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
.article-tags span {
|
||||
min-height: 34px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0 13px;
|
||||
border: 1px solid #d9e5f5;
|
||||
border-radius: 5px;
|
||||
color: #096fff;
|
||||
background: #f7fbff;
|
||||
font-size: 12px;
|
||||
}
|
||||
.load-more {
|
||||
min-width: 150px;
|
||||
@@ -736,10 +847,13 @@ function requestWhitepaper(source) {
|
||||
url('/images/lanhu/slices/home-group105-image31@2x.png') center / cover no-repeat;
|
||||
}
|
||||
.insights-cta-content {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
padding: 74px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.insights-cta-content p {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: #237df0;
|
||||
font-size: 12px;
|
||||
@@ -850,24 +964,48 @@ function requestWhitepaper(source) {
|
||||
flex-direction: column;
|
||||
}
|
||||
.insight-filters {
|
||||
justify-content: flex-start;
|
||||
gap: 30px;
|
||||
width: 100%;
|
||||
margin-top: 52px;
|
||||
padding-bottom: 4px;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.insight-filters button {
|
||||
flex: 0 0 auto;
|
||||
height: 48px;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
.article-grid article,
|
||||
.article-grid article.lead {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 18px;
|
||||
padding: 14px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
.article-cover {
|
||||
min-height: 210px;
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
aspect-ratio: 1.43;
|
||||
}
|
||||
.article-copy {
|
||||
padding: 25px 22px;
|
||||
padding: 0 4px 4px;
|
||||
}
|
||||
.article-copy h3,
|
||||
.article-grid article.lead h3 {
|
||||
font-size: 22px;
|
||||
font-size: 21px;
|
||||
}
|
||||
.article-copy > p {
|
||||
font-size: 14px;
|
||||
}
|
||||
.article-tags {
|
||||
gap: 8px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
.article-tags span {
|
||||
min-height: 30px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.whitepaper-grid {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
@@ -37,6 +37,12 @@ const ringModels = [
|
||||
}
|
||||
]
|
||||
|
||||
const serviceVisualImages = [
|
||||
'/images/services/brand-exposure-visual.png',
|
||||
'/images/services/lead-conversion-visual.png',
|
||||
'/images/services/omnichannel-visual.png'
|
||||
]
|
||||
|
||||
const services = [
|
||||
{
|
||||
id: 'brand-exposure',
|
||||
@@ -190,11 +196,11 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<div class="hero-core">
|
||||
<small>GEO</small><strong>品效双环</strong><span>持续增长</span>
|
||||
</div>
|
||||
<div class="hero-data hero-data-top"><small>品牌提及</small><strong>+217%</strong></div>
|
||||
<div class="hero-data hero-data-bottom">
|
||||
<small>转化效率</small><strong>+64%</strong>
|
||||
</div>
|
||||
<div class="hero-visual-caption"><span></span> AI 搜索增长系统正在运行</div>
|
||||
<!-- <div class="hero-data hero-data-top"><small>品牌提及</small><strong>+217%</strong></div>-->
|
||||
<!-- <div class="hero-data hero-data-bottom">-->
|
||||
<!-- <small>转化效率</small><strong>+64%</strong>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="hero-visual-caption"><span></span> AI 搜索增长系统正在运行</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -224,7 +230,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<section class="model-deep-section">
|
||||
<div class="page-width">
|
||||
<header class="model-heading services-reveal">
|
||||
<p class="section-kicker">双环增长模型</p>
|
||||
<p class="section-kicker section-center">双环增长模型</p>
|
||||
<h2>一边沉淀品牌声量,一边推动精准获客</h2>
|
||||
<p>两个环路共享同一套业务事实、内容资产与数据目标,让品牌建设和转化结果互相增强。</p>
|
||||
</header>
|
||||
@@ -279,7 +285,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<div class="page-width">
|
||||
<header class="service-system-heading services-reveal">
|
||||
<div>
|
||||
<p class="section-kicker">服务体系</p>
|
||||
<p class="section-kicker section-center">服务体系</p>
|
||||
<h2>三类能力,服务同一个增长目标</h2>
|
||||
</div>
|
||||
<p>
|
||||
@@ -337,7 +343,13 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<span>{{ service.visualTitle }}</span
|
||||
><small>YUNTU GEO SYSTEM</small>
|
||||
</div>
|
||||
<div class="visual-network">
|
||||
<img
|
||||
v-if="serviceVisualImages[serviceIndex]"
|
||||
class="visual-network-image"
|
||||
:src="serviceVisualImages[serviceIndex]"
|
||||
:alt="`${service.title}示意图`"
|
||||
/>
|
||||
<div v-else class="visual-network">
|
||||
<div class="network-core">
|
||||
<small>{{ service.index }}</small
|
||||
><strong>{{ service.title.split(',')[0] }}</strong>
|
||||
@@ -350,7 +362,10 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
>
|
||||
<i v-for="line in 4" :key="line" :class="`network-line line-${line}`"></i>
|
||||
</div>
|
||||
<div class="visual-metric">
|
||||
<div
|
||||
v-if="serviceIndex === 0 || !serviceVisualImages[serviceIndex]"
|
||||
class="visual-metric"
|
||||
>
|
||||
<strong>{{ service.metric }}</strong
|
||||
><span>{{ service.metricLabel }}</span>
|
||||
</div>
|
||||
@@ -364,7 +379,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<div class="process-background" aria-hidden="true"></div>
|
||||
<div class="page-width">
|
||||
<header class="process-heading services-reveal">
|
||||
<p class="section-kicker">标准化交付</p>
|
||||
<p class="section-kicker section-center">标准化交付</p>
|
||||
<h2>五步推进,每一步都有依据</h2>
|
||||
<p>从第一次沟通到内容资产交付,节点透明、数据可查、方向可调整。</p>
|
||||
</header>
|
||||
@@ -424,7 +439,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<article class="featured-proof">
|
||||
<div class="proof-tag">教育培训行业 · GEO 全链路案例</div>
|
||||
<h2>420 个真实问题,5 个月进入 AI 推荐列表</h2>
|
||||
<p>
|
||||
<p class="add-white">
|
||||
围绕家长“找方法、选机构、比课程、看口碑、做决策”的完整路径,搭建问题库、可信内容与持续监测体系。
|
||||
</p>
|
||||
<div class="proof-data">
|
||||
@@ -460,7 +475,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
<section class="services-cta">
|
||||
<div class="cta-wave" aria-hidden="true"></div>
|
||||
<div class="page-width services-cta-content services-reveal">
|
||||
<p>从一次真实诊断开始</p>
|
||||
<p class="section-center">从一次真实诊断开始</p>
|
||||
<h2>你的品牌,应该先解决曝光问题,<br />还是转化问题?</h2>
|
||||
<span>聊聊行业、现状和目标,我们会给出第一步建议。</span>
|
||||
<button
|
||||
@@ -520,6 +535,10 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.14em;
|
||||
}
|
||||
.section-center {
|
||||
justify-content: center;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
.services-hero {
|
||||
position: relative;
|
||||
min-height: 650px;
|
||||
@@ -666,10 +685,10 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid rgba(255, 255, 255, 0.9);
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: linear-gradient(145deg, rgba(35, 126, 241, 0.94), rgba(43, 180, 231, 0.84));
|
||||
background: linear-gradient(145deg, #176fd8, #1ca9de);
|
||||
box-shadow:
|
||||
0 22px 45px rgba(33, 116, 224, 0.28),
|
||||
inset 0 1px 5px rgba(255, 255, 255, 0.7);
|
||||
@@ -695,7 +714,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
z-index: 3;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
border: 1px solid rgba(50, 133, 234, 0.3);
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
@@ -706,14 +725,13 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
.hero-orbit-two {
|
||||
width: 490px;
|
||||
height: 490px;
|
||||
border-style: dashed;
|
||||
opacity: 0.72;
|
||||
}
|
||||
.hero-orbit i {
|
||||
position: absolute;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
border: 3px solid #fff;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
background: #2383f4;
|
||||
box-shadow: 0 5px 15px rgba(32, 125, 237, 0.35);
|
||||
@@ -896,11 +914,20 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
position: absolute;
|
||||
width: 345px;
|
||||
aspect-ratio: 1;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.model-ring img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
width: calc(100% + 4px);
|
||||
max-width: none;
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
filter: drop-shadow(0 25px 32px rgba(58, 123, 205, 0.12));
|
||||
box-shadow: none;
|
||||
}
|
||||
.ring-1 {
|
||||
top: 10px;
|
||||
@@ -916,16 +943,23 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
left: 50%;
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
min-width: 106px;
|
||||
padding: 10px 14px 11px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: 0 10px 24px rgba(42, 100, 180, 0.14);
|
||||
transform: translate(-50%, -50%);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
.ring-copy small {
|
||||
color: #87a4c6;
|
||||
color: #6e8eb4;
|
||||
font-size: 11px;
|
||||
}
|
||||
.ring-copy strong {
|
||||
margin-top: 5px;
|
||||
color: #2d76d8;
|
||||
color: #135fbd;
|
||||
font-size: 17px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.ring-connector {
|
||||
position: absolute;
|
||||
@@ -1040,6 +1074,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.service-index span {
|
||||
font-size: 18px;
|
||||
margin-left: 12px;
|
||||
color: #2c80ed;
|
||||
}
|
||||
@@ -1095,9 +1130,9 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
.service-details li {
|
||||
position: relative;
|
||||
padding-left: 14px;
|
||||
color: var(--service-copy);
|
||||
font-size: 14px;
|
||||
line-height: 1.65;
|
||||
color: var(--service-copy) !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.65 !important;
|
||||
}
|
||||
.service-details li::before {
|
||||
position: absolute;
|
||||
@@ -1110,20 +1145,30 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
background: #4b97ef;
|
||||
}
|
||||
.service-action {
|
||||
min-height: 48px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 9px;
|
||||
margin-top: 27px;
|
||||
padding: 0 0 5px;
|
||||
border-bottom: 1px solid #8eb8e9;
|
||||
color: #257ce8;
|
||||
background: transparent;
|
||||
padding: 0 24px !important;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
color: #fff;
|
||||
background: linear-gradient(100deg, #3158ff, #12aef5);
|
||||
box-shadow: 0 12px 24px rgba(25, 106, 255, 0.2);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.service-action b {
|
||||
margin-left: 8px;
|
||||
transition: margin 0.2s;
|
||||
.service-action :deep(.app-icon) {
|
||||
flex: 0 0 auto;
|
||||
font-size: 1.05em;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.service-action:hover b {
|
||||
margin-left: 13px;
|
||||
.service-action:hover :deep(.app-icon) {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
.service-story-visual {
|
||||
position: relative;
|
||||
@@ -1149,6 +1194,8 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
linear-gradient(145deg, #f4f8ff, #dcecff);
|
||||
}
|
||||
.visual-topline {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 24px 27px;
|
||||
@@ -1168,6 +1215,19 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
height: 340px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.visual-network-image {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 54%;
|
||||
left: 50%;
|
||||
width: min(620px, 108%);
|
||||
height: min(500px, 90%);
|
||||
max-width: none;
|
||||
object-fit: contain;
|
||||
pointer-events: none;
|
||||
filter: drop-shadow(0 22px 34px rgba(46, 121, 220, 0.16));
|
||||
transform: translate(-50%, -48%);
|
||||
}
|
||||
.network-core {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
@@ -1252,6 +1312,7 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
}
|
||||
.visual-metric {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
right: 24px;
|
||||
bottom: 22px;
|
||||
display: grid;
|
||||
@@ -1444,6 +1505,9 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
letter-spacing: 0.12em;
|
||||
opacity: 0.72;
|
||||
}
|
||||
.add-white {
|
||||
color: white !important;
|
||||
}
|
||||
.featured-proof h2 {
|
||||
max-width: 720px;
|
||||
margin: 26px 0 0;
|
||||
@@ -1815,6 +1879,11 @@ onBeforeUnmount(() => animationContext?.revert())
|
||||
width: 310px;
|
||||
height: 280px;
|
||||
}
|
||||
.visual-network-image {
|
||||
top: 52%;
|
||||
width: min(500px, 118%);
|
||||
height: 360px;
|
||||
}
|
||||
.network-core {
|
||||
width: 108px;
|
||||
height: 108px;
|
||||
|
||||
|
After Width: | Height: | Size: 645 KiB |
|
After Width: | Height: | Size: 563 KiB |
|
After Width: | Height: | Size: 688 KiB |
|
After Width: | Height: | Size: 734 KiB |
|
After Width: | Height: | Size: 602 KiB |
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 810 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 731 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 458 KiB |
|
After Width: | Height: | Size: 601 KiB |
|
After Width: | Height: | Size: 566 KiB |
@@ -0,0 +1,10 @@
|
||||
export default defineEventHandler((event) => {
|
||||
const config = useRuntimeConfig()
|
||||
const targetBase = String(config.officialApiProxyTarget || 'http://localhost:8080').replace(/\/$/, '')
|
||||
const rawPath = event.context.params?.path || ''
|
||||
const path = Array.isArray(rawPath) ? rawPath.join('/') : rawPath
|
||||
const requestUrl = getRequestURL(event)
|
||||
const targetUrl = `${targetBase}/api/${path}${requestUrl.search}`
|
||||
|
||||
return proxyRequest(event, targetUrl)
|
||||
})
|
||||