feat(home): 简介与视频前置、侧栏 Win/安卓直链;后台与 API 默认中文

Made-with: Cursor
This commit is contained in:
whm
2026-03-24 14:48:39 +08:00
parent f5852bc04e
commit 3222dffc64
5 changed files with 255 additions and 208 deletions

View File

@@ -17,13 +17,13 @@
<el-form v-if="siteId" ref="formRef" :model="form" label-width="120px" class="homepage-form">
<el-divider content-position="left">导航与标题</el-divider>
<el-form-item label="Logo 文案">
<el-input v-model="form.logo_text" placeholder="YUHENG ONE" />
<el-input v-model="form.logo_text" placeholder="宇恒一号" />
</el-form-item>
<el-form-item label="主标题">
<el-input v-model="form.title" placeholder="宇恒一号" />
</el-form-item>
<el-form-item label="副标题">
<el-input v-model="form.subtitle" placeholder="INTERSTELLAR EXPLORER EDITION" />
<el-input v-model="form.subtitle" placeholder="可选,前台大标题区已精简" />
</el-form-item>
<el-form-item label="描述">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="支持换行,会显示在首页" />
@@ -50,51 +50,46 @@
<el-button link type="primary" @click="form.nav_links.push({ label: '', url: '#' })">+ 添加链接</el-button>
</el-form-item>
<el-divider content-position="left">下载按钮</el-divider>
<el-form-item label="按钮文案">
<el-input v-model="form.download_text" placeholder="START EXPLORING" />
<el-divider content-position="left">侧栏下载Windows / 安卓直链</el-divider>
<p class="builder-tip" style="margin: -6px 0 12px">
填写同域可下载的静态地址需将安装包放到站点 <code>promotion/downloads/</code> 并部署前台为Windows 版下载安卓版下载直连不跳转整页
</p>
<el-form-item label="Windows 安装包">
<el-input v-model="form.download_windows_url" placeholder="/promotion/downloads/yuheng-windows.zip" />
</el-form-item>
<el-form-item label="按钮链接">
<el-form-item label="安卓安装包">
<el-input v-model="form.download_android_url" placeholder="/promotion/downloads/yuheng-android.apk" />
</el-form-item>
<el-divider content-position="left">旧版字段前台 Vue 已不使用轨道路由</el-divider>
<el-form-item label="下载按钮文案">
<el-input v-model="form.download_text" placeholder="下载" />
</el-form-item>
<el-form-item label="下载按钮链接">
<div style="display: flex; gap: 8px; align-items: center; flex-wrap: wrap; width: 100%">
<el-input v-model="form.download_url" placeholder="#" style="flex: 1; min-width: 200px" />
<el-button type="primary" link @click="openLinkPicker({ type: 'download' })">选择链接</el-button>
<el-link
v-if="previewReady(form.download_url)"
type="primary"
:href="previewHref(form.download_url)"
target="_blank"
rel="noopener noreferrer"
>试跳</el-link>
</div>
</el-form-item>
<el-divider content-position="left">平台轨道</el-divider>
<el-form-item label="平台列表">
<el-form-item label="平台轨道(可选)">
<div v-for="(p, i) in form.platforms" :key="i" style="display: flex; gap: 8px; margin-bottom: 8px; align-items: center">
<el-input v-model="p.name" placeholder="如 WINDOWS" style="width: 140px" />
<el-input v-model="p.name" placeholder="名称" style="width: 140px" />
<el-input v-model="p.url" placeholder="链接" style="flex: 1; min-width: 140px" />
<el-button type="primary" link @click="openLinkPicker({ type: 'platform', index: i })">选择链接</el-button>
<el-link
v-if="previewReady(p.url)"
type="primary"
:href="previewHref(p.url)"
target="_blank"
rel="noopener noreferrer"
>试跳</el-link>
<el-button link type="danger" @click="form.platforms.splice(i, 1)">删除</el-button>
</div>
<el-button link type="primary" @click="form.platforms.push({ name: '', url: '#' })">+ 添加平台</el-button>
<el-button link type="primary" @click="form.platforms.push({ name: '', url: '#' })">+ 添加</el-button>
</el-form-item>
<el-divider content-position="left">版本与徽章</el-divider>
<el-divider content-position="left">版本与徽章前台已隐藏主视觉条可留空</el-divider>
<el-form-item label="版本">
<el-input v-model="form.version" placeholder="VERSION 3.2.1" style="width: 200px" />
<el-input v-model="form.version" placeholder="可留空" style="width: 200px" />
</el-form-item>
<el-form-item label="发射年份">
<el-input v-model="form.launch_year" placeholder="LAUNCH: 2024" style="width: 200px" />
<el-form-item label="发布说明">
<el-input v-model="form.launch_year" placeholder="发布日期:以官网为准" style="width: 200px" />
</el-form-item>
<el-form-item label="徽章文案">
<el-input v-model="form.badge_text" placeholder="FREE ACCESS" style="width: 200px" />
<el-input v-model="form.badge_text" placeholder="完全免费" style="width: 200px" />
</el-form-item>
<el-divider content-position="left">特性卡片</el-divider>
@@ -108,12 +103,12 @@
</el-form-item>
<el-form-item label="页脚文案">
<el-input v-model="form.footer_text" placeholder="© 2024 YUHENG ONE" />
<el-input v-model="form.footer_text" placeholder="© 2024 宇恒一号 · 成都宇信达智能科技有限公司" />
</el-form-item>
<el-divider content-position="left">首页下方扩展区可视化积木可拖拽排序</el-divider>
<p class="builder-tip">
网页管理 积木相同从左侧手柄拖拽调整模块顺序保存后内容显示在落地页主视觉与特性卡片<strong>之后</strong>页脚之前留空则不显示扩展区
网页管理 积木相同从左侧手柄拖拽调整模块顺序保存后内容显示在落地页主体模块<strong>之后</strong>页脚之前留空则不显示扩展区
</p>
<el-form-item label="扩展积木" class="builder-form-item homepage-builder-wrap">
<PageBuilderEditor v-model="form.body_builder" :site-id="siteId" />
@@ -149,29 +144,29 @@ const linkPickerVisible = ref(false)
const linkPickTarget = ref({ type: 'download' })
const defaultForm = () => ({
logo_text: 'YUHENG ONE',
nav_links: [{ label: 'MISSION', url: '#' }, { label: 'DOWNLOAD', url: '#' }, { label: 'CONTACT', url: '#' }],
title: '宇恒一号',
subtitle: 'INTERSTELLAR EXPLORER EDITION',
description: '跨越星际的智能伙伴 · 探索无限可能\n引领您进入前所未有的数字宇宙',
download_text: 'START EXPLORING',
download_url: '#',
platforms: [
{ name: 'WINDOWS', url: '#' },
{ name: 'MACOS', url: '#' },
{ name: 'LINUX', url: '#' },
{ name: 'IOS', url: '#' },
{ name: 'ANDROID', url: '#' }
logo_text: '宇恒一号',
nav_links: [
{ label: '产品简介', url: '#intro' },
{ label: '产品视频', url: '#videos' },
{ label: '联系我们', url: '#contact' }
],
version: 'VERSION 3.2.1',
launch_year: 'LAUNCH: 2024',
badge_text: 'FREE ACCESS',
title: '宇恒一号',
subtitle: '',
description: '跨越星际的智能伙伴 · 探索无限可能\n引领您进入前所未有的数字宇宙',
download_text: '下载',
download_url: '#',
download_windows_url: '/promotion/downloads/yuheng-windows.zip',
download_android_url: '/promotion/downloads/yuheng-android.apk',
platforms: [],
version: '',
launch_year: '发布日期:以官网为准',
badge_text: '完全免费',
features: [
{ title: '星际导航', desc: '先进的 AI 导航系统,精准定位您的需求,引领探索之旅' },
{ title: '量子同步', desc: '跨维度数据同步技术,您的数据在多宇宙中保持一致' },
{ title: '星际防护', desc: '来自未来的安全加密协议,守护您的数字资产安全' }
],
footer_text: '© 2024 YUHENG ONE // STELLAR EXPLORATION INITIATIVE',
footer_text: '© 2024 宇恒一号 · 成都宇信达智能科技有限公司',
body_builder: ''
})
@@ -205,12 +200,15 @@ const fetchData = async () => {
if (!siteId.value) return
try {
const data = await getHomepage(siteId.value)
const base = defaultForm()
Object.assign(form, {
...defaultForm(),
...base,
...data,
nav_links: Array.isArray(data.nav_links) && data.nav_links.length ? data.nav_links : defaultForm().nav_links,
platforms: Array.isArray(data.platforms) && data.platforms.length ? data.platforms : defaultForm().platforms,
features: Array.isArray(data.features) && data.features.length ? data.features : defaultForm().features
nav_links: Array.isArray(data.nav_links) && data.nav_links.length ? data.nav_links : base.nav_links,
platforms: Array.isArray(data.platforms) ? data.platforms : base.platforms,
features: Array.isArray(data.features) && data.features.length ? data.features : base.features,
download_windows_url: data.download_windows_url || base.download_windows_url,
download_android_url: data.download_android_url || base.download_android_url
})
} catch (e) {
ElMessage.error(e.message)

View File

@@ -186,29 +186,25 @@ func DownloadHomepage(c *gin.Context) {
func defaultHomepageData() models.HomepageData {
return models.HomepageData{
LogoText: "YUHENG ONE",
NavLinks: []models.NavLink{{Label: "MISSION", URL: "#"}, {Label: "DOWNLOAD", URL: "#"}, {Label: "CONTACT", URL: "#"}},
LogoText: "宇恒一号",
NavLinks: []models.NavLink{{Label: "产品简介", URL: "#intro"}, {Label: "产品视频", URL: "#videos"}, {Label: "联系我们", URL: "#contact"}},
Title: "宇恒一号",
Subtitle: "INTERSTELLAR EXPLORER EDITION",
Description: "跨越星际的智能伙伴 · 探索无限可能<br>\n 引领您进入前所未有的数字宇宙",
DownloadText: "START EXPLORING",
Subtitle: "",
Description: "",
DownloadText: "下载",
DownloadURL: "#",
Platforms: []models.PlatformItem{
{Name: "WINDOWS", URL: "#"},
{Name: "MACOS", URL: "#"},
{Name: "LINUX", URL: "#"},
{Name: "IOS", URL: "#"},
{Name: "ANDROID", URL: "#"},
},
Version: "VERSION 3.2.1",
LaunchYear: "LAUNCH: 2024",
BadgeText: "FREE ACCESS",
Platforms: []models.PlatformItem{},
Version: "",
LaunchYear: "发布日期:以官网为准",
BadgeText: "完全免费",
DownloadWindowsURL: "/promotion/downloads/yuheng-windows.zip",
DownloadAndroidURL: "/promotion/downloads/yuheng-android.apk",
Features: []models.FeatureItem{
{Title: "星际导航", Desc: "先进的 AI 导航系统,精准定位您的需求,引领探索之旅"},
{Title: "量子同步", Desc: "跨维度数据同步技术,您的数据在多宇宙中保持一致"},
{Title: "星际防护", Desc: "来自未来的安全加密协议,守护您的数字资产安全"},
},
FooterText: "© 2024 YUHENG ONE // STELLAR EXPLORATION INITIATIVE",
FooterText: "© 2024 宇恒一号 · 成都宇信达智能科技有限公司",
}
}

View File

@@ -40,6 +40,9 @@ type HomepageData struct {
BadgeText string `json:"badge_text"` // FREE ACCESS
Features []FeatureItem `json:"features"` // 星际导航等
FooterText string `json:"footer_text"` // © 2024 YUHENG ONE
// 侧栏直链(与 web 首页 Home.vue 一致,同域静态路径)
DownloadWindowsURL string `json:"download_windows_url,omitempty"`
DownloadAndroidURL string `json:"download_android_url,omitempty"`
// BodyBuilder 首页下方扩展区:与网页积木相同 JSON 字符串 {"version":1,"blocks":[...]},空则仅展示上方模板
BodyBuilder string `json:"body_builder,omitempty"`
}

View File

View File

@@ -7,9 +7,9 @@
<div class="planet planet-3"></div>
<nav class="navbar" :style="navbarStyle">
<a href="#home" class="logo-space" @click.prevent="scrollToSel('#home')">
<a href="#intro" class="logo-space" @click.prevent="scrollToSel('#intro')">
<img class="logo-space-img" src="/logo.png" alt="" width="40" height="40" decoding="async" />
<span class="logo-space-text">{{ data.logo_text || 'YUHENG ONE' }}</span>
<span class="logo-space-text">{{ data.logo_text || '宇恒一号' }}</span>
</a>
<div class="nav-links">
<template v-for="(link, i) in data.nav_links" :key="i">
@@ -24,55 +24,14 @@
</div>
</nav>
<section class="hero" id="home">
<div class="title-container">
<h1 class="title-3d">
<span v-for="(ch, i) in titleChars" :key="i">{{ ch }}</span>
</h1>
</div>
<p class="subtitle-space">{{ data.subtitle || 'INTERSTELLAR EXPLORER EDITION' }}</p>
<p class="description-space" v-html="descriptionHtml"></p>
<div class="download-warp">
<div class="warp-effect"></div>
<a
href="#download"
class="warp-btn"
@click.prevent="scrollToSel('#download')"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
{{ data.download_text || '免费下载' }}
</a>
</div>
<div class="orbit-platforms" id="download">
<div class="orbit-collision-ring" aria-hidden="true"></div>
<a v-for="(p, i) in data.platforms" :key="i" class="orbit-platform" :href="p.url || '#'" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24"><path d="M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></svg>
<span>{{ p.name }}</span>
</a>
</div>
<div class="mission-info">
<span class="mission-badge">{{ data.version || 'VERSION 3.2.1' }}</span>
<span>🚀 {{ data.launch_year || '发布日期: 2024年' }}</span>
<span> {{ data.badge_text || '完全免费' }}</span>
<span>🔒 {{ data.privacy_text || '隐私保护' }}</span>
</div>
<div class="features-space" id="features">
<div v-for="(f, i) in data.features" :key="i" class="feature-space">
<div class="feature-icon"><svg viewBox="0 0 24 24"><path :d="featureIconPath(i)"/></svg></div>
<h3>{{ f.title }}</h3>
<p>{{ f.desc }}</p>
</div>
</div>
</section>
<div class="portal-shell">
<div class="portal-shell home-portal-shell">
<div class="portal-inner portal-inner--main">
<main class="portal-main">
<!-- 当前章节正文预览章节列表点击切换不跳转路由 -->
<div class="portal-row-split portal-card">
<!-- 简介前置与宣传册同源 -->
<div id="intro" class="portal-row-split portal-card home-lead intro-card">
<div class="portal-preview-wrap">
<h3 class="portal-block-title">宣传册预览</h3>
<p class="portal-preview-tip">在右侧选择章节此处即时展示正文与完整宣传册同源文案</p>
<h3 class="portal-block-title">产品简介</h3>
<p class="portal-preview-tip">在右侧选择章节此处即时展示正文与完整宣传册同源</p>
<div class="portal-preview-body">
<HomeBrochurePreview :topic="selectedBrochureTopic" @update:topic="selectedBrochureTopic = $event" />
</div>
@@ -99,57 +58,9 @@
</div>
</div>
<!-- 统计数据 promotion/index.html 一致 -->
<section class="stats-section portal-card-lite">
<div class="stats-container">
<div class="stat-item"><div class="stat-number">50+</div><div class="stat-label">活跃用户</div></div>
<div class="stat-item"><div class="stat-number">99.9%</div><div class="stat-label">服务可用性</div></div>
<div class="stat-item"><div class="stat-number">8+</div><div class="stat-label">核心功能</div></div>
<div class="stat-item"><div class="stat-number">24/7</div><div class="stat-label">技术支持</div></div>
</div>
</section>
<section class="highlights-section">
<div class="section-title">
<h2>为什么选择宇恒一号</h2>
<p>融合前沿 AI 技术为您打造前所未有的智能体验</p>
</div>
<div class="highlight-grid">
<div class="highlight-card" v-for="(h, i) in highlightCards" :key="i">
<div class="highlight-icon"><svg viewBox="0 0 24 24"><path :d="h.icon"/></svg></div>
<h3>{{ h.title }}</h3>
<p>{{ h.desc }}</p>
<router-link v-if="h.to" :to="h.to" class="card-jump-link">跳转宣传册{{ h.linkLabel }} </router-link>
</div>
</div>
</section>
<section class="scenarios-section" id="scenarios">
<div class="section-title">
<h2>适用场景</h2>
<p>宇恒一号广泛应用于各行各业助力数字化转型升级</p>
</div>
<div class="scenarios-grid">
<div class="scenario-card" v-for="(s, i) in scenarioCards" :key="i">
<div class="scenario-icon"><svg viewBox="0 0 24 24"><path :d="s.icon"/></svg></div>
<div class="scenario-content">
<h4>{{ s.title }}</h4>
<p>{{ s.desc }}</p>
<router-link v-if="s.to" :to="s.to" class="card-jump-link subtle">进入宣传册相关章节 </router-link>
</div>
</div>
</div>
<div class="brochure-cta">
<p>以下为宣传册各章节<strong>路由跳转</strong>非仅展示可点开逐页浏览</p>
<div class="brochure-multi">
<router-link v-for="b in brochureEntryLinks" :key="b.topic" :to="'/brochure/' + b.topic" class="brochure-chip">{{ b.label }}</router-link>
</div>
<router-link to="/brochure/company" class="brochure-btn">从第一章开始阅读</router-link>
</div>
</section>
<section class="video-section" id="videos">
<div class="section-title">
<!-- 视频紧随简介放大展示 -->
<section class="video-section home-lead-video portal-card" id="videos">
<div class="section-title section-title--lead">
<h2>产品视频</h2>
<p>以下为产品介绍视频点击即可播放</p>
</div>
@@ -197,6 +108,63 @@
</div>
</section>
<div class="features-space home-features" id="features">
<div v-for="(f, i) in data.features" :key="i" class="feature-space">
<div class="feature-icon"><svg viewBox="0 0 24 24"><path :d="featureIconPath(i)"/></svg></div>
<h3>{{ f.title }}</h3>
<p>{{ f.desc }}</p>
</div>
</div>
<!-- 统计数据 promotion/index.html 一致 -->
<section class="stats-section portal-card-lite">
<div class="stats-container">
<div class="stat-item"><div class="stat-number">50+</div><div class="stat-label">活跃用户</div></div>
<div class="stat-item"><div class="stat-number">99.9%</div><div class="stat-label">服务可用性</div></div>
<div class="stat-item"><div class="stat-number">8+</div><div class="stat-label">核心功能</div></div>
<div class="stat-item"><div class="stat-number">7×24</div><div class="stat-label">技术支持</div></div>
</div>
</section>
<section class="highlights-section">
<div class="section-title">
<h2>为什么选择宇恒一号</h2>
<p>融合前沿 AI 技术为您打造前所未有的智能体验</p>
</div>
<div class="highlight-grid">
<div class="highlight-card" v-for="(h, i) in highlightCards" :key="i">
<div class="highlight-icon"><svg viewBox="0 0 24 24"><path :d="h.icon"/></svg></div>
<h3>{{ h.title }}</h3>
<p>{{ h.desc }}</p>
<router-link v-if="h.to" :to="h.to" class="card-jump-link">跳转宣传册{{ h.linkLabel }} </router-link>
</div>
</div>
</section>
<section class="scenarios-section" id="scenarios">
<div class="section-title">
<h2>适用场景</h2>
<p>宇恒一号广泛应用于各行各业助力数字化转型升级</p>
</div>
<div class="scenarios-grid">
<div class="scenario-card" v-for="(s, i) in scenarioCards" :key="i">
<div class="scenario-icon"><svg viewBox="0 0 24 24"><path :d="s.icon"/></svg></div>
<div class="scenario-content">
<h4>{{ s.title }}</h4>
<p>{{ s.desc }}</p>
<router-link v-if="s.to" :to="s.to" class="card-jump-link subtle">进入宣传册相关章节 </router-link>
</div>
</div>
</div>
<div class="brochure-cta">
<p>以下为宣传册各章节<strong>路由跳转</strong>非仅展示可点开逐页浏览</p>
<div class="brochure-multi">
<router-link v-for="b in brochureEntryLinks" :key="b.topic" :to="'/brochure/' + b.topic" class="brochure-chip">{{ b.label }}</router-link>
</div>
<router-link to="/brochure/company" class="brochure-btn">从第一章开始阅读</router-link>
</div>
</section>
<section class="testimonials-section" id="testimonials">
<div class="section-title">
<h2>用户评价</h2>
@@ -308,11 +276,18 @@
<span class="portal-social-tile-label">{{ item.label }}</span>
</button>
</div>
<div class="portal-aside-download-row" role="group" aria-label="客户端下载">
<a
href="#download"
class="portal-aside-download"
@click.prevent="scrollToSel('#download')"
>前往下载 </a>
:href="downloadWindowsHref"
:download="downloadWindowsFilename"
>Windows 版下载</a>
<a
class="portal-aside-download portal-aside-download--secondary"
:href="downloadAndroidHref"
:download="downloadAndroidFilename"
>安卓版下载</a>
</div>
</div>
</aside>
</div>
@@ -322,7 +297,7 @@
<div class="footer-logo">宇恒一号</div>
<div class="footer-company">成都宇信达智能科技有限公司</div>
<div class="footer-links">
<a href="#home" @click.prevent="scrollToSel('#home')">首页</a>
<a href="#intro" @click.prevent="scrollToSel('#intro')">首页</a>
<a href="#features" @click.prevent="scrollToSel('#features')">功能特性</a>
<a href="#scenarios" @click.prevent="scrollToSel('#scenarios')">应用场景</a>
<router-link to="/brochure/company">宣传册</router-link>
@@ -436,29 +411,27 @@ const socialQrCandidates = ref([])
const socialQrCandidateIdx = ref(0)
const defaultData = () => ({
logo_text: 'YUHENG ONE',
logo_text: '宇恒一号',
/** 侧栏直链:请将安装包放到 web/promotion/downloads/ 下同名文件,部署脚本会同步到站点 */
download_windows_url: '/promotion/downloads/yuheng-windows.zip',
download_android_url: '/promotion/downloads/yuheng-android.apk',
nav_links: [
{ label: '产品简介', url: '#intro' },
{ label: '产品视频', url: '#videos' },
{ label: '功能特性', url: '#features' },
{ label: '应用场景', url: '#scenarios' },
{ label: '产品视频', url: '#videos' },
{ label: '宣传册', url: '/brochure/company' },
{ label: '关注我们', url: '#social-follow' },
{ label: '联系我们', url: '#contact' }
],
title: '宇恒一号',
subtitle: 'INTERSTELLAR EXPLORER EDITION',
description: '跨越星际的智能伙伴 · 探索无限可能\n引领您进入前所未有的数字宇宙释放无限创造力',
download_text: '免费下载',
download_url: '#download',
platforms: [
{ name: 'WINDOWS', url: '#' },
{ name: 'MACOS', url: '#' },
{ name: 'LINUX', url: '#' },
{ name: 'IOS', url: '#' },
{ name: 'ANDROID', url: '#' }
],
version: 'VERSION 3.2.1',
launch_year: '发布日期: 2024年',
subtitle: '',
description: '',
download_text: '下载',
download_url: '#',
platforms: [],
version: '',
launch_year: '发布日期:以官网为准',
badge_text: '完全免费',
privacy_text: '隐私保护',
features: [
@@ -469,17 +442,26 @@ const defaultData = () => ({
{ title: '多维协作', desc: '支持团队协作,跨时空共享智慧与资源' },
{ title: '星际通讯', desc: '智能对话系统,理解上下文,精准回答您的问题' }
],
footer_text: '© 2024 宇恒一号 YUHENG ONE // 成都宇信达智能科技有限公司',
footer_text: '© 2024 宇恒一号 · 成都宇信达智能科技有限公司',
body_builder: ''
})
const data = reactive(defaultData())
const titleChars = computed(() => [...(data.title || '宇恒一号')])
const descriptionHtml = computed(() => {
const s = (data.description || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
return s.replace(/\n/g, '<br>')
})
const downloadWindowsHref = computed(() => data.download_windows_url || '/promotion/downloads/yuheng-windows.zip')
const downloadAndroidHref = computed(() => data.download_android_url || '/promotion/downloads/yuheng-android.apk')
function basenameFromUrl(u) {
if (!u || typeof u !== 'string') return ''
try {
const path = u.replace(/^[a-z]+:\/\/[^/]+/i, '')
const seg = path.split('/').filter(Boolean)
return seg.length ? decodeURIComponent(seg[seg.length - 1].split('?')[0]) : ''
} catch {
return ''
}
}
const downloadWindowsFilename = computed(() => basenameFromUrl(downloadWindowsHref.value) || 'yuheng-windows.zip')
const downloadAndroidFilename = computed(() => basenameFromUrl(downloadAndroidHref.value) || 'yuheng-android.apk')
const navbarStyle = computed(() => {
const y = scrollY.value
@@ -512,7 +494,7 @@ const bodyBuilderBlocks = computed(() => {
const highlightCards = [
{ title: '智能高效', desc: 'AI 驱动的工作流自动化,化繁为简,大幅提升效率', icon: 'M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79s7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58s9.14-3.47 12.65 0L21 3v7.12z', to: '/brochure/advantages', linkLabel: '核心优势' },
{ title: '安全可靠', desc: '企业级数据保护,隐私加密,您的数据仅属于您自己', icon: 'M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z', to: '/brochure/functions', linkLabel: '功能模块' },
{ title: '全平台支持', desc: 'Windows、macOS、Linux、iOS、Android 全覆盖', icon: 'M4.5 9.5C5.88 9.5 7 8.38 7 7S5.88 4.5 4.5 4.5 2 5.62 2 7s1.12 2.5 2.5 2.5zM9 8v8l6-4-6-4zm10.5.5c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5z', to: '/brochure/intro', linkLabel: '产品介绍' },
{ title: '双端覆盖', desc: '提供 Windows 与安卓客户端,侧栏一键下载安装包', icon: 'M4.5 9.5C5.88 9.5 7 8.38 7 7S5.88 4.5 4.5 4.5 2 5.62 2 7s1.12 2.5 2.5 2.5zM9 8v8l6-4-6-4zm10.5.5c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5z', to: '/brochure/intro', linkLabel: '产品介绍' },
{ title: '云端同步', desc: '本地与云端协同,多设备无缝切换', icon: 'M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z', to: '/brochure/functions', linkLabel: '功能模块' },
{ title: '持续进化', desc: '模型与能力持续迭代,越用越智能', icon: 'M12 3L1 9l11 6 9-4.91V17h2V9L12 3z', to: '/brochure/intro', linkLabel: '产品介绍' },
{ title: '免费使用', desc: '基础能力免费开放,无隐藏收费', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z', to: '/brochure/support', linkLabel: '服务支持' }
@@ -574,7 +556,7 @@ const testimonials = [
const faqList = [
{ q: '宇恒一号是完全免费的吗?', a: '基础功能可免费使用;我们也提供更高阶的能力与定制服务,满足不同规模团队需求。' },
{ q: '我的数据安全有保障吗?', a: '我们重视隐私与合规,采用加密与安全实践;您可按部署方式选择数据留存在本地或受控环境。' },
{ q: '支持哪些操作系统', a: '支持 Windows、macOS、Linux 及主流移动端;具体以官方下载页为准。' },
{ q: '支持哪些客户端', a: '目前提供 Windows 与安卓安装包下载;其他版本如有发布将同步在官网更新。' },
{ q: '如何获取技术支持?', a: '可通过官网邮箱、公众号等渠道联系我们,也可查阅宣传册中的服务与支持章节。' }
]
@@ -713,6 +695,8 @@ async function fetchHomepage() {
Object.assign(data, base, json)
if (Array.isArray(json.nav_links) && json.nav_links.length) data.nav_links = json.nav_links
if (Array.isArray(json.platforms) && json.platforms.length) data.platforms = json.platforms
if (typeof json.download_windows_url === 'string' && json.download_windows_url) data.download_windows_url = json.download_windows_url
if (typeof json.download_android_url === 'string' && json.download_android_url) data.download_android_url = json.download_android_url
if (Array.isArray(json.features) && json.features.length) data.features = json.features
} catch (_) {}
}
@@ -731,7 +715,7 @@ onMounted(() => {
})
}
fetchHomepage()
document.title = (data.title || '宇恒一号') + ' - 星际探索版'
document.title = (data.title || '宇恒一号') + ' - 首页'
window.addEventListener('scroll', onScroll, { passive: true })
document.addEventListener('keydown', onDocKeydown)
nextTick(() => {
@@ -842,12 +826,12 @@ onUnmounted(() => {
display: block; flex-shrink: 0;
}
.logo-space-text {
font-family: 'Exo 2', sans-serif; font-size: 24px; font-weight: 900;
font-family: 'Noto Sans SC', sans-serif; font-size: 22px; font-weight: 800;
background: linear-gradient(90deg, var(--plasma-cyan), var(--star-white), var(--plasma-pink));
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
background-clip: text; letter-spacing: 3px;
background-clip: text; letter-spacing: 0.15em;
}
.nav-links { display: flex; gap: 28px; flex-wrap: wrap; font-family: 'Exo 2', sans-serif; font-size: 12px; letter-spacing: 2px; }
.nav-links { display: flex; gap: 28px; flex-wrap: wrap; font-family: 'Noto Sans SC', sans-serif; font-size: 13px; letter-spacing: 0.06em; }
.nav-link-item { color: rgba(255,255,255,0.6); text-decoration: none; transition: color 0.3s; }
.nav-link-item:hover { color: var(--plasma-cyan); }
.router-link-active.nav-link-item { color: var(--plasma-cyan); }
@@ -958,7 +942,7 @@ onUnmounted(() => {
border-radius: 15px; display: flex; align-items: center; justify-content: center; margin-bottom: 20px;
}
.feature-icon svg { width: 28px; height: 28px; fill: var(--space-dark); }
.feature-space h3 { font-family: 'Exo 2', sans-serif; font-size: 18px; color: var(--star-white); margin-bottom: 12px; letter-spacing: 1px; }
.feature-space h3 { font-family: 'Noto Sans SC', sans-serif; font-size: 18px; color: var(--star-white); margin-bottom: 12px; letter-spacing: 0.04em; }
.feature-space p { color: rgba(255,255,255,0.5); font-size: 14px; line-height: 1.7; }
/* 门户主栏 + 侧栏(约 75% / 25% */
@@ -968,6 +952,73 @@ onUnmounted(() => {
background: linear-gradient(180deg, rgba(10, 12, 22, 0.4) 0%, rgba(18, 22, 38, 0.92) 8%, rgba(20, 24, 40, 0.98) 100%);
padding: 36px 0 8px;
}
.home-portal-shell {
padding-top: 64px;
}
.intro-card {
margin-bottom: 28px;
}
.home-lead .portal-block-title {
font-size: clamp(1.2rem, 2.4vw, 1.85rem);
margin-bottom: 16px;
}
.home-lead .portal-preview-tip {
font-size: 14px;
}
.home-lead .portal-preview-body {
max-height: min(82vh, 720px);
font-size: 15px;
line-height: 1.68;
}
.home-lead-video {
margin-bottom: 28px;
padding: 32px 26px 40px !important;
}
.home-lead-video .section-title--lead {
margin-bottom: 36px;
}
.home-lead-video .section-title--lead h2 {
font-size: clamp(1.55rem, 3.4vw, 2.4rem);
letter-spacing: 0.12em;
font-family: 'Noto Sans SC', sans-serif;
}
.home-lead-video .section-title--lead p {
font-size: 17px;
max-width: 640px;
}
.home-lead-video .main-thumb {
min-height: min(52vw, 440px);
}
.home-lead-video .video-info h3 {
font-size: clamp(1.2rem, 2.2vw, 1.75rem);
font-family: 'Noto Sans SC', sans-serif;
}
.home-features {
margin-bottom: 28px;
padding: 8px 8px 12px;
border-radius: 16px;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(0, 212, 255, 0.1);
}
.portal-aside-download-row {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 18px;
}
.portal-aside-download-row .portal-aside-download {
margin-top: 0;
}
.portal-aside-download--secondary {
background: rgba(10, 18, 36, 0.95);
color: var(--plasma-cyan);
border: 1px solid rgba(0, 212, 255, 0.5);
font-family: 'Noto Sans SC', sans-serif;
letter-spacing: 0.06em;
}
.portal-aside-download--secondary:hover {
filter: brightness(1.12);
}
/* 主内容区单独一列;大屏为右侧 fixed 侧栏预留空间,避免正文被遮挡 */
.portal-inner--main {
max-width: 1320px;
@@ -1217,8 +1268,8 @@ onUnmounted(() => {
text-align: center;
border-radius: 10px;
font-size: 13px;
font-family: 'Exo 2', sans-serif;
letter-spacing: 1px;
font-family: 'Noto Sans SC', sans-serif;
letter-spacing: 0.06em;
color: var(--space-dark);
text-decoration: none;
background: linear-gradient(135deg, var(--plasma-cyan), var(--plasma-pink));
@@ -1251,8 +1302,8 @@ onUnmounted(() => {
.section-title { text-align: center; margin-bottom: 50px; }
.section-title h2 {
font-family: 'Exo 2', sans-serif; font-size: clamp(26px, 5vw, 40px); color: var(--star-white);
margin-bottom: 12px; letter-spacing: 3px;
font-family: 'Noto Sans SC', sans-serif; font-size: clamp(26px, 5vw, 40px); color: var(--star-white);
margin-bottom: 12px; letter-spacing: 0.08em;
}
.section-title p { color: rgba(255,255,255,0.5); font-size: 16px; max-width: 600px; margin: 0 auto; }
@@ -1513,7 +1564,6 @@ onUnmounted(() => {
@media (max-width: 768px) {
.navbar { padding: 15px 20px; }
.planet { display: none; }
.orbit-platforms::before { display: none; }
.stats-container { grid-template-columns: 1fr; }
.testimonials-grid { grid-template-columns: 1fr; }
}