diff --git a/OSS-DEPLOY.md b/OSS-DEPLOY.md
new file mode 100644
index 0000000..18d0c9e
--- /dev/null
+++ b/OSS-DEPLOY.md
@@ -0,0 +1,32 @@
+# 阿里云 OSS 发布
+
+在项目根目录打开 PowerShell,执行:
+
+```powershell
+npm run deploy:oss
+```
+
+脚本会自动完成以下操作:
+
+1. 使用当前时间生成 `static/wwwweb/yyyyMMdd-HHmmss/` 目录。
+2. 执行 Vue/Vite 生产构建。
+3. 改写并检查 OSS 静态资源地址,阻止重复 `https://...https://...` 地址上传。
+4. 上传 JS、CSS、图片等静态资源,并排除 `index.html`。
+5. 验证线上 JS、CSS、Logo 可访问,同时确认 OSS 中不存在 `index.html`。
+
+构建完成后,将终端输出的 `Server index` 文件部署到 `www.yuedongsports.com` 服务器。
+
+## 前置配置
+
+- AccessKey 配置文件:`C:\Users\当前用户\.ossutilconfig`
+- ossutil 默认位置:`.tools\ossutil-2.3.0-windows-amd64\ossutil.exe`
+
+如果路径不同,可以直接调用脚本并传入参数:
+
+```powershell
+powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy-oss.ps1 `
+ -ConfigFile "D:\secure\.ossutilconfig" `
+ -OssutilPath "D:\tools\ossutil.exe"
+```
+
+仅在网络环境无法执行公网校验时,可增加 `-SkipRemoteVerify`;上传和本地路径检查仍会正常执行。
diff --git a/package.json b/package.json
index 74103e5..884ef14 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"dev": "vite",
"build": "vite build",
"rewrite:oss": "node scripts/rewrite-oss-paths.mjs",
+ "deploy:oss": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy-oss.ps1",
"preview": "vite preview"
},
"dependencies": {
diff --git a/scripts/deploy-oss.ps1 b/scripts/deploy-oss.ps1
new file mode 100644
index 0000000..994b907
--- /dev/null
+++ b/scripts/deploy-oss.ps1
@@ -0,0 +1,137 @@
+[CmdletBinding()]
+param(
+ [string]$Bucket = 'yuedong-wechatapplet',
+ [string]$Prefix = 'static/wwwweb',
+ [string]$PublicOrigin = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com',
+ [string]$ConfigFile = (Join-Path $HOME '.ossutilconfig'),
+ [string]$OssutilPath = '',
+ [switch]$SkipRemoteVerify
+)
+
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+
+$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
+$DistDir = Join-Path $ProjectRoot 'dist'
+$DefaultOssutil = Join-Path $ProjectRoot '.tools\ossutil-2.3.0-windows-amd64\ossutil.exe'
+
+if (-not $OssutilPath) {
+ $OssutilPath = $DefaultOssutil
+}
+
+if (-not (Test-Path -LiteralPath $OssutilPath -PathType Leaf)) {
+ throw "ossutil not found: $OssutilPath"
+}
+
+if (-not (Test-Path -LiteralPath $ConfigFile -PathType Leaf)) {
+ throw "OSS config not found: $ConfigFile"
+}
+
+if (-not (Get-Command 'npm.cmd' -ErrorAction SilentlyContinue)) {
+ throw 'npm.cmd was not found. Install Node.js and reopen PowerShell.'
+}
+
+$Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
+$CleanOrigin = $PublicOrigin.TrimEnd('/')
+$CleanPrefix = $Prefix.Trim('/')
+$PublicBase = "$CleanOrigin/$CleanPrefix/$Timestamp/"
+$OssTarget = "oss://$Bucket/$CleanPrefix/$Timestamp/"
+
+Push-Location $ProjectRoot
+try {
+ Write-Host "[1/5] Building production files" -ForegroundColor Cyan
+ & npm.cmd run build -- "--base=$PublicBase"
+ if ($LASTEXITCODE -ne 0) {
+ throw "Vite build failed with exit code $LASTEXITCODE"
+ }
+
+ Write-Host "[2/5] Rewriting and validating OSS asset paths" -ForegroundColor Cyan
+ & npm.cmd run rewrite:oss -- $PublicBase
+ if ($LASTEXITCODE -ne 0) {
+ throw "OSS path validation failed with exit code $LASTEXITCODE"
+ }
+
+ $IndexPath = Join-Path $DistDir 'index.html'
+ $IndexContent = [System.IO.File]::ReadAllText($IndexPath)
+ $DuplicatePrefix = $PublicBase.TrimEnd('/') + $PublicBase
+
+ if ($IndexContent.Contains($DuplicatePrefix)) {
+ throw 'The generated index.html contains a duplicated OSS prefix.'
+ }
+
+ if (-not $IndexContent.Contains($PublicBase)) {
+ throw 'The generated index.html does not reference the new OSS directory.'
+ }
+
+ $Files = Get-ChildItem -LiteralPath $DistDir -Recurse -File
+ $UploadFiles = @($Files | Where-Object { $_.Name -ne 'index.html' })
+ $UploadBytes = ($UploadFiles | Measure-Object Length -Sum).Sum
+
+ Write-Host "[3/5] Uploading $($UploadFiles.Count) static files" -ForegroundColor Cyan
+ Write-Host " Target: $OssTarget"
+ & $OssutilPath -c $ConfigFile cp "$DistDir\" $OssTarget -r --exclude 'index.html' -f -q --no-progress
+ if ($LASTEXITCODE -ne 0) {
+ throw "OSS upload failed with exit code $LASTEXITCODE"
+ }
+
+ Write-Host '[4/5] Confirming index.html was excluded' -ForegroundColor Cyan
+ $RemoteIndexUrl = "${PublicBase}index.html?verify=$Timestamp"
+ try {
+ $RemoteIndexResponse = Invoke-WebRequest -Uri $RemoteIndexUrl -Method Head -UseBasicParsing
+ if ($RemoteIndexResponse.StatusCode -eq 200) {
+ throw 'index.html exists in the new OSS directory, but it must remain on the web server.'
+ }
+ } catch {
+ if (-not $_.Exception.Response) {
+ throw
+ }
+
+ $RemoteIndexStatus = [int]$_.Exception.Response.StatusCode
+ if ($RemoteIndexStatus -ne 404) {
+ throw "Unable to confirm that index.html was excluded. HTTP status: $RemoteIndexStatus"
+ }
+ }
+
+ if (-not $SkipRemoteVerify) {
+ Write-Host '[5/5] Verifying uploaded JS, CSS, and image URLs' -ForegroundColor Cyan
+ $ScriptMatch = [regex]::Match($IndexContent, '
diff --git a/src/components/PurchaseChannels.vue b/src/components/PurchaseChannels.vue
new file mode 100644
index 0000000..902f680
--- /dev/null
+++ b/src/components/PurchaseChannels.vue
@@ -0,0 +1,42 @@
+
+
+
+
OFFICIAL STORES
+
购买渠道
+
前往跃动线上店铺,查看在售产品、规格与最新活动。
+
+
+
+
+
+
diff --git a/src/components/SiteFooter.vue b/src/components/SiteFooter.vue
index d67584b..7f7eac7 100644
--- a/src/components/SiteFooter.vue
+++ b/src/components/SiteFooter.vue
@@ -4,9 +4,9 @@
@@ -29,6 +42,10 @@ const scrolled = ref(false);
const headerHidden = ref(false);
const logoUrl = '/site/assets/logo.png';
const closeMenu = () => { menuOpen.value = false; };
+const isSectionActive = (item) => {
+ if (item.to === '/') return route.path === '/';
+ return route.path === item.to || route.path.startsWith(`${item.to.split('/').slice(0, 2).join('/')}/`);
+};
let lastScrollY = 0;
let scrollFrame = 0;
@@ -75,11 +92,52 @@ onUnmounted(() => {
const nav = [
{ label: '首页', to: '/' },
- { label: '关于跃动', to: '/about/brand-story', children: [{ label: '品牌故事', to: '/about/brand-story' }, { label: '跃动历程', to: '/about/history' }, { label: '动态公告', to: '/about/notices' }] },
- { label: '赛事资讯', to: '/events/news', children: [{ label: '赛事新闻', to: '/events/news' }, { label: '赛事发布', to: '/events/releases' }, { label: '活动公告', to: '/events/notices' }] },
- { label: '产品装备', to: '/products/categories', children: [{ label: '装备分类', to: '/products/categories' }, { label: '供应链', to: '/products/supply-chain' }, { label: '开发定制', to: '/products/custom' }] },
- { label: '教育培训', to: '/education/venues', children: [{ label: '跃动运动馆', to: '/education/venues' }, { label: '寒暑营', to: '/education/camps' }, { label: '训练营', to: '/education/training' }] },
- { label: '跃动科技', to: '/technology' }, { label: '跃动健康', to: '/health' }, { label: 'YGJRC', to: '/ygjrc' },
- { label: '联系我们', to: '/contact/social', children: [{ label: '社媒与合作', to: '/contact/social' }, { label: '场馆地址', to: '/contact/venues' }, { label: '联系方式', to: '/contact/contact-info' }] }
+ { label: '关于跃动', to: '/about/brand-story', children: [{ label: '品牌故事', to: '/about/brand-story' }, { label: '跃动历程', to: '/about/history' }, { label: '集团动态', to: '/about/group-news' }] },
+ {
+ label: '跃动体育',
+ to: '/sports/competition',
+ groups: [
+ {
+ label: '竞赛演艺',
+ to: '/sports/competition',
+ children: [
+ { label: '赛事招募', to: '/sports/competition#event-recruitment' },
+ { label: '赛事新闻', to: '/sports/competition#event-news' },
+ { label: '演艺活动', to: '/sports/competition#performances' }
+ ]
+ },
+ {
+ label: '跃动运动馆',
+ to: '/sports/venues',
+ children: [
+ { label: '运动馆介绍', to: '/sports/venues#venue-intro' },
+ { label: '冠军班', to: '/sports/venues#champion-class' },
+ { label: '特色训练营', to: '/sports/venues#camps' },
+ { label: '运动馆地址', to: '/sports/venues#venue-address' }
+ ]
+ },
+ {
+ label: '跃动装备',
+ to: '/sports/equipment',
+ children: [
+ { label: '1阶 启蒙型', to: '/sports/equipment-stage-1' },
+ { label: '2阶 初学型', to: '/sports/equipment-stage-2' },
+ { label: '3阶 提速型', to: '/sports/equipment-stage-3' },
+ { label: '4阶 考测型', to: '/sports/equipment-stage-4' },
+ { label: '5阶 竞技型', to: '/sports/equipment-stage-5' },
+ { label: '校园跳绳', to: '/sports/equipment-campus' },
+ { label: '健身跳绳', to: '/sports/equipment-fitness' },
+ { label: '跳绳鞋服', to: '/sports/equipment-apparel' },
+ { label: '其它周边', to: '/sports/equipment-accessories' },
+ { label: '购买渠道', to: '/sports/purchase-channels' }
+ ]
+ }
+ ]
+ },
+ { label: '跃动科技', to: '/technology' },
+ { label: '跃动健康', to: '/health' },
+ { label: '跃动工厂', to: '/factory/supply-chain', children: [{ label: '供应链', to: '/factory/supply-chain' }, { label: 'KA定制', to: '/factory/ka-custom' }] },
+ { label: 'YGJRC', to: '/ygjrc' },
+ { label: '联系我们', to: '/contact' }
];
diff --git a/src/components/SportsGroupedSection.vue b/src/components/SportsGroupedSection.vue
new file mode 100644
index 0000000..9132ca2
--- /dev/null
+++ b/src/components/SportsGroupedSection.vue
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+ {{ panel.eyebrow }}
+ {{ panel.label }}
+ {{ panel.description }}
+
+
+
+
+ {{ String(index + 1).padStart(2, '0') }}
+ {{ article.title }}
{{ line }}
+
+
+
+
+
+
+
+
+
+
+ VENUE INTRODUCTION运动馆介绍
+ 了解跃动运动馆的品牌体系、课程理念与全国布局。
+
+
+
+
+
+
+ CHAMPION CLASS冠军班
+ 由专业教练团队打造的进阶竞技培养课程。
+
+
+
+
+
+
+ FEATURED CAMPS特色训练营
+ 围绕假期集训、体测培优和专项突破开展主题课程。
+
+
+
+
+
+
+ VENUE NETWORK运动馆地址
+ 按城市查找全国跃动运动馆及合作场馆。
+
+
+
+
+
+
+
+
diff --git a/src/components/VenueAddressSection.vue b/src/components/VenueAddressSection.vue
new file mode 100644
index 0000000..3f2cf4e
--- /dev/null
+++ b/src/components/VenueAddressSection.vue
@@ -0,0 +1,63 @@
+
+
+
+ 场馆按城市平铺展示,便于快速查找附近的跃动运动馆。门店信息可能调整,到访前可通过“联系我们”确认。
+
+
+
+ {{ city.en }}
+
{{ city.city }}
+ {{ city.venues.length }} 家场馆
+
+
+
+
+
+
+
diff --git a/src/data/page-content.js b/src/data/page-content.js
index 4a9b289..b67d470 100644
--- a/src/data/page-content.js
+++ b/src/data/page-content.js
@@ -144,7 +144,6 @@ export const pages = {
};
pages.about.sections['brand-story'].body = brandIntroduction;
-pages.about.sections['brand-story'].timeline = aboutTimeline;
pages.about.sections.history.body = [];
pages.about.sections.history.timeline = aboutTimeline;
@@ -171,3 +170,149 @@ Object.assign(pages.education.sections.venues, {
{ src: '/sports-hall/competition-collage.png', alt: '学员训练与比赛精彩瞬间' }
]
});
+
+// 官网栏目结构以《跃动官网.xmind》为准。旧的 events / products /
+// education 数据继续作为内容源,新的 sports / factory 页面负责对外呈现。
+pages.about.tabs = [
+ { key: 'brand-story', label: '品牌故事' },
+ { key: 'history', label: '跃动历程' },
+ { key: 'group-news', label: '集团动态' }
+];
+pages.about.sections['group-news'] = {
+ ...pages.about.sections.notices,
+ title: '集团动态'
+};
+
+const eventImages = images('赛事资讯');
+const educationImages = images('教育培训');
+const productHero = materials.products.find((product) => product.image)?.image;
+const productsIn = (...categories) => productDetails.filter((product) => categories.includes(product.category));
+const overviewCard = (title, description, to) => ({ title, body: [description], to });
+
+pages.sports = {
+ eyebrow: 'YUEDONG SPORTS',
+ title: '跃动体育',
+ summary: '连接竞赛演艺、跃动运动馆与专业装备,构建覆盖赛事、培训和运动消费的体育服务体系。',
+ hero: pages.events.hero,
+ tabs: [
+ { key: 'competition', label: '竞赛演艺' },
+ { key: 'venues', label: '跃动运动馆' },
+ { key: 'equipment', label: '跃动装备' }
+ ],
+ sections: {
+ competition: {
+ title: '竞赛演艺',
+ body: ['以专业赛事运营、青少年竞赛和冠军团队演艺为核心,让跳绳运动连接城市、校园与大众舞台。'],
+ gallery: eventImages.slice(0, 5),
+ cards: [
+ overviewCard('赛事招募', '汇集跃动旗下赛事报名、参赛通知与活动信息。', '/sports/competition#event-recruitment'),
+ overviewCard('赛事新闻', '关注专业赛事、城市活动与青少年运动员的最新动态。', '/sports/competition#event-news'),
+ overviewCard('演艺活动', '冠军团队、花样跳绳与大型活动演出服务。', '/sports/competition#performances')
+ ]
+ },
+ 'event-recruitment': {
+ ...pages.events.sections.releases,
+ parent: 'competition',
+ title: '赛事招募'
+ },
+ 'event-news': {
+ ...pages.events.sections.news,
+ parent: 'competition',
+ title: '赛事新闻'
+ },
+ performances: {
+ parent: 'competition',
+ title: '演艺活动',
+ body: ['跃动冠军团队将竞技实力、花样创意与舞台表达融为一体,为体育赛事、品牌活动、校园庆典和城市文化项目提供专业演艺服务。'],
+ gallery: eventImages.slice(20, 32)
+ },
+ venues: {
+ parent: 'venues',
+ title: '跃动运动馆',
+ body: ['跃动运动馆以跳绳为核心,融合体适能、专项技能和成长训练,为青少年提供科学、系统、可持续的运动课程。'],
+ gallery: educationImages.slice(0, 4),
+ cards: [
+ overviewCard('运动馆介绍', '了解跃动运动馆的品牌体系、课程理念与全国布局。', '/sports/venues#venue-intro'),
+ overviewCard('冠军班', '由专业教练团队打造的进阶竞技培养课程。', '/sports/venues#champion-class'),
+ overviewCard('特色训练营', '围绕假期集训、体测培优和专项突破开展主题课程。', '/sports/venues#camps'),
+ overviewCard('运动馆地址', '查找全国跃动运动馆及合作场馆。', '/sports/venues#venue-address')
+ ]
+ },
+ 'venue-intro': {
+ ...pages.education.sections.venues,
+ parent: 'venues',
+ title: '运动馆介绍'
+ },
+ 'champion-class': {
+ parent: 'venues',
+ title: '冠军班',
+ body: [
+ '冠军班面向具备专项基础、希望进一步提升竞技能力的学员,围绕速度、耐力、花样与临场表现进行系统训练。',
+ '课程通过阶段测评、训练计划和赛事实践,帮助学员建立稳定技术、竞赛意识和长期成长目标。'
+ ],
+ gallery: educationImages.slice(0, 4)
+ },
+ camps: {
+ ...pages.education.sections.camps,
+ parent: 'venues',
+ title: '特色训练营'
+ },
+ 'venue-address': {
+ parent: 'venues',
+ title: '运动馆地址'
+ },
+ equipment: {
+ parent: 'equipment',
+ title: '跃动分阶跳绳',
+ products: productDetails
+ },
+ 'equipment-stage-1': { parent: 'equipment', title: '1阶 · 启蒙型', products: productsIn('竹节跳绳') },
+ 'equipment-stage-2': { parent: 'equipment', title: '2阶 · 初学型', products: productsIn('分段跳绳') },
+ 'equipment-stage-3': { parent: 'equipment', title: '3阶 · 提速型', products: productsIn('胶绳') },
+ 'equipment-stage-4': { parent: 'equipment', title: '4阶 · 考测型', products: productsIn('电子计数跳绳') },
+ 'equipment-stage-5': { parent: 'equipment', title: '5阶 · 竞技型', products: productsIn('速度跳绳', '交互绳') },
+ 'equipment-campus': { parent: 'equipment', title: '校园跳绳', products: productsIn('分段跳绳', '电子计数跳绳') },
+ 'equipment-fitness': { parent: 'equipment', title: '健身跳绳', products: productsIn('健身跳绳') },
+ 'equipment-apparel': {
+ parent: 'equipment',
+ title: '跳绳鞋服',
+ body: ['围绕日常训练、竞赛和团队形象需求,逐步完善专业跳绳鞋服产品体系。'],
+ gallery: productHero ? [{ src: productHero, alt: '跃动跳绳鞋服与装备' }] : []
+ },
+ 'equipment-accessories': {
+ parent: 'equipment',
+ title: '其它周边',
+ body: ['提供与跳绳训练、赛事组织和团队活动配套的周边产品及组合方案。'],
+ gallery: images('产品装备').slice(0, 4)
+ },
+ 'purchase-channels': {
+ parent: 'equipment',
+ title: '购买渠道',
+ body: ['跃动产品可通过官方社媒、电商平台、线下运动馆及团体采购渠道了解与购买。'],
+ cards: [overviewCard('联系装备服务', '获取产品选型、团体采购和购买渠道支持。', '/contact/contact-info')]
+ }
+ }
+};
+
+pages.technology.sections.default.title = '1+4+N 智慧体育解决方案';
+
+pages.factory = {
+ eyebrow: 'YUEDONG FACTORY',
+ title: '跃动工厂',
+ summary: '以稳定供应链、研发制造与定制服务,为品牌、赛事、学校和机构提供专业装备解决方案。',
+ hero: images('产品装备')[0] || (productHero ? { src: productHero, alt: '跃动工厂' } : null),
+ tabs: [
+ { key: 'supply-chain', label: '供应链' },
+ { key: 'ka-custom', label: 'KA定制' }
+ ],
+ sections: {
+ 'supply-chain': {
+ ...pages.products.sections['supply-chain'],
+ title: '供应链'
+ },
+ 'ka-custom': {
+ ...pages.products.sections.custom,
+ title: 'KA定制'
+ }
+ }
+};
diff --git a/src/data/venue-groups.js b/src/data/venue-groups.js
new file mode 100644
index 0000000..7c70080
--- /dev/null
+++ b/src/data/venue-groups.js
@@ -0,0 +1,82 @@
+export const venueGroups = [
+ {
+ city: '上海',
+ en: 'SHANGHAI',
+ venues: [
+ { name: '杨浦翔殷馆', address: '上海市杨浦区翔殷路260号' },
+ { name: '杨浦新江湾运动健康中心馆', address: '上海市杨浦区国浩路701号201室' },
+ { name: '宝山高境三邻桥馆', address: '上海市宝山区江杨南路485号三邻桥体育文化园11号101B室' },
+ { name: '宝山体育中心馆', address: '上海市宝山区永清路700号体育中心内' },
+ { name: '闵行七宝宝龙广场馆', address: '上海市闵行区漕宝路3299弄七宝宝龙广场3楼' },
+ { name: '浦东金桥馆', address: '上海市浦东新区金藏路1296弄151号2楼2027室' },
+ { name: '静安盛源生活广场馆', address: '上海市静安区柳营路777号盛源生活广场2楼' },
+ { name: '静安889GLO广场馆', address: '上海市静安区万航渡路889号889广场3楼' },
+ { name: '闵行力波馆', address: '上海市闵行区虹梅南路379弄27号力波九坊' },
+ { name: '浦东恒生万鹂广场馆', address: '上海市浦东新区芳甸路115弄恒生万鹂广场' },
+ { name: '虹口瑞虹星星堂馆', address: '上海市虹口区天宝路280弄瑞虹天地星星堂' },
+ { name: '普陀曹杨复悦荟馆', address: '上海市普陀区曹杨路1888号复悦荟3楼' },
+ { name: '青浦区跃动青少儿运动健康促进中心', address: '上海市青浦区淀山湖路535号4楼' }
+ ]
+ },
+ {
+ city: '北京',
+ en: 'BEIJING',
+ venues: [
+ { name: '西城官园馆', address: '北京市西城区西直门南小街2号楼B1-103' },
+ { name: '丰台草桥馆', address: '北京市丰台区草桥欣园一区5号楼2楼260室' },
+ { name: '西城马连道馆', address: '北京市西城区马连道街华睦大厦' },
+ { name: '东城崇文门馆', address: '北京市东城区崇文门区域' },
+ { name: '西城西便门馆', address: '北京市西城区西便门区域' },
+ { name: '朝阳大郊亭馆', address: '北京市朝阳区大郊亭华腾新天地运动中心' }
+ ]
+ },
+ {
+ city: '天津',
+ en: 'TIANJIN',
+ venues: [
+ { name: '天津南开馆', address: '天津市南开区宾川道507号' },
+ { name: '天津和平馆', address: '天津市和平区人民体育馆区域' }
+ ]
+ },
+ {
+ city: '广州',
+ en: 'GUANGZHOU',
+ venues: [
+ { name: '天河林和东馆', address: '广州市天河区林和东路218号2楼自编03室' },
+ { name: '海珠广纸天地荟馆', address: '广州市海珠区工业大道广纸天地荟207-208' }
+ ]
+ },
+ {
+ city: '徐州',
+ en: 'XUZHOU',
+ venues: [
+ { name: '经开淮海环球港馆', address: '徐州市经开区淮海环球港L2096' },
+ { name: '鼓楼金地商都馆', address: '徐州市鼓楼区中山北路6号金地商都' }
+ ]
+ },
+ {
+ city: '合肥',
+ en: 'HEFEI',
+ venues: [
+ { name: '庐阳华润橡树湾馆', address: '合肥市庐阳区华润橡树湾商业区' },
+ { name: '包河馆', address: '合肥市包河区安徽省运动健康促进中心2楼' }
+ ]
+ },
+ {
+ city: '成都',
+ en: 'CHENGDU',
+ venues: [
+ { name: '武侯莱蒙都会馆', address: '成都市武侯区二环路南四段51号莱蒙都会商场4楼' }
+ ]
+ },
+ {
+ city: '加盟场馆',
+ en: 'FRANCHISE VENUES',
+ venues: [
+ { name: '松江大学城馆', address: '上海市松江区梅家浜路1501号3楼' },
+ { name: '广西南宁馆', address: '南宁市青秀区星湖路1号' },
+ { name: '江西信丰馆', address: '赣州市信丰县体育中心内' },
+ { name: '江西上饶馆', address: '上饶市广信区旭日街道武夷山大道博华年华北区2栋111-113' }
+ ]
+ }
+];
diff --git a/src/router.js b/src/router.js
index 16b39e3..6bf5224 100644
--- a/src/router.js
+++ b/src/router.js
@@ -1,4 +1,4 @@
-import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
+import { createRouter, createWebHashHistory } from 'vue-router';
import HomePage from './views/HomePage.vue';
import ContentPage from './views/ContentPage.vue';
import ContentDetailPage from './views/ContentDetailPage.vue';
@@ -7,27 +7,56 @@ import ContactPage from './views/ContactPage.vue';
const routes = [
{ path: '/', name: 'home', component: HomePage },
+ { path: '/about/notices', redirect: '/about/group-news' },
{ path: '/about/:section?', component: ContentPage, meta: { page: 'about' } },
- { path: '/events/:section?', component: ContentPage, meta: { page: 'events' } },
- { path: '/products/:section?', component: ContentPage, meta: { page: 'products' } },
- { path: '/education/:section?', component: ContentPage, meta: { page: 'education' } },
+ { path: '/sports/equipment/detail/:id', name: 'sports-product-detail', component: ProductDetailPage, meta: { page: 'sports' } },
+ { path: '/sports/event-recruitment', redirect: '/sports/competition#event-recruitment' },
+ { path: '/sports/event-news', redirect: '/sports/competition#event-news' },
+ { path: '/sports/performances', redirect: '/sports/competition#performances' },
+ { path: '/sports/venue-intro', redirect: '/sports/venues#venue-intro' },
+ { path: '/sports/champion-class', redirect: '/sports/venues#champion-class' },
+ { path: '/sports/camps', redirect: '/sports/venues#camps' },
+ { path: '/sports/venue-address', redirect: '/sports/venues#venue-address' },
+ { path: '/sports/:section?', component: ContentPage, meta: { page: 'sports' } },
{ path: '/technology', component: ContentPage, meta: { page: 'technology' } },
{ path: '/health', component: ContentPage, meta: { page: 'health' } },
+ { path: '/factory/:section?', component: ContentPage, meta: { page: 'factory' } },
{ path: '/ygjrc', component: ContentPage, meta: { page: 'ygjrc' } },
+ { path: '/contact/venues', redirect: '/sports/venues#venue-address' },
{ path: '/contact/:section?', component: ContactPage, meta: { page: 'contact' } },
{ path: '/products/detail/:id', name: 'product-detail', component: ProductDetailPage, meta: { page: 'products' } },
+ {
+ path: '/events/:section?',
+ redirect: (to) => ({
+ news: '/sports/competition#event-news',
+ releases: '/sports/competition#event-recruitment',
+ notices: '/sports/competition#performances'
+ })[to.params.section] || '/sports/competition'
+ },
+ {
+ path: '/products/:section?',
+ redirect: (to) => `/sports/${({ categories: 'equipment', 'supply-chain': 'equipment', custom: 'purchase-channels' })[to.params.section] || 'equipment'}`
+ },
+ {
+ path: '/education/:section?',
+ redirect: (to) => ({
+ venues: '/sports/venues#venue-intro',
+ camps: '/sports/venues#camps',
+ training: '/sports/venues#champion-class'
+ })[to.params.section] || '/sports/venues'
+ },
{ path: '/detail/:page/:section/:index?', name: 'content-detail', component: ContentDetailPage },
{ path: '/:pathMatch(.*)*', redirect: '/' }
];
export default createRouter({
- history: import.meta.env.VITE_STATIC_DEPLOY === 'oss'
- ? createWebHashHistory()
- : createWebHistory(),
+ history: createWebHashHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition;
+ if (to.hash) return { el: to.hash, top: 138, behavior: 'smooth' };
+
if (to.name === 'product-detail' || to.name === 'content-detail') {
return { top: 0 };
}
diff --git a/src/style.css b/src/style.css
index c8ff6d3..d0a1af1 100644
--- a/src/style.css
+++ b/src/style.css
@@ -48,8 +48,8 @@ main { min-height: 72vh; }
.nav-item > a i { width: 5px; height: 5px; border-right: 1px solid currentColor; border-bottom: 1px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .25s; }
.nav-item:hover > a i { transform: translateY(1px) rotate(225deg); }
.nav-item > a::after { content: ""; position: absolute; left: 50%; right: 50%; bottom: -1px; height: 3px; border-radius: 3px 3px 0 0; background: linear-gradient(90deg, var(--blue-500), var(--blue-700)); transition: left .3s ease, right .3s ease; }
-.nav-item:hover > a, .nav-item > a.router-link-active { color: var(--blue-700); }
-.nav-item:hover > a::after, .nav-item > a.router-link-active::after { left: 14px; right: 14px; }
+.nav-item:hover > a, .nav-item > a.router-link-active, .nav-item > a.section-active { color: var(--blue-700); }
+.nav-item:hover > a::after, .nav-item > a.router-link-active::after, .nav-item > a.section-active::after { left: 14px; right: 14px; }
.dropdown {
position: absolute; top: 72px; left: 50%; width: 190px; padding: 12px;
background: rgba(255,255,255,.97); border: 1px solid rgba(0,144,255,.14); border-radius: 14px;
@@ -63,6 +63,13 @@ main { min-height: 72vh; }
.dropdown a::before { content: ""; position: absolute; left: 10px; top: 50%; width: 5px; height: 5px; border-radius: 50%; background: var(--blue-300); transform: translateY(-50%); transition: .22s; }
.dropdown a:hover, .dropdown a.router-link-active { color: var(--blue-700); background: var(--blue-50); transform: translateX(3px); }
.dropdown a:hover::before { background: var(--blue-600); box-shadow: 0 0 0 4px rgba(0,144,255,.12); }
+.dropdown-mega { width: min(820px,calc(100vw - 48px)); padding: 18px; }
+.dropdown-groups { display: grid; grid-template-columns: .85fr 1fr 1.45fr; gap: 12px; }
+.dropdown-group { min-width: 0; padding: 6px; border-radius: 11px; background: #f8fbff; }
+.dropdown .dropdown-group-title { margin: 0 0 5px; padding: 11px 12px; color: var(--blue-800); background: #eaf6ff; font-size: 14px; font-weight: 800; }
+.dropdown .dropdown-group-title::before { display: none; }
+.dropdown .dropdown-group-title:hover { transform: none; }
+.dropdown-group a:not(.dropdown-group-title) { padding-top: 8px; padding-bottom: 8px; font-size: 13px; }
.nav-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.language-switch { height: 38px; display: inline-grid; grid-template-columns: repeat(2,34px); align-items: center; padding: 3px; border: 1px solid rgba(0,144,255,.2); border-radius: 20px; background: var(--blue-50); box-shadow: inset 0 0 0 1px rgba(255,255,255,.7); }
.language-switch span,.language-switch a { height: 30px; display: grid; place-items: center; border-radius: 16px; font-size: 11px; font-weight: 800; letter-spacing: .4px; transition: color .25s ease, background .25s ease, transform .25s ease, box-shadow .25s ease; }
@@ -288,7 +295,6 @@ main { min-height: 72vh; }
.hero-orbit-two { right: 105px; top: 110px; width: 190px; height: 190px; opacity: .14; animation-direction: reverse; animation-duration: 11s; }
@keyframes orbit { to { transform: rotate(360deg); } }
.hero-copy { position: relative; z-index: 1; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; color: #fff; }
-.hero-index { position: absolute; right: 3%; bottom: -24px; color: rgba(255,255,255,.07); font-size: clamp(100px, 14vw, 185px); font-weight: 900; line-height: 1; letter-spacing: -8px; user-select: none; }
.hero-copy > span { display: flex; align-items: center; gap: 12px; color: rgba(255,255,255,.72); font-size: 10px; font-weight: 800; letter-spacing: 4px; }
.hero-copy > span::before { content: ""; width: 38px; height: 2px; background: var(--blue-300); }
.hero-copy h1 { margin: 11px 0 13px; max-width: 900px; font-size: clamp(40px, 5vw, 68px); line-height: 1.06; letter-spacing: -3px; text-shadow: 0 12px 38px rgba(0,0,0,.2); }
@@ -310,8 +316,7 @@ main { min-height: 72vh; }
/* Inner content */
.content-page { background: linear-gradient(180deg,#fff 0,var(--blue-50) 100%); padding-top: 76px; }
.content { padding: 96px 0 128px; }
-.section-heading { display: grid; grid-template-columns: 62px auto 1fr; align-items: center; gap: 20px; margin-bottom: 52px; }
-.section-heading > span { width: 62px; height: 62px; display: grid; place-items: center; color: #fff; border-radius: 18px 4px 18px 4px; background: linear-gradient(145deg,var(--blue-500),var(--blue-800)); box-shadow: 0 12px 28px rgba(8,120,232,.23); font-size: 18px; font-weight: 900; }
+.section-heading { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 20px; margin-bottom: 52px; }
.section-heading small { color: var(--blue-600); font-size: 10px; font-weight: 800; letter-spacing: 3px; }
.section-heading h2 { margin: 7px 0 0; font-size: clamp(30px,4vw,46px); letter-spacing: -2px; }
.section-heading i { height: 1px; margin-left: 20px; background: linear-gradient(90deg,var(--line),transparent); }
@@ -370,6 +375,81 @@ main { min-height: 72vh; }
.category-filters button { padding: 10px 16px; color: #587087; border: 0; border-radius: 10px; background: var(--blue-50); cursor: pointer; transition: .25s; }
.category-filters button:hover, .category-filters button.active { color: #fff; background: linear-gradient(135deg,var(--blue-500),var(--blue-700)); box-shadow: 0 8px 20px rgba(8,120,232,.2); }
.product-toolbar > span { flex: 0 0 auto; color: var(--muted); font-size: 12px; }
+.product-pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 9px; margin: 48px 0 0; }
+.product-pagination button { min-width: 42px; height: 42px; padding: 0 12px; color: #526b83; border: 1px solid rgba(8,120,232,.14); border-radius: 11px 3px 11px 3px; background: #fff; box-shadow: 0 8px 22px rgba(4,67,128,.06); cursor: pointer; font-weight: 750; transition: .25s ease; }
+.product-pagination button:hover:not(:disabled),.product-pagination button.active { color: #fff; border-color: transparent; background: linear-gradient(145deg,var(--blue-500),var(--blue-800)); box-shadow: 0 10px 25px rgba(8,120,232,.24); transform: translateY(-2px); }
+.product-pagination button:disabled { opacity: .35; cursor: not-allowed; }
+.purchase-channels { display: grid; grid-template-columns: minmax(260px,.7fr) minmax(0,1.3fr); gap: 46px; align-items: center; margin-top: 68px; padding: 42px 46px; overflow: hidden; color: #fff; border-radius: 28px 7px 28px 7px; background: linear-gradient(135deg,#005eae,#0090ff 68%,#42b5ff); box-shadow: 0 26px 65px rgba(0,88,167,.2); }
+.purchase-channel-copy small { color: rgba(255,255,255,.66); font-size: 10px; font-weight: 850; letter-spacing: 3px; }
+.purchase-channel-copy h2 { margin: 9px 0 12px; font-size: clamp(30px,3.5vw,44px); }
+.purchase-channel-copy p { max-width: 420px; margin: 0; color: rgba(255,255,255,.76); font-size: 14px; line-height: 1.8; }
+.purchase-channel-links { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 14px; }
+.purchase-channel-links a { display: grid; grid-template-columns: 48px minmax(0,1fr); gap: 16px; align-items: center; min-height: 118px; padding: 20px; color: var(--ink); border: 1px solid rgba(255,255,255,.5); border-radius: 18px 5px 18px 5px; background: rgba(255,255,255,.94); box-shadow: 0 14px 34px rgba(0,66,126,.16); transition: transform .3s ease, box-shadow .3s ease, background .3s ease; }
+.purchase-channel-links a:hover { color: var(--ink); background: #fff; box-shadow: 0 22px 44px rgba(0,57,112,.24); transform: translateY(-5px); }
+.purchase-channel-links a > span { width: 48px; height: 48px; display: grid; place-items: center; color: #fff; border-radius: 14px 4px 14px 4px; background: linear-gradient(145deg,var(--blue-500),var(--blue-800)); font-size: 13px; font-weight: 900; }
+.purchase-channel-links small { display: block; color: var(--blue-600); font-size: 9px; font-weight: 800; letter-spacing: 1.5px; }
+.purchase-channel-links strong { display: block; margin-top: 4px; font-size: 20px; }
+.purchase-channel-links b { grid-column: 2; color: var(--blue-700); font-size: 11px; }
+.purchase-channels.compact { display: block; margin: 28px 0 18px; padding: 18px; color: var(--ink); border: 1px solid rgba(8,120,232,.12); border-radius: 16px 4px 16px 4px; background: linear-gradient(145deg,#fff,var(--blue-50)); box-shadow: 0 12px 28px rgba(0,83,155,.07); }
+.purchase-channels.compact .purchase-channel-copy { margin-bottom: 12px; }
+.purchase-channels.compact .purchase-channel-copy > small,.purchase-channels.compact .purchase-channel-copy p { display: none; }
+.purchase-channels.compact .purchase-channel-copy h2 { margin: 0; color: var(--ink); font-size: 17px; }
+.purchase-channels.compact .purchase-channel-links { gap: 9px; }
+.purchase-channels.compact .purchase-channel-links a { grid-template-columns: 36px minmax(0,1fr); gap: 10px; min-height: 76px; padding: 10px 12px; border-color: rgba(8,120,232,.13); box-shadow: none; }
+.purchase-channels.compact .purchase-channel-links a > span { width: 36px; height: 36px; border-radius: 10px 3px 10px 3px; font-size: 10px; }
+.purchase-channels.compact .purchase-channel-links small { display: none; }
+.purchase-channels.compact .purchase-channel-links strong { margin: 0; font-size: 15px; }
+.purchase-channels.compact .purchase-channel-links b { font-size: 9px; }
+
+/* Single-page sports business sections */
+.sports-grouped-layout { display: grid; grid-template-columns: 210px minmax(0,1fr); gap: 54px; align-items: start; }
+.sports-side-nav { position: sticky; top: calc(var(--header-offset) + 92px); z-index: 25; padding: 24px 18px; border: 1px solid rgba(8,120,232,.12); border-radius: 20px 5px 20px 5px; background: rgba(255,255,255,.94); box-shadow: 0 18px 42px rgba(2,62,119,.09); backdrop-filter: blur(16px); }
+.sports-side-nav > small { display: block; margin: 0 8px 14px; color: var(--blue-600); font-size: 9px; font-weight: 850; letter-spacing: 2px; line-height: 1.6; }
+.sports-side-nav nav { display: grid; gap: 7px; }
+.sports-side-nav a { display: grid; grid-template-columns: 28px minmax(0,1fr); gap: 9px; align-items: center; padding: 12px 10px; color: #587087; border-radius: 11px 3px 11px 3px; font-size: 13px; font-weight: 700; transition: .25s ease; }
+.sports-side-nav a span { color: var(--blue-400); font-size: 10px; font-weight: 900; }
+.sports-side-nav a:hover,.sports-side-nav a.active { color: #fff; background: linear-gradient(145deg,var(--blue-500),var(--blue-800)); box-shadow: 0 10px 24px rgba(8,120,232,.22); transform: translateX(3px); }
+.sports-side-nav a:hover span,.sports-side-nav a.active span { color: rgba(255,255,255,.7); }
+.sports-grouped-content { min-width: 0; }
+.sports-grouped-section { scroll-margin-top: calc(var(--header-offset) + 135px); padding: 12px 0 104px; }
+.sports-grouped-section + .sports-grouped-section { padding-top: 92px; border-top: 1px solid var(--line); }
+.sports-grouped-heading { max-width: 820px; margin-bottom: 40px; }
+.sports-grouped-heading small { color: var(--blue-600); font-size: 10px; font-weight: 850; letter-spacing: 3px; }
+.sports-grouped-heading h2 { margin: 10px 0 13px; color: var(--ink); font-size: clamp(32px,4vw,50px); letter-spacing: -2px; }
+.sports-grouped-heading p { max-width: 680px; margin: 0; color: var(--muted); font-size: 14px; line-height: 1.85; }
+.sports-grouped-articles { margin-top: 0; }
+.sports-performance-block,.sports-text-gallery { display: grid; gap: 34px; }
+.sports-performance-block > .prose,.sports-text-gallery > .prose { max-width: 860px; padding: 30px 34px; border-left: 4px solid var(--blue-500); border-radius: 0 15px 15px 0; background: #fff; box-shadow: 0 14px 38px rgba(2,62,119,.07); }
+.sports-grouped-gallery { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 14px; }
+.sports-grouped-gallery img { width: 100%; height: 290px; object-fit: cover; border-radius: 18px 4px 18px 4px; box-shadow: 0 13px 34px rgba(2,62,119,.1); }
+.poster-gallery { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 18px; align-items: stretch; }
+.poster-gallery__card { position: relative; min-width: 0; min-height: 420px; padding: 18px; overflow: hidden; border: 1px solid rgba(8,120,232,.12); border-radius: 20px 5px 20px 5px; background: linear-gradient(145deg,#f7fbff,#eaf5ff); box-shadow: 0 13px 34px rgba(2,62,119,.1); cursor: zoom-in; }
+.poster-gallery__card img { display: block; width: 100%; height: 100%; max-height: 660px; object-fit: contain; transition: transform .35s ease; }
+.poster-gallery__card > span { position: absolute; right: 14px; bottom: 14px; display: inline-flex; align-items: center; gap: 8px; padding: 9px 12px; color: #fff; border-radius: 10px 3px 10px 3px; background: rgba(0,69,134,.82); box-shadow: 0 8px 22px rgba(0,47,91,.22); backdrop-filter: blur(10px); font-size: 11px; font-weight: 750; }
+.poster-gallery__card > span b { font-size: 14px; }
+.poster-gallery__card:hover img { transform: scale(1.018); }
+.poster-lightbox-open { overflow: hidden; }
+.poster-lightbox { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; color: #fff; outline: none; }
+.poster-lightbox__backdrop { position: absolute; inset: 0; background: rgba(0,16,31,.96); backdrop-filter: blur(14px); }
+.poster-lightbox__topbar { position: absolute; z-index: 3; top: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 18px 24px; background: linear-gradient(180deg,rgba(0,14,28,.82),transparent); }
+.poster-lightbox__topbar > div { min-width: 0; display: grid; gap: 3px; }
+.poster-lightbox__topbar strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
+.poster-lightbox__topbar small { color: rgba(255,255,255,.58); font-size: 11px; }
+.poster-lightbox__topbar button,.poster-lightbox__arrow,.poster-lightbox__controls button { display: grid; place-items: center; color: #fff; border: 1px solid rgba(255,255,255,.18); background: rgba(255,255,255,.1); backdrop-filter: blur(12px); cursor: pointer; }
+.poster-lightbox__topbar button { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%; font-size: 28px; line-height: 1; }
+.poster-lightbox__viewport { position: absolute; z-index: 1; inset: 72px 86px 76px; display: grid; place-items: center; overflow: hidden; touch-action: none; }
+.poster-lightbox__viewport.is-draggable { cursor: grab; }
+.poster-lightbox__viewport.is-dragging { cursor: grabbing; }
+.poster-lightbox__viewport img { display: block; flex: 0 0 auto; max-width: none; max-height: none; object-fit: fill; user-select: none; transform-origin: center; transition: transform .16s ease; }
+.poster-lightbox__viewport.is-dragging img { transition: none; }
+.poster-lightbox__arrow { position: absolute; z-index: 3; top: 50%; width: 48px; height: 66px; border-radius: 14px 4px 14px 4px; transform: translateY(-50%); font-size: 40px; }
+.poster-lightbox__arrow--previous { left: 20px; }
+.poster-lightbox__arrow--next { right: 20px; }
+.poster-lightbox__controls { position: absolute; z-index: 3; left: 50%; bottom: 20px; display: flex; align-items: center; gap: 7px; padding: 7px; border: 1px solid rgba(255,255,255,.12); border-radius: 14px 4px 14px 4px; background: rgba(0,35,69,.72); transform: translateX(-50%); backdrop-filter: blur(14px); }
+.poster-lightbox__controls button { min-width: 38px; height: 36px; border-radius: 9px 3px 9px 3px; font-size: 18px; }
+.poster-lightbox__controls button:disabled { opacity: .35; cursor: default; }
+.poster-lightbox__controls .poster-lightbox__scale { min-width: 68px; font-size: 11px; font-weight: 800; }
+.poster-lightbox button:hover:not(:disabled) { background: rgba(8,144,255,.65); }
.card-detail-link { display: block; margin-top: 18px; color: var(--blue-600); font-size: 12px; }
.content-detail-link { display: inline-flex; align-items: center; gap: 18px; margin-top: 20px; padding: 14px 20px; color: #fff; border-radius: 10px; background: linear-gradient(135deg,var(--blue-500),var(--blue-700)); box-shadow: 0 12px 24px rgba(8,120,232,.2); font-size: 13px; font-weight: 700; }
.content-detail-link span { transition: transform .25s; }
@@ -570,14 +650,16 @@ main { min-height: 72vh; }
.venue-city-title h3 { margin: 0; color: var(--ink); font-size: 29px; }
.venue-city-title b { margin-left: auto; color: var(--muted); font-size: 11px; font-weight: 600; }
.venue-grid { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 14px; }
-.venue-grid article { min-height: 128px; display: grid; grid-template-columns: 32px minmax(0,1fr); gap: 14px; align-items: start; padding: 23px 22px; border: 1px solid rgba(0,144,255,.12); border-radius: 15px 3px 15px 3px; background: #fff; box-shadow: 0 9px 28px rgba(0,83,155,.055); transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease; }
-.venue-grid article:hover { transform: translateY(-5px); border-color: rgba(0,144,255,.3); box-shadow: 0 18px 38px rgba(0,83,155,.11); }
+.venue-grid > a { min-height: 150px; display: grid; grid-template-columns: 32px minmax(0,1fr); gap: 14px; align-items: start; padding: 23px 22px; border: 1px solid rgba(0,144,255,.12); border-radius: 15px 3px 15px 3px; background: #fff; box-shadow: 0 9px 28px rgba(0,83,155,.055); transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease; }
+.venue-grid > a:hover { transform: translateY(-5px); border-color: rgba(0,144,255,.3); box-shadow: 0 18px 38px rgba(0,83,155,.11); }
.venue-pin { position: relative; width: 28px; height: 28px; border: 2px solid var(--blue-600); border-radius: 50% 50% 50% 6px; transform: rotate(-45deg); }
.venue-pin::after { content: ""; position: absolute; left: 8px; top: 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--blue-600); }
.venue-grid h4 { margin: 0 0 10px; color: var(--ink); font-size: 16px; }
.venue-grid p { margin: 0; color: #64788d; font-size: 12px; line-height: 1.75; }
+.venue-map-link { display: inline-flex; align-items: center; gap: 8px; margin-top: 14px; color: var(--blue-600); font-size: 11px; font-weight: 800; }
+.venue-map-link span { transition: transform .25s ease; }
+.venue-grid > a:hover .venue-map-link span { transform: translateX(4px); }
.contact-info-section { color: #fff; background: linear-gradient(135deg,#006fc9,#0090ff 68%,#3facff); }
-.contact-info-section .section-heading > span { color: var(--blue-700); background: #fff; box-shadow: 0 12px 30px rgba(0,73,135,.2); }
.contact-info-section .section-heading small { color: rgba(255,255,255,.68); }
.contact-info-section .section-heading h2 { color: #fff; }
.contact-info-section .section-heading i { background: linear-gradient(90deg,rgba(255,255,255,.3),transparent); }
@@ -676,9 +758,12 @@ main { min-height: 72vh; }
.dropdown::before, .dropdown-label { display: none; }
.dropdown a { display: inline-block; margin-right: 18px; padding: 9px 0; font-size: 14px; }
.dropdown a::before { display: none; }
+ .dropdown-mega { width: 100%; padding-left: 18px; }
+ .dropdown-groups { display: block; }
+ .dropdown-group { margin: 5px 0 10px; padding: 8px 10px; }
+ .dropdown .dropdown-group-title { display: block; margin: 0; padding: 9px 0; background: transparent; }
.home-original { padding-top: 70px; }
.page-hero { height: 400px; padding-top: 70px; }
- .hero-index { right: 5%; font-size: 130px; }
.scroll-cue { display: none; }
.subnav { justify-content: flex-start; min-height: 64px; overflow-x: auto; padding: 8px 20px; }
.subnav a { min-width: 120px; white-space: nowrap; }
@@ -715,6 +800,12 @@ main { min-height: 72vh; }
.product-summary { position: static; }
.detail-copy-grid { grid-template-columns: 1fr; gap: 38px; }
.related-grid { grid-template-columns: repeat(2,1fr); }
+ .purchase-channels { grid-template-columns: 1fr; gap: 28px; }
+ .sports-grouped-layout { grid-template-columns: 1fr; gap: 34px; }
+ .sports-side-nav { top: calc(var(--header-offset) + 64px); padding: 12px; overflow-x: auto; border-radius: 14px 3px 14px 3px; }
+ .sports-side-nav > small { display: none; }
+ .sports-side-nav nav { display: flex; width: max-content; min-width: 100%; gap: 7px; }
+ .sports-side-nav a { flex: 0 0 auto; min-width: 142px; transform: none; }
.editorial-detail { grid-template-columns: 1fr; gap: 35px; }
.editorial-detail aside { position: static; }
}
@@ -727,10 +818,8 @@ main { min-height: 72vh; }
.hero-orbit-two { display: none; }
.hero-copy h1 { margin-top: 10px; font-size: 38px; letter-spacing: -2px; }
.hero-copy p { font-size: 13px; line-height: 1.7; }
- .hero-index { bottom: -12px; font-size: 92px; letter-spacing: -6px; }
.content { padding: 68px 0 88px; }
- .section-heading { grid-template-columns: 48px auto; gap: 14px; margin-bottom: 38px; }
- .section-heading > span { width: 48px; height: 48px; border-radius: 13px 3px 13px 3px; font-size: 14px; }
+ .section-heading { grid-template-columns: minmax(0,auto) 1fr; gap: 14px; margin-bottom: 38px; }
.section-heading i { display: none; }
.section-heading h2 { font-size: 30px; }
.story-layout { padding: 25px 22px; border-radius: 19px 4px 19px 4px; }
@@ -784,6 +873,23 @@ main { min-height: 72vh; }
.product-toolbar { align-items: flex-start; flex-direction: column; }
.category-filters { width: 100%; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; }
.category-filters button { flex: 0 0 auto; }
+ .product-pagination { gap: 7px; margin-top: 36px; }
+ .product-pagination button { min-width: 38px; height: 38px; padding: 0 9px; }
+ .purchase-channels { margin-top: 48px; padding: 30px 24px; border-radius: 21px 5px 21px 5px; }
+ .purchase-channel-links { grid-template-columns: 1fr; }
+ .purchase-channels.compact .purchase-channel-links { grid-template-columns: 1fr; }
+ .sports-grouped-section { padding-bottom: 72px; }
+ .sports-grouped-section + .sports-grouped-section { padding-top: 62px; }
+ .sports-grouped-heading { margin-bottom: 30px; }
+ .sports-grouped-gallery { grid-template-columns: 1fr; }
+ .sports-grouped-gallery img { height: 230px; }
+ .poster-gallery { grid-template-columns: 1fr; }
+ .poster-gallery__card { min-height: 390px; padding: 12px; }
+ .poster-lightbox__topbar { padding: 13px 15px; }
+ .poster-lightbox__viewport { inset: 68px 12px 78px; }
+ .poster-lightbox__arrow { top: auto; bottom: 18px; width: 42px; height: 42px; border-radius: 50%; transform: none; font-size: 30px; }
+ .poster-lightbox__arrow--previous { left: 14px; }
+ .poster-lightbox__arrow--next { right: 14px; }
.detail-hero, .detail-hero-inner { min-height: 430px; }
.breadcrumbs { top: 24px; left: 0; }
.detail-hero h1 { font-size: 39px; letter-spacing: -2px; }
diff --git a/src/views/ContactPage.vue b/src/views/ContactPage.vue
index 5e4514e..f112673 100644
--- a/src/views/ContactPage.vue
+++ b/src/views/ContactPage.vue
@@ -4,8 +4,8 @@
-
08
CONTACT US联系我们
-
连接跃动社媒矩阵、业务合作网络与全国线下运动场馆。
+
CONTACT US联系我们
+
连接跃动社媒矩阵、业务合作网络与品牌服务团队。
CONNECT WITH YUEDONG
@@ -17,7 +17,7 @@
社媒与业务合作
社媒与业务合作
线下场馆地址
场馆按城市平铺展示,便于快速查找附近的跃动运动馆。门店信息可能调整,到访前可通过第三部分联系方式确认。
-{{ city.city }}
{{ city.venues.length }} 家场馆{{ venue.name }}
{{ venue.address }}
联系方式
联系方式
{{ contact.service }}
{{ contact.name }}
{{ contact.phone }}拨打电话 → @@ -80,7 +65,6 @@ import { useRoute } from 'vue-router'; const route = useRoute(); const sectionNav = [ { key: 'social', label: '社媒与合作' }, - { key: 'venues', label: '场馆地址' }, { key: 'contact-info', label: '联系方式' } ]; const activeKey = computed(() => sectionNav.some((item) => item.key === route.params.section) ? route.params.section : 'social'); @@ -100,57 +84,6 @@ const capabilities = [ { title: '装备服务', en: 'EQUIPMENT', description: '专业跳绳、智能装备及团体采购定制。' } ]; -const venueGroups = [ - { city: '上海', en: 'SHANGHAI', venues: [ - { name: '杨浦翔殷馆', address: '上海市杨浦区翔殷路260号' }, - { name: '杨浦新江湾运动健康中心馆', address: '上海市杨浦区国浩路701号201室' }, - { name: '宝山高境三邻桥馆', address: '上海市宝山区江杨南路485号三邻桥体育文化园11号101B室' }, - { name: '宝山体育中心馆', address: '上海市宝山区永清路700号体育中心内' }, - { name: '闵行七宝宝龙广场馆', address: '上海市闵行区漕宝路3299弄七宝宝龙广场3楼' }, - { name: '浦东金桥馆', address: '上海市浦东新区金藏路1296弄151号2楼2027室' }, - { name: '静安盛源生活广场馆', address: '上海市静安区柳营路777号盛源生活广场2楼' }, - { name: '静安889GLO广场馆', address: '上海市静安区万航渡路889号889广场3楼' }, - { name: '闵行力波馆', address: '上海市闵行区虹梅南路379弄27号力波九坊' }, - { name: '浦东恒生万鹂广场馆', address: '上海市浦东新区芳甸路115弄恒生万鹂广场' }, - { name: '虹口瑞虹星星堂馆', address: '上海市虹口区天宝路280弄瑞虹天地星星堂' }, - { name: '普陀曹杨复悦荟馆', address: '上海市普陀区曹杨路1888号复悦荟3楼' }, - { name: '青浦区跃动青少儿运动健康促进中心', address: '上海市青浦区淀山湖路535号4楼' } - ] }, - { city: '北京', en: 'BEIJING', venues: [ - { name: '西城官园馆', address: '北京市西城区西直门南小街2号楼B1-103' }, - { name: '丰台草桥馆', address: '北京市丰台区草桥欣园一区5号楼2楼260室' }, - { name: '西城马连道馆', address: '北京市西城区马连道街华睦大厦' }, - { name: '东城崇文门馆', address: '北京市东城区崇文门区域' }, - { name: '西城西便门馆', address: '北京市西城区西便门区域' }, - { name: '朝阳大郊亭馆', address: '北京市朝阳区大郊亭华腾新天地运动中心' } - ] }, - { city: '天津', en: 'TIANJIN', venues: [ - { name: '天津南开馆', address: '天津市南开区宾川道507号' }, - { name: '天津和平馆', address: '天津市和平区人民体育馆区域' } - ] }, - { city: '广州', en: 'GUANGZHOU', venues: [ - { name: '天河林和东馆', address: '广州市天河区林和东路218号2楼自编03室' }, - { name: '海珠广纸天地荟馆', address: '广州市海珠区工业大道广纸天地荟207-208' } - ] }, - { city: '徐州', en: 'XUZHOU', venues: [ - { name: '经开淮海环球港馆', address: '徐州市经开区淮海环球港L2096' }, - { name: '鼓楼金地商都馆', address: '徐州市鼓楼区中山北路6号金地商都' } - ] }, - { city: '合肥', en: 'HEFEI', venues: [ - { name: '庐阳华润橡树湾馆', address: '合肥市庐阳区华润橡树湾商业区' }, - { name: '包河馆', address: '合肥市包河区安徽省运动健康促进中心2楼' } - ] }, - { city: '成都', en: 'CHENGDU', venues: [ - { name: '武侯莱蒙都会馆', address: '成都市武侯区二环路南四段51号莱蒙都会商场4楼' } - ] }, - { city: '加盟场馆', en: 'FRANCHISE VENUES', venues: [ - { name: '松江大学城馆', address: '上海市松江区梅家浜路1501号3楼' }, - { name: '广西南宁馆', address: '南宁市青秀区星湖路1号' }, - { name: '江西信丰馆', address: '赣州市信丰县体育中心内' }, - { name: '江西上饶馆', address: '上饶市广信区旭日街道武夷山大道博华年华北区2栋111-113' } - ] } -]; - const contacts = [ { service: '赛事活动', en: 'EVENTS', name: '郭先生', phone: '16621102107' }, { service: '演艺服务', en: 'PERFORMANCE', name: '李先生', phone: '15201737732' }, diff --git a/src/views/ContentDetailPage.vue b/src/views/ContentDetailPage.vue index bd38562..6173bca 100644 --- a/src/views/ContentDetailPage.vue +++ b/src/views/ContentDetailPage.vue @@ -33,9 +33,17 @@ const detail = computed(() => { if (item) return { title: item.title || item.alt || source.title, body: item.body || source.body || [page.value.summary], gallery: source.gallery || [] }; return { title: source.title, body: source.body || source.articles?.flatMap((entry) => entry.body) || [page.value.summary], gallery: source.gallery || [] }; }); -const backPath = computed(() => ['technology', 'health', 'ygjrc'].includes(route.params.page) - ? `/${route.params.page}` - : `/${route.params.page}/${route.params.section}`); +const backPath = computed(() => { + if (route.params.page === 'sports') { + const competitionSections = ['event-recruitment', 'event-news', 'performances']; + const venueSections = ['venue-intro', 'champion-class', 'camps', 'venue-address']; + if (competitionSections.includes(route.params.section)) return `/sports/competition#${route.params.section}`; + if (venueSections.includes(route.params.section)) return `/sports/venues#${route.params.section}`; + } + return ['technology', 'health', 'ygjrc'].includes(route.params.page) + ? `/${route.params.page}` + : `/${route.params.page}/${route.params.section}`; +}); const heroStyle = computed(() => page.value?.hero?.src ? { backgroundImage: `url("${page.value.hero.src}")` } : {}); const unreadableImageName = /\uFFFD|锟斤拷|鈥|銆|鈫|馃|鍥剧墖|璺冨姩|鍏充簬|鏂伴椈|浜у搧|绀惧獟|璇︽儏/; const genericImageName = /^(?:微信图片|图片|image|img|dsc|screenshot|截图|未命名|幻灯片|slide|photo)[-_((\s]?\d*/i; diff --git a/src/views/ContentPage.vue b/src/views/ContentPage.vue index 5e3ea44..94f0099 100644 --- a/src/views/ContentPage.vue +++ b/src/views/ContentPage.vue @@ -6,43 +6,59 @@{{ page.title }}
{{ page.summary }}
{{ content.title }}
{{ content.title }}
{{ product.name || product.category }}
{{ product.description }}
查看产品详情 →{{ article.title }}
{{ line }}
{{ line }}
{{ card.title || card.alt }}
{{ card.body[0] }}
查看详情 →{{ card.title || card.alt }}
{{ card.body[0] }}
查看详情 →以跳绳为核心,连接专业装备、国际赛事、教育培训、智慧科技与运动健康,让每一次跃起都更有力量。
精选产品装备
精选跃动装备
{{ product.name }}
查看产品详情 ↗赛事资讯
竞赛演艺
{{ product.name }}
{{ product.category }} · 来源于《跳绳产品分类-7类资料》{{ product.sheet }}工作表第 {{ product.row }} 行
@@ -39,6 +39,7 @@{{ product.name }}
{{ descriptionLead }}
+同类产品
{{ item.name }}
查看详情 →