Compare commits
11 Commits
ec6222d183
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f02e6555af | |||
| c56f65898b | |||
| d9a3fc16a4 | |||
| 9309e3e76a | |||
| 68e6e98234 | |||
| f1bc500678 | |||
| a33d132289 | |||
| 40fb2ab22e | |||
| 77af4e0dc7 | |||
| 0403710e8c | |||
| 92c84e9dab |
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(npm install *)",
|
||||
"Bash(npx vite *)",
|
||||
"Bash(npx tailwindcss *)",
|
||||
"Bash(timeout 10)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
# 产品营销网站设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
为广西职业院校提供教育信息化产品的营销推广网站。纯前端静态站点,部署到 EdgeOne,域名 `https://products.2009xc.com/`。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **构建工具**:Vite
|
||||
- **框架**:React 18 + React Router v6
|
||||
- **样式**:Tailwind CSS v3 + CSS 变量(主题色切换)
|
||||
- **部署**:静态文件,EdgeOne CDN
|
||||
|
||||
## 页面结构
|
||||
|
||||
### 路由设计
|
||||
|
||||
| 路由 | 页面 | 说明 |
|
||||
|------|------|------|
|
||||
| `/` | 首页 | Hero区 + 产品概览 + 信任背书 + 新闻动态 |
|
||||
| `/product/:slug` | 产品详情页 | 通用模板,根据slug加载产品数据 |
|
||||
| `/contact` | 联系我们/成为代理商 | 代理优势 + 申请表单 + 联系方式 |
|
||||
|
||||
### 目录结构
|
||||
|
||||
```
|
||||
website
|
||||
/
|
||||
├── public/ # 静态资源
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── Navbar.jsx # 顶部导航栏(固定、响应式汉堡菜单)
|
||||
│ │ ├── Footer.jsx # 页脚
|
||||
│ │ ├── HeroSection.jsx # 首页Hero大图区
|
||||
│ │ ├── ProductCard.jsx # 产品概览卡片
|
||||
│ │ ├── TrustSection.jsx # 信任背书区(Logo墙+评价+数据)
|
||||
│ │ ├── NewsSection.jsx # 新闻动态区
|
||||
│ │ ├── DemoSection.jsx # 演示体验模块(网址+二维码+账号密码)
|
||||
│ │ ├── ContactForm.jsx # 代理商申请表单
|
||||
│ │ └── ThemeProvider.jsx# 主题色上下文(CSS变量切换)
|
||||
│ ├── pages/
|
||||
│ │ ├── Home.jsx
|
||||
│ │ ├── ProductPage.jsx # 通用产品详情页模板
|
||||
│ │ └── Contact.jsx
|
||||
│ ├── data/
|
||||
│ │ └── products.js # 产品数据配置
|
||||
│ ├── App.jsx
|
||||
│ └── main.jsx
|
||||
├── index.html
|
||||
├── tailwind.config.js
|
||||
├── vite.config.js
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## 首页设计
|
||||
|
||||
### 1. 导航栏
|
||||
- 公司Logo(左)+ 产品菜单(下拉展示所有产品)+ "联系我们"按钮(右)
|
||||
- 滚动后固定顶部,添加阴影
|
||||
- 移动端折叠为汉堡菜单
|
||||
|
||||
### 2. Hero 大图区
|
||||
- 全屏渐变背景(深蓝→蓝紫渐变)
|
||||
- 公司标语:"智慧教育,赋能未来"(示例)
|
||||
- 副标题:一句话描述公司使命
|
||||
- CTA按钮:"了解我们的产品"
|
||||
|
||||
### 3. 产品概览区
|
||||
- 2×3 网格卡片布局
|
||||
- 每张卡片:SVG图标 + 产品名称 + 一句话简介 + "了解更多"按钮
|
||||
- hover效果:上浮+阴影增强
|
||||
|
||||
### 4. 信任背书区
|
||||
- 合作院校Logo墙(示例占位)
|
||||
- 关键数据统计:"服务100+所院校"、"覆盖50万+师生"(示例)
|
||||
- 客户评价轮播
|
||||
|
||||
### 5. 新闻动态区
|
||||
- 3-4条最新动态卡片(标题+摘要+日期)
|
||||
- 示例占位内容
|
||||
|
||||
### 6. 页脚
|
||||
- 公司信息 + 联系方式 + 版权 + 备案号
|
||||
|
||||
## 产品详情页设计
|
||||
|
||||
通过URL参数 `/product/:slug` 从 `products.js` 加载数据,所有产品共享同一模板。
|
||||
|
||||
### 页面结构(从上到下)
|
||||
|
||||
1. **产品头部** — 全宽渐变背景(产品主题色),产品名称 + Slogan + 产品截图/插画
|
||||
2. **核心价值** — 3-4个价值点(图标+标题+描述),营销化文案
|
||||
3. **功能亮点** — 左右交替布局,图文并茂,每个功能一个区块
|
||||
4. **应用场景** — 针对职业院校的实际使用场景
|
||||
5. **演示体验模块** — 演示网址(可点击)+ 二维码(SVG占位)+ 体验账号密码(卡片)
|
||||
6. **其他产品推荐** — "您可能还感兴趣"卡片
|
||||
7. **CTA** — "立即联系我们"按钮
|
||||
|
||||
## 主题色系统
|
||||
|
||||
通过 CSS 变量 + ThemeProvider 上下文实现每个产品页面的主题色切换。
|
||||
|
||||
| 产品 | slug | 主题色 | 色值 |
|
||||
|------|------|--------|------|
|
||||
| 智慧校园管理平台 | smart-campus | 蓝色 | #2563EB |
|
||||
| 实习实训管理平台 | internship | 绿色 | #059669 |
|
||||
| 教学资源管理平台 | teaching-resource | 紫色 | #7C3AED |
|
||||
| 考试测评系统 | exam-system | 橙色 | #EA580C |
|
||||
| 就业服务平台 | career-service | 青色 | #0891B2 |
|
||||
|
||||
导航栏和页脚使用公司统一配色(深色),不受产品主题色影响。
|
||||
|
||||
## 联系我们/成为代理商页面
|
||||
|
||||
1. **代理优势区** — 4-6个加盟优势卡片(政策支持、培训赋能、丰厚回报、品牌背书等)
|
||||
2. **代理流程** — 横向步骤条:咨询 → 签约 → 培训 → 开业
|
||||
3. **在线申请表单** — 姓名、公司名称、联系电话、邮箱、所在地区、代理意向产品(下拉)、备注
|
||||
4. **联系方式区** — 电话、邮箱、地址、微信公众号二维码
|
||||
|
||||
表单仅做前端验证,展示提交成功提示(无后端处理)。
|
||||
|
||||
## 响应式断点
|
||||
|
||||
- **桌面端** ≥1024px:完整布局,双栏图文交替
|
||||
- **平板端** 768-1023px:间距调整,卡片2列
|
||||
- **移动端** <768px:单栏,汉堡菜单
|
||||
|
||||
## 设计风格
|
||||
|
||||
- 科技感/现代风,参考阿里云/腾讯云产品页风格
|
||||
- 大色块渐变、圆角卡片、适当的阴影和动效
|
||||
- 中文排版,适合中国用户习惯
|
||||
- SVG图标和装饰元素增加美观
|
||||
- 文案以营销宣传为主,不深入技术细节
|
||||
|
||||
## 产品数据结构
|
||||
|
||||
```js
|
||||
// src/data/products.js
|
||||
{
|
||||
slug: 'smart-campus',
|
||||
name: '校企益邦',
|
||||
slogan: '数字化管理,让校园更智慧',
|
||||
themeColor: '#2563EB',
|
||||
icon: '...', // SVG图标组件名
|
||||
brief: '...', // 一句话简介(首页卡片用)
|
||||
values: [...], // 核心价值点
|
||||
features: [...], // 功能亮点
|
||||
scenarios: [...], // 应用场景
|
||||
demo: {
|
||||
url: '...',
|
||||
qrCode: '...', // 二维码图片路径
|
||||
account: '...',
|
||||
password: '...'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 部署
|
||||
|
||||
- `vite build` 输出到 `website/dist/`
|
||||
- 上传到 EdgeOne,绑定域名 `products.2009xc.com`
|
||||
- Vite 配置 `base: '/'`
|
||||
@@ -14,6 +14,8 @@ dist-ssr
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
.claude/*
|
||||
docs/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
|
||||
@@ -4,11 +4,137 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=ZCOOL+QingKe+HuangYou&family=ZCOOL+XiaoWei&family=Long+Cang&family=Ma+Shan+Zheng&family=Zhi+Mang+Xing&family=Noto+Serif+SC:wght@600;700;900&display=swap" rel="stylesheet">
|
||||
<title>广西讯驰 - 智慧教育产品</title>
|
||||
</head>
|
||||
|
||||
<!-- ===== GEO: 语义化 meta 标签 ===== -->
|
||||
<meta name="description" content="广西讯驰是专注智慧教育领域的科技企业,为职业院校和高校提供实习就业管理、科研管理、智慧党建、实训管理平台等数字化解决方案,已服务150+所院校、覆盖5万+学生。" />
|
||||
<meta name="keywords" content="智慧教育,实习管理平台,科研管理系统,智慧党建,实训管理平台,广西讯驰,职业院校信息化" />
|
||||
<meta name="baidu-site-verification" content="codeva-N8Wnw7Njp2" />
|
||||
<title>广西讯驰 - 智慧教育数字化解决方案 | 校企益邦 · 科研管理 · 智慧党建 · 实训管理平台</title>
|
||||
|
||||
<!-- ===== GEO: Schema.org JSON-LD 结构化数据——AI 直接解析企业信息 ===== -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"name": "广西讯驰",
|
||||
"description": "专注智慧教育领域的科技企业,为职业院校和高校提供数字化解决方案",
|
||||
"url": "https://products.2009xc.com/",
|
||||
"logo": "https://products.2009xc.com/favicon.ico",
|
||||
"foundingDate": "2010",
|
||||
"areaServed": "中国",
|
||||
"knowsAbout": ["校企益邦", "科研管理系统", "智慧党建", "实训管理平台"],
|
||||
"contactPoint": {
|
||||
"@type": "ContactPoint",
|
||||
"telephone": "+86-771-3864294",
|
||||
"contactType": "customer service"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- FAQPage 结构化数据——AI 偏好的问答格式 -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "广西讯驰提供哪些智慧教育解决方案?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "核心产品包括校企益邦(实习就业管理平台)、科研管理系统、智慧党建平台、实训管理平台实训系统,覆盖实习管理、科研管理、党建数字化、商科实训四大领域。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "广西讯驰服务了多少院校?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "已服务超过150所职业院校和高校,覆盖5万+学生,客户主要分布在广西及周边省份。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "校企益邦实习管理平台有哪些功能?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "校企益邦涵盖实习岗位发布与匹配、学生实习过程跟踪、实习报告与评价、校企双导师协同管理、数据统计分析等全流程功能。"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- React 挂载点 -->
|
||||
<div id="root"></div>
|
||||
|
||||
<!-- ===== GEO: noscript 内容——AI 爬虫不执行 JS,从这里读取 ===== -->
|
||||
<noscript>
|
||||
<header>
|
||||
<h1>广西讯驰</h1>
|
||||
<p><strong>专注智慧教育领域的科技企业</strong></p>
|
||||
<p>成立于2010年,总部位于广西南宁,为职业院校和高校提供数字化解决方案。</p>
|
||||
<ul>
|
||||
<li>已服务 <strong>150+</strong> 所院校</li>
|
||||
<li>覆盖 <strong>5万+</strong> 学生</li>
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<h2>核心产品和服务</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<h3>校企益邦(实习就业管理平台)</h3>
|
||||
<p>面向职业院校实习就业管理的专业化平台,覆盖实习计划制定、过程跟踪、数据采集、鉴定评价全流程,已服务广西多所职业院校,帮助学校轻松应对教育厅数据上报要求。</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>科研管理系统</h3>
|
||||
<p>面向高校及科研院所的全生命周期科研业务管理平台。覆盖项目申报、评审立项、经费管控、成果登记到数据统计的全流程数字化,已帮助多所高校实现科研管理从纸质流转到"一网通办"的跨越。</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>智慧党建平台</h3>
|
||||
<p>面向高校及职业院校各级党组织的智慧党建管理系统。以"党业融合、指标驱动、全程留痕"为核心理念,将三会一课、党员活动、工作记录等日常工作自动关联考核指标,实现年终考核"零重复填报"。</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>实训管理平台</h3>
|
||||
<p>专为职业院校商科专业群打造的实训项目管理系统。以"项目—模块—任务"三级结构为骨架,以"咖豆积分+技能画像"为引擎,将抽象的五级进阶培养模式变成可量化、可追踪、可激励的线上实战平台。</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>常见问题</h2>
|
||||
|
||||
<h3>校企益邦实习管理平台和其他平台有什么不同?</h3>
|
||||
<p>校企益邦专为职业院校场景设计,支持集中实习和自主实习两种模式,提供企业资质审核、实习保险对接、工学交替打卡、实习成绩多维评价等功能,已适配广西、湖南等多省教育厅实习管理数据上报标准。</p>
|
||||
|
||||
<h3>系统支持私有化部署吗?</h3>
|
||||
<p>支持。所有产品均提供SaaS云服务和私有化部署两种方案,满足院校对数据安全和合规性的不同要求。</p>
|
||||
|
||||
<h3>科研管理系统能否对接省级课题管理平台?</h3>
|
||||
<p>可以。科研管理系统已与广西教育厅、广西科技厅等省级课题管理平台实现数据对接,支持项目申报、中检、结题等环节的数据同步。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>资质与荣誉</h2>
|
||||
<ul>
|
||||
<li>国家高新技术企业</li>
|
||||
<li>通过ISO 9001质量管理体系认证</li>
|
||||
<li>多项软件著作权(实习管理、科研管理、智慧党建、商科实训等)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p><strong>广西讯驰信息科技有限公司</strong></p>
|
||||
<p>地址:广西南宁市 | 电话:0771-3864294</p>
|
||||
<p>官网:https://products.2009xc.com/</p>
|
||||
<p>页面更新时间:2026年6月10日</p>
|
||||
</footer>
|
||||
</noscript>
|
||||
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
@@ -0,0 +1,76 @@
|
||||
# 广西讯驰 - 智慧教育数字化解决方案
|
||||
|
||||
> 广西讯驰信息科技有限公司(讯驰科技 / XUNCHI TECH),成立于 2010 年,总部位于广西南宁,专注为职业院校和高校提供智慧教育数字化解决方案。国家高新技术企业,已服务 150+ 所院校、覆盖 5 万+ 学生。
|
||||
|
||||
## 核心页面
|
||||
|
||||
- [首页](https://products.2009xc.com/): 企业概览、核心数据、四大产品展示、资质荣誉
|
||||
- [产品详情](https://products.2009xc.com/product/smart-campus): 各产品详情页(痛点、功能、优势、FAQ),通过 /product/{slug} 动态路由访问
|
||||
- [合作咨询](https://products.2009xc.com/contact): 联系方式、代理合作权益、在线咨询表单
|
||||
|
||||
## 核心产品
|
||||
|
||||
### 校企益邦(实习就业管理平台)
|
||||
|
||||
- 详情页: https://products.2009xc.com/product/smart-campus
|
||||
- 面向职业院校实习就业管理的专业化平台,覆盖实习计划制定、过程跟踪、数据采集、鉴定评价全流程。已服务 20+ 所院校、50,000+ 学生、100 万+ 累计签到。
|
||||
- 核心功能:实习计划管理、GPS 打卡 + 电子围栏、问卷式日志、多维度评价、一键同步省级教育平台、微信小程序
|
||||
- 解决痛点:实习管理缺乏统一执行方案、教师数据采集负担重、学生参与度低
|
||||
|
||||
### 科研管理系统
|
||||
|
||||
- 详情页: https://products.2009xc.com/product/exam-system
|
||||
- 面向高校及科研院所的全生命周期科研业务管理平台,覆盖项目申报、评审立项、经费管控、成果登记到数据统计。已服务 10+ 高校、管理 3,000+ 项目、登记 8,000+ 成果。
|
||||
- 核心功能:在线申报审批、智能查重、经费管控、成果自动计分、关键节点提醒、一键年报导出
|
||||
- 解决痛点:纸质流程繁琐、人工审核工作量大、经费管理复杂、统计汇总困难
|
||||
|
||||
### 智慧党建平台
|
||||
|
||||
- 详情页: https://products.2009xc.com/product/teaching-resource
|
||||
- 面向高校各级党组织的智慧党建管理系统。以"党业融合、指标驱动、全程留痕"为核心理念,将三会一课、党员活动、工作记录自动关联考核指标。已覆盖 150+ 党支部、管理 5,000+ 党员。
|
||||
- 核心功能:三级考核指标体系、三会一课数字化、万能工作记录、实时进度看板、党员发展管理、党建数据中心
|
||||
- 解决痛点:党建与业务两张皮、年终突击补材料、会议组织与留痕困难、分级考核存在盲区
|
||||
|
||||
### 实训管理平台
|
||||
|
||||
- 详情页: https://products.2009xc.com/product/internship
|
||||
- 专为职业院校商科专业群打造的实训项目管理系统。以"项目—模块—任务"三级结构为骨架,以"咖豆积分 + 技能画像"为引擎,将五级进阶培养模式变成可量化、可追踪的线上实战平台。已积累 500+ 实训项目、覆盖 15+ 专业。
|
||||
- 核心功能:三级精细化管理、咖豆积分引擎、五级自动晋升、动态技能画像、人才培养驾驶舱、积分商城
|
||||
- 解决痛点:渐进式人才培养难以落地、实训项目数据分散、技能成长过程不可见
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 系统支持本地化/私有化部署吗?
|
||||
|
||||
支持。所有产品均提供 SaaS 云服务和私有化部署两种方案,满足院校对数据安全和合规性的不同要求。
|
||||
|
||||
### 可以对接学校现有的教务/人事系统吗?
|
||||
|
||||
可以。所有产品均提供标准 API 接口,支持与学校现有系统对接。
|
||||
|
||||
### 售后服务和技术支持是怎样的?
|
||||
|
||||
提供 7x24 小时技术支持,包括远程运维、定期巡检、系统升级、用户培训等。
|
||||
|
||||
### 数据安全如何保障?
|
||||
|
||||
通过国家信息安全等级保护三级认证,采用银行级数据加密、多活灾备、细粒度权限控制。
|
||||
|
||||
## 企业资质
|
||||
|
||||
- 国家高新技术企业
|
||||
- AAA 级信用企业
|
||||
- ISO 9001 质量管理体系认证
|
||||
- ISO 14001 环境管理体系认证
|
||||
- ISO 45001 职业健康安全管理体系认证
|
||||
- ISO 27001 信息安全管理体系认证
|
||||
- ISO 20000 信息技术服务管理体系认证
|
||||
- 40+ 项软件著作权
|
||||
- 16 年行业经验
|
||||
|
||||
## 联系方式
|
||||
|
||||
- 官网: https://products.2009xc.com/
|
||||
- 电话: 0771-3864294
|
||||
- 地址: 广西南宁市
|
||||
- ICP 备案: 桂ICP备10003405号-1
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
|
||||
<!-- 首页 -->
|
||||
<url>
|
||||
<loc>https://products.2009xc.com/</loc>
|
||||
<lastmod>2026-06-10</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
|
||||
<!-- 产品页 -->
|
||||
<url>
|
||||
<loc>https://products.2009xc.com/product/smart-campus</loc>
|
||||
<lastmod>2026-06-10</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://products.2009xc.com/product/exam-system</loc>
|
||||
<lastmod>2026-06-10</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://products.2009xc.com/product/teaching-resource</loc>
|
||||
<lastmod>2026-06-10</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://products.2009xc.com/product/internship</loc>
|
||||
<lastmod>2026-06-10</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
|
||||
<!-- 联系页 -->
|
||||
<url>
|
||||
<loc>https://products.2009xc.com/contact</loc>
|
||||
<lastmod>2026-06-10</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
</url>
|
||||
|
||||
</urlset>
|
||||
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 153 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 461 KiB |
|
After Width: | Height: | Size: 233 KiB |
|
After Width: | Height: | Size: 597 KiB |
|
After Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 210 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 790 KiB After Width: | Height: | Size: 484 KiB |
|
Before Width: | Height: | Size: 12 MiB After Width: | Height: | Size: 255 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 544 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 181 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 222 KiB |
@@ -0,0 +1,140 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { X } from 'lucide-react'
|
||||
|
||||
export default function Carousel({ images, interval = 4000, themeColor }) {
|
||||
const [current, setCurrent] = useState(0)
|
||||
const [prevSrc, setPrevSrc] = useState(null)
|
||||
const [isTransitioning, setIsTransitioning] = useState(false)
|
||||
const [preview, setPreview] = useState(null)
|
||||
const timerRef = useRef(null)
|
||||
const busyRef = useRef(false)
|
||||
|
||||
const goTo = useCallback((index) => {
|
||||
if (index === current || busyRef.current) return
|
||||
busyRef.current = true
|
||||
setPrevSrc(images[current]?.url)
|
||||
setCurrent(index)
|
||||
// rAF x2 to ensure the DOM has rendered the new image before starting transition
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
setIsTransitioning(true)
|
||||
})
|
||||
})
|
||||
// After transition completes
|
||||
setTimeout(() => {
|
||||
setIsTransitioning(false)
|
||||
setPrevSrc(null)
|
||||
busyRef.current = false
|
||||
}, 500)
|
||||
}, [current, images])
|
||||
|
||||
const next = useCallback(() => {
|
||||
goTo((current + 1) % images.length)
|
||||
}, [current, images.length, goTo])
|
||||
|
||||
useEffect(() => {
|
||||
if (preview !== null) return
|
||||
timerRef.current = setInterval(next, interval)
|
||||
return () => clearInterval(timerRef.current)
|
||||
}, [next, interval, preview])
|
||||
|
||||
const handleImageClick = (index) => {
|
||||
setPreview(index)
|
||||
}
|
||||
|
||||
const handleClosePreview = () => {
|
||||
setPreview(null)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div >
|
||||
{/* Center - monitor frame (static, no animation) */}
|
||||
<div
|
||||
className="relative z-30 cursor-pointer"
|
||||
style={{ '--monitor-theme': themeColor }}
|
||||
onClick={() => handleImageClick(current)}
|
||||
>
|
||||
{/* 显示器外框 */}
|
||||
<div className="monitor-frame">
|
||||
<div className="monitor-screen relative">
|
||||
{/* 旧图片 — 交叉淡出 */}
|
||||
{prevSrc && (
|
||||
<img
|
||||
src={prevSrc}
|
||||
alt=""
|
||||
className="absolute inset-0 w-full h-full object-contain transition-opacity duration-500"
|
||||
style={{ opacity: isTransitioning ? 0 : 1 }}
|
||||
/>
|
||||
)}
|
||||
{/* 新图片 — 交叉淡入 */}
|
||||
<img
|
||||
src={images[current]?.url}
|
||||
alt=""
|
||||
className="absolute inset-0 w-full h-full object-contain transition-opacity duration-500"
|
||||
style={{ opacity: prevSrc ? (isTransitioning ? 1 : 0) : 1 }}
|
||||
/>
|
||||
</div>
|
||||
{/* 底部下巴 */}
|
||||
<div className="monitor-chin">
|
||||
<span className="monitor-chin-label">{images[current]?.name || ''}</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* 支架 */}
|
||||
<div className="monitor-stand-neck" />
|
||||
<div className="monitor-stand-base" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dot indicators */}
|
||||
<div className="flex justify-center gap-2 mt-2">
|
||||
{images.map((_, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => i !== current && goTo(i)}
|
||||
className="rounded-full transition-all duration-500"
|
||||
style={{
|
||||
width: i === current ? '24px' : '8px',
|
||||
height: '8px',
|
||||
backgroundColor: i === current ? themeColor : '#d1d5db',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Image name — lines on both sides */}
|
||||
<div className="text-center mt-5">
|
||||
<div className="flex items-center justify-center gap-5 md:gap-7">
|
||||
<span className="flex-1 h-[3px] max-w-[80px] md:max-w-[140px] rounded-full" style={{ background: `linear-gradient(90deg, transparent, ${themeColor}30)` }} />
|
||||
<span className="text-lg md:text-2xl font-bold tracking-[0.08em]"
|
||||
style={{ color: `${themeColor}aa` }}
|
||||
>
|
||||
{images[current]?.name || ''}
|
||||
</span>
|
||||
<span className="flex-1 h-[3px] max-w-[80px] md:max-w-[140px] rounded-full" style={{ background: `linear-gradient(90deg, ${themeColor}30, transparent)` }} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Preview Modal */}
|
||||
{preview !== null && (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4"
|
||||
onClick={handleClosePreview}
|
||||
>
|
||||
<button
|
||||
className="absolute top-6 right-6 z-10 w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center text-white transition-colors"
|
||||
onClick={handleClosePreview}
|
||||
>
|
||||
<X className="w-6 h-6" />
|
||||
</button>
|
||||
<img
|
||||
src={images[preview].url}
|
||||
alt=""
|
||||
className="max-w-full max-h-[85vh] object-contain rounded-2xl"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
import React from 'react'
|
||||
import ScrollReveal from './ScrollReveal'
|
||||
import { Award, Leaf, Shield, Lock, Wrench } from 'lucide-react'
|
||||
|
||||
/* ─── 证书数据 — 统一蓝色 ─── */
|
||||
const certificates = [
|
||||
{
|
||||
id: 'iso9001',
|
||||
icon: Award,
|
||||
code: 'ISO 9001',
|
||||
name: '质量管理体系认证',
|
||||
|
||||
date: '2024年3月',
|
||||
color: '#004ec4',
|
||||
sealColor: '#004ec4',
|
||||
},
|
||||
{
|
||||
id: 'iso14001',
|
||||
icon: Leaf,
|
||||
code: 'ISO 14001',
|
||||
name: '环境管理体系认证',
|
||||
|
||||
date: '2024年3月',
|
||||
color: '#004ec4',
|
||||
sealColor: '#004ec4',
|
||||
},
|
||||
{
|
||||
id: 'iso45001',
|
||||
icon: Shield,
|
||||
code: 'ISO 45001',
|
||||
name: '职业健康安全管理体系认证',
|
||||
|
||||
date: '2024年3月',
|
||||
color: '#004ec4',
|
||||
sealColor: '#004ec4',
|
||||
},
|
||||
{
|
||||
id: 'iso27001',
|
||||
icon: Lock,
|
||||
code: 'ISO 27001',
|
||||
name: '信息安全管理体系认证',
|
||||
|
||||
date: '2024年3月',
|
||||
color: '#004ec4',
|
||||
sealColor: '#004ec4',
|
||||
},
|
||||
{
|
||||
id: 'iso20000',
|
||||
icon: Wrench,
|
||||
code: 'ISO 20000',
|
||||
name: '信息技术服务管理体系认证',
|
||||
|
||||
date: '2024年3月',
|
||||
color: '#004ec4',
|
||||
sealColor: '#004ec4',
|
||||
},
|
||||
]
|
||||
|
||||
export default function CertificateCard({ certificate, index, scale = 1 }) {
|
||||
const { icon: Icon, code, name, desc, color } = certificate
|
||||
|
||||
return (
|
||||
<ScrollReveal delay={index * 0.08}>
|
||||
<div className="group relative transition-all duration-500 w-[260px] h-[380px] sm:w-[300px] sm:h-[440px] md:w-[360px] md:h-[500px]"
|
||||
style={{ transform: `scale(${scale})` }}
|
||||
>
|
||||
{/* ── 外阴影 ── */}
|
||||
<div className="absolute inset-0 rounded-sm translate-y-1.5 translate-x-1 opacity-25 group-hover:opacity-35 transition-opacity duration-500"
|
||||
style={{ background: `linear-gradient(135deg, ${color}40, ${color}15)` }}
|
||||
/>
|
||||
|
||||
{/* ── 证书主体 ── */}
|
||||
<div className="relative rounded-sm h-full flex flex-col"
|
||||
style={{ backgroundColor: '#faf7ed' }}
|
||||
>
|
||||
{/* 外层粗边框 */}
|
||||
<div className="absolute inset-0 border-[3px] rounded-sm"
|
||||
style={{ borderColor: `${color}50` }}
|
||||
/>
|
||||
|
||||
{/* 中层装饰线 */}
|
||||
<div className="absolute inset-[3px] border rounded-sm"
|
||||
style={{ borderColor: `${color}25` }}
|
||||
/>
|
||||
|
||||
{/* 内层双线框 */}
|
||||
<div className="absolute inset-[7px] border rounded-sm"
|
||||
style={{ borderColor: `${color}18` }}
|
||||
/>
|
||||
<div className="absolute inset-[9px] border rounded-sm"
|
||||
style={{ borderColor: `${color}0f` }}
|
||||
/>
|
||||
|
||||
{/* 四边中点装饰 */}
|
||||
<BorderCenterOrnament position="top" color={color} />
|
||||
<BorderCenterOrnament position="bottom" color={color} />
|
||||
<BorderCenterOrnament position="left" color={color} />
|
||||
<BorderCenterOrnament position="right" color={color} />
|
||||
|
||||
{/* 内容区 */}
|
||||
<div className="relative px-6 py-6 sm:px-8 sm:py-8 md:px-10 md:py-10 flex-1 flex flex-col items-center text-center justify-center">
|
||||
|
||||
{/* 认证图标 */}
|
||||
<div className="relative mb-3 sm:mb-4">
|
||||
<div className="w-12 h-12 sm:w-14 sm:h-14 md:w-16 md:h-16 rounded-full border-2 flex items-center justify-center group-hover:scale-110 transition-transform duration-500"
|
||||
style={{ borderColor: `${color}40`, backgroundColor: `${color}08` }}
|
||||
>
|
||||
<Icon className="w-6 h-6 sm:w-7 sm:h-7 md:w-8 md:h-8" style={{ color }} strokeWidth={1.5} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* 认证编号 */}
|
||||
<div className="text-base sm:text-lg md:text-xl font-black tracking-[0.15em] mb-1 sm:mb-2" style={{ color }}>
|
||||
{code}
|
||||
</div>
|
||||
|
||||
{/* 认证名称 */}
|
||||
<div className="text-sm sm:text-base font-bold text-[#1e293b] mb-3 sm:mb-4 leading-tight">
|
||||
{name}
|
||||
</div>
|
||||
|
||||
{/* 分隔线 — 带花纹 */}
|
||||
<div className="flex items-center gap-2 mb-3 sm:mb-4 w-full max-w-[120px] sm:max-w-[140px] md:max-w-[160px]">
|
||||
<div className="flex-1 h-px" style={{ background: `linear-gradient(90deg, transparent, ${color}50)` }} />
|
||||
<div className="flex gap-0.5">
|
||||
<div className="w-1 h-1 rounded-full" style={{ backgroundColor: `${color}60` }} />
|
||||
<div className="w-1 h-1 rounded-full" style={{ backgroundColor: `${color}40` }} />
|
||||
<div className="w-1 h-1 rounded-full" style={{ backgroundColor: `${color}60` }} />
|
||||
</div>
|
||||
<div className="flex-1 h-px" style={{ background: `linear-gradient(90deg, ${color}50, transparent)` }} />
|
||||
</div>
|
||||
|
||||
{/* 证明文字 */}
|
||||
<p className="text-xs sm:text-sm text-[#64748b] leading-relaxed mb-4 sm:mb-5 max-w-[240px] sm:max-w-[280px] md:max-w-[320px]">
|
||||
{desc}
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{/* 底部蓝色线条 */}
|
||||
<div className="relative h-1.5 bg-gradient-to-r from-blue-600 to-blue-800">
|
||||
{/* 折角 */}
|
||||
<div className="absolute left-0 top-0 w-1.5 h-1.5"
|
||||
style={{ background: 'linear-gradient(135deg, #faf7ed 50%, transparent 50%)' }}
|
||||
/>
|
||||
<div className="absolute right-0 top-0 w-1.5 h-1.5"
|
||||
style={{ background: 'linear-gradient(225deg, #faf7ed 50%, transparent 50%)' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* hover 顶部高光线 */}
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-500 rounded-t-sm"
|
||||
style={{ background: `linear-gradient(90deg, transparent, ${color}, transparent)` }}
|
||||
/>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
)
|
||||
}
|
||||
|
||||
/* ─── 边框中点装饰 ─── */
|
||||
function BorderCenterOrnament({ position, color }) {
|
||||
const posMap = {
|
||||
'top': 'top-[3px] left-1/2 -translate-x-1/2',
|
||||
'bottom': 'bottom-[3px] left-1/2 -translate-x-1/2',
|
||||
'left': 'left-[3px] top-1/2 -translate-y-1/2',
|
||||
'right': 'right-[3px] top-1/2 -translate-y-1/2',
|
||||
}
|
||||
const isHorizontal = position === 'top' || position === 'bottom'
|
||||
|
||||
return (
|
||||
<div className={`absolute ${posMap[position]} flex ${isHorizontal ? 'flex-row' : 'flex-col'} items-center gap-0.5`}
|
||||
style={{ opacity: 0.5 }}
|
||||
>
|
||||
<div className="w-2 h-2 rounded-full border" style={{ borderColor: `${color}40`, backgroundColor: `${color}10` }} />
|
||||
<div className="w-1 h-1 rounded-full" style={{ backgroundColor: `${color}50` }} />
|
||||
<div className="w-2 h-2 rounded-full border" style={{ borderColor: `${color}40`, backgroundColor: `${color}10` }} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { certificates }
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react'
|
||||
import CertificateCard, { certificates } from './CertificateCard'
|
||||
|
||||
export default function CertificateCarousel() {
|
||||
const [active, setActive] = useState(2) // 从中间开始 (ISO 45001)
|
||||
const [isMobile, setIsMobile] = useState(false)
|
||||
|
||||
// 检测是否为移动端
|
||||
useEffect(() => {
|
||||
const check = () => setIsMobile(window.innerWidth < 768)
|
||||
check()
|
||||
window.addEventListener('resize', check)
|
||||
return () => window.removeEventListener('resize', check)
|
||||
}, [])
|
||||
|
||||
const next = useCallback(() => {
|
||||
setActive(prev => (prev + 1) % certificates.length)
|
||||
}, [])
|
||||
|
||||
// 自动轮播
|
||||
useEffect(() => {
|
||||
const timer = setInterval(next, 3000)
|
||||
return () => clearInterval(timer)
|
||||
}, [next])
|
||||
|
||||
const goTo = (index) => setActive(index)
|
||||
|
||||
// 响应式参数
|
||||
const containerHeight = isMobile ? 'h-[360px]' : 'h-[600px]'
|
||||
const translateXBase = isMobile ? 140 : 260
|
||||
const scaleCenter = 1.0
|
||||
const scaleNear = isMobile ? 0.8 : 0.7
|
||||
const scaleFar = isMobile ? 0.5 : 0.4
|
||||
|
||||
return (
|
||||
<div className="relative max-w-4xl mx-auto">
|
||||
{/* 证书展示区 */}
|
||||
<div className={`relative ${containerHeight} flex items-center justify-center`}>
|
||||
{certificates.map((cert, i) => {
|
||||
let offset = i - active
|
||||
|
||||
// 循环环绕:取最短路径
|
||||
if (offset > 2) offset = offset - certificates.length
|
||||
if (offset < -2) offset = offset + certificates.length
|
||||
|
||||
const absOffset = Math.abs(offset)
|
||||
|
||||
let scale = scaleCenter
|
||||
if (absOffset === 1) scale = scaleNear
|
||||
if (absOffset >= 2) scale = scaleFar
|
||||
|
||||
let opacity = 1
|
||||
if (absOffset === 1) opacity = 0.6
|
||||
if (absOffset >= 2) opacity = 0
|
||||
|
||||
let translateX = offset * translateXBase
|
||||
|
||||
let zIndex = 10 - absOffset
|
||||
|
||||
return (
|
||||
<div
|
||||
key={cert.id}
|
||||
className="absolute transition-all duration-500 ease-in-out cursor-pointer"
|
||||
style={{
|
||||
transform: `translateX(${translateX}px) scale(${scale})`,
|
||||
opacity,
|
||||
zIndex,
|
||||
filter: absOffset >= 2 ? 'blur(2px)' : 'none',
|
||||
}}
|
||||
onClick={() => goTo(i)}
|
||||
>
|
||||
<CertificateCard certificate={cert} index={i} scale={isMobile ? 0.7 : 1} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 底部指示点 */}
|
||||
<div className="flex justify-center gap-2 mt-4">
|
||||
{certificates.map((cert, i) => (
|
||||
<button
|
||||
key={cert.id}
|
||||
onClick={() => goTo(i)}
|
||||
className={`w-2 h-2 rounded-full transition-all duration-300 ${
|
||||
i === active
|
||||
? 'bg-[#004ec4] w-6'
|
||||
: 'bg-[#004ec4]/30 hover:bg-[#004ec4]/50'
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { CheckCircle, X } from 'lucide-react';
|
||||
|
||||
const productOptions = [
|
||||
'校企益邦',
|
||||
'商咖五级进阶',
|
||||
'实训管理平台',
|
||||
'智慧党建平台',
|
||||
'科研管理系统',
|
||||
];
|
||||
@@ -37,7 +37,7 @@ export default function ContactForm() {
|
||||
setShowModal(false);
|
||||
}
|
||||
|
||||
const inputClass = 'w-full px-4 py-3 border border-gray-200 rounded-xl text-base focus:outline-none focus:ring-2 focus:ring-[#043b8f]/20 focus:border-[#043b8f]/40 transition-shadow placeholder-[#94a3b8] bg-white text-[#334155]';
|
||||
const inputClass = 'w-full px-4 py-3 border border-gray-200 rounded-xl text-base focus:outline-none focus:ring-2 focus:ring-[#004ec4]/30 focus:border-[#004ec4]/60 transition-shadow placeholder-[#94a3b8] bg-white text-[#334155]';
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -46,21 +46,21 @@ export default function ContactForm() {
|
||||
<div className="text-center mb-16">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">Inquiry</span>
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#004ec4]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#004ec4]">Inquiry</span>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
在线咨询
|
||||
</h2>
|
||||
<p className="text-[#475569] text-lg md:text-xl mt-5 max-w-xl leading-relaxed">填写表单,我们将在 1 个工作日内与您联系</p>
|
||||
<p className="text-[#475569] text-sm sm:text-base md:text-lg lg:text-xl mt-4 md:mt-5 max-w-xl leading-relaxed">填写表单,我们将在 1 个工作日内与您联系</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative bg-white rounded-2xl p-8 md:p-10 border border-gray-100 overflow-hidden max-w-3xl mx-auto">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-100"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-28 h-28 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-16 h-16 border border-[#043b8f]/[0.06] rounded-tr-3xl" />
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #004ec4, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-28 h-28 bg-[#004ec4]/[0.06] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-16 h-16 border border-[#004ec4]/[0.15] rounded-tr-3xl" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<form onSubmit={handleSubmit} className="space-y-8">
|
||||
@@ -91,7 +91,7 @@ export default function ContactForm() {
|
||||
关注产品 <span className="text-[#94a3b8] text-sm">(可选)</span>
|
||||
</label>
|
||||
<select id="product" name="product" value={form.product} onChange={handleChange}
|
||||
className="w-full px-4 py-3 border border-gray-200 rounded-xl text-base focus:outline-none focus:ring-2 focus:ring-[#043b8f]/20 focus:border-[#043b8f]/40 transition-shadow bg-white text-[#64748b]">
|
||||
className="w-full px-4 py-3 border border-gray-200 rounded-xl text-base focus:outline-none focus:ring-2 focus:ring-[#004ec4]/30 focus:border-[#004ec4]/60 transition-shadow bg-white text-[#64748b]">
|
||||
<option value="">请选择关注的产品</option>
|
||||
{productOptions.map((product) => (
|
||||
<option key={product} value={product}>{product}</option>
|
||||
@@ -107,8 +107,8 @@ export default function ContactForm() {
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-4 text-white font-bold rounded-xl text-base transition-all focus:outline-none focus:ring-2 focus:ring-[#043b8f]/20 focus:ring-offset-2 hover:shadow-lg hover:shadow-[#043b8f]/20"
|
||||
style={{ background: 'linear-gradient(135deg, #043b8f, #0659c7)' }}
|
||||
className="w-full py-4 text-white font-bold rounded-xl text-base transition-all focus:outline-none focus:ring-2 focus:ring-[#004ec4]/30 focus:ring-offset-2 hover:shadow-lg hover:shadow-[#004ec4]/30"
|
||||
style={{ background: 'linear-gradient(135deg, #004ec4, #0659c7)' }}
|
||||
>
|
||||
提交咨询
|
||||
</button>
|
||||
@@ -123,8 +123,8 @@ export default function ContactForm() {
|
||||
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={closeModal} />
|
||||
<div className="relative bg-white rounded-2xl p-8 md:p-10 max-w-md w-full shadow-2xl overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px]"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-20 h-20 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #004ec4, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-20 h-20 bg-[#004ec4]/[0.06] rounded-bl-full" />
|
||||
|
||||
<button onClick={closeModal}
|
||||
className="absolute top-4 right-4 w-8 h-8 rounded-full bg-gray-50 flex items-center justify-center hover:bg-gray-100 transition-colors">
|
||||
@@ -132,16 +132,16 @@ export default function ContactForm() {
|
||||
</button>
|
||||
|
||||
<div className="relative z-10 text-center">
|
||||
<div className="w-16 h-16 rounded-full bg-[#043b8f]/[0.06] border border-[#043b8f]/10 flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="w-8 h-8 text-[#043b8f]" />
|
||||
<div className="w-16 h-16 rounded-full bg-[#004ec4]/[0.12] border border-[#004ec4]/20 flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="w-8 h-8 text-[#004ec4]" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#0f172a] mb-3">提交成功</h3>
|
||||
<p className="text-[#64748b] text-base leading-relaxed mb-8">
|
||||
感谢您的咨询!我们将在 <span className="font-bold text-[#043b8f]">1 个工作日</span> 内与您联系
|
||||
感谢您的咨询!我们将在 <span className="font-bold text-[#004ec4]">1 个工作日</span> 内与您联系
|
||||
</p>
|
||||
<button onClick={closeModal}
|
||||
className="w-full py-3.5 text-white font-bold rounded-xl text-base transition-all hover:shadow-lg hover:shadow-[#043b8f]/20"
|
||||
style={{ background: 'linear-gradient(135deg, #043b8f, #0659c7)' }}>
|
||||
className="w-full py-3.5 text-white font-bold rounded-xl text-base transition-all hover:shadow-lg hover:shadow-[#004ec4]/30"
|
||||
style={{ background: 'linear-gradient(135deg, #004ec4, #0659c7)' }}>
|
||||
我知道了
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -20,16 +20,16 @@ export default function Footer() {
|
||||
<div className="md:px-8">
|
||||
<div className="flex items-center justify-center gap-2.5 mb-3 whitespace-nowrap">
|
||||
<img src="/favicon.ico" alt="讯驰" className="w-8 h-8" />
|
||||
<span className="text-lg font-bold text-white tracking-tight">讯驰科技</span>
|
||||
<span className="text-base sm:text-lg font-bold text-white tracking-tight">讯驰科技</span>
|
||||
</div>
|
||||
<p className="text-white/60 text-xs leading-loose mb-4">智慧校园解决方案提供商</p>
|
||||
<p className="text-white/60 text-xs sm:text-sm leading-loose mb-4">智慧校园解决方案提供商</p>
|
||||
<div className="flex items-start justify-center gap-2 mb-3">
|
||||
<MapPin className="w-3.5 h-3.5 text-white/50 mt-0.5 shrink-0" />
|
||||
<span className="text-white/70 text-xs leading-loose">南宁市总部路3号中国东盟科技企业孵化基地二期9号厂房二楼212房</span>
|
||||
<span className="text-white/70 text-xs sm:text-sm leading-loose">南宁市总部路3号中国东盟科技企业孵化基地二期9号厂房二楼212房</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Phone className="w-3.5 h-3.5 text-white/50 shrink-0" />
|
||||
<span className="text-white/70 text-xs">0771-3864294</span>
|
||||
<span className="text-white/70 text-xs sm:text-sm">0771-3864294</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -77,7 +77,7 @@ export default function Footer() {
|
||||
|
||||
{/* Row 2: Copyright */}
|
||||
<div className="pt-6 border-t border-white/15">
|
||||
<p className="text-white/50 text-xs text-center">© 2024 讯驰科技 版权所有 · 桂ICP备XXXXXXXX号</p>
|
||||
<p className="text-white/50 text-xs text-center">© 2026 讯驰科技 版权所有 ·备案号:桂ICP备10003405号-1</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -1,85 +1,86 @@
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import bag from '../../public/bag.mp4'
|
||||
// import { useEffect, useRef } from 'react';
|
||||
|
||||
function ParticleNetwork() {
|
||||
const canvasRef = useRef(null);
|
||||
// function ParticleNetwork() {
|
||||
// const canvasRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
let animId;
|
||||
let particles = [];
|
||||
const COUNT = 35;
|
||||
const CONNECT_DIST = 150;
|
||||
// useEffect(() => {
|
||||
// const canvas = canvasRef.current;
|
||||
// if (!canvas) return;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
// let animId;
|
||||
// let particles = [];
|
||||
// const COUNT = 35;
|
||||
// const CONNECT_DIST = 150;
|
||||
|
||||
function resize() {
|
||||
canvas.width = canvas.offsetWidth * window.devicePixelRatio;
|
||||
canvas.height = canvas.offsetHeight * window.devicePixelRatio;
|
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||
}
|
||||
// function resize() {
|
||||
// canvas.width = canvas.offsetWidth * window.devicePixelRatio;
|
||||
// canvas.height = canvas.offsetHeight * window.devicePixelRatio;
|
||||
// ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||
// }
|
||||
|
||||
function init() {
|
||||
resize();
|
||||
particles = [];
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
particles.push({
|
||||
x: Math.random() * canvas.offsetWidth,
|
||||
y: Math.random() * canvas.offsetHeight,
|
||||
vx: (Math.random() - 0.5) * 0.15,
|
||||
vy: (Math.random() - 0.5) * 0.15,
|
||||
r: Math.random() * 1 + 0.3,
|
||||
color: Math.random() > 0.8 ? '#f08519' : '#004ec4',
|
||||
});
|
||||
}
|
||||
}
|
||||
// function init() {
|
||||
// resize();
|
||||
// particles = [];
|
||||
// for (let i = 0; i < COUNT; i++) {
|
||||
// particles.push({
|
||||
// x: Math.random() * canvas.offsetWidth,
|
||||
// y: Math.random() * canvas.offsetHeight,
|
||||
// vx: (Math.random() - 0.5) * 0.15,
|
||||
// vy: (Math.random() - 0.5) * 0.15,
|
||||
// r: Math.random() * 1 + 0.3,
|
||||
// color: Math.random() > 0.8 ? '#f08519' : '#004ec4',
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
function draw() {
|
||||
const w = canvas.offsetWidth;
|
||||
const h = canvas.offsetHeight;
|
||||
ctx.clearRect(0, 0, w, h);
|
||||
// function draw() {
|
||||
// const w = canvas.offsetWidth;
|
||||
// const h = canvas.offsetHeight;
|
||||
// ctx.clearRect(0, 0, w, h);
|
||||
|
||||
for (let i = 0; i < particles.length; i++) {
|
||||
const p = particles[i];
|
||||
p.x += p.vx;
|
||||
p.y += p.vy;
|
||||
if (p.x < 0 || p.x > w) p.vx *= -1;
|
||||
if (p.y < 0 || p.y > h) p.vy *= -1;
|
||||
// for (let i = 0; i < particles.length; i++) {
|
||||
// const p = particles[i];
|
||||
// p.x += p.vx;
|
||||
// p.y += p.vy;
|
||||
// if (p.x < 0 || p.x > w) p.vx *= -1;
|
||||
// if (p.y < 0 || p.y > h) p.vy *= -1;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
|
||||
ctx.fillStyle = p.color;
|
||||
ctx.globalAlpha = 0.15;
|
||||
ctx.fill();
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
|
||||
// ctx.fillStyle = p.color;
|
||||
// ctx.globalAlpha = 0.15;
|
||||
// ctx.fill();
|
||||
|
||||
for (let j = i + 1; j < particles.length; j++) {
|
||||
const p2 = particles[j];
|
||||
const dx = p.x - p2.x;
|
||||
const dy = p.y - p2.y;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
if (dist < CONNECT_DIST) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(p.x, p.y);
|
||||
ctx.lineTo(p2.x, p2.y);
|
||||
ctx.strokeStyle = '#004ec4';
|
||||
ctx.globalAlpha = 0.03 * (1 - dist / CONNECT_DIST);
|
||||
ctx.lineWidth = 0.5;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.globalAlpha = 1;
|
||||
animId = requestAnimationFrame(draw);
|
||||
}
|
||||
// for (let j = i + 1; j < particles.length; j++) {
|
||||
// const p2 = particles[j];
|
||||
// const dx = p.x - p2.x;
|
||||
// const dy = p.y - p2.y;
|
||||
// const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
// if (dist < CONNECT_DIST) {
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(p.x, p.y);
|
||||
// ctx.lineTo(p2.x, p2.y);
|
||||
// ctx.strokeStyle = '#004ec4';
|
||||
// ctx.globalAlpha = 0.03 * (1 - dist / CONNECT_DIST);
|
||||
// ctx.lineWidth = 0.5;
|
||||
// ctx.stroke();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ctx.globalAlpha = 1;
|
||||
// animId = requestAnimationFrame(draw);
|
||||
// }
|
||||
|
||||
init();
|
||||
draw();
|
||||
window.addEventListener('resize', () => { resize(); });
|
||||
return () => cancelAnimationFrame(animId);
|
||||
}, []);
|
||||
// init();
|
||||
// draw();
|
||||
// window.addEventListener('resize', () => { resize(); });
|
||||
// return () => cancelAnimationFrame(animId);
|
||||
// }, []);
|
||||
|
||||
return <canvas ref={canvasRef} className="absolute inset-0 w-full h-full z-[1]" />;
|
||||
}
|
||||
// return <canvas ref={canvasRef} className="absolute inset-0 w-full h-full z-[1] border-amber-500 " />;
|
||||
// }
|
||||
|
||||
export default function HeroSection() {
|
||||
return (
|
||||
@@ -93,7 +94,7 @@ export default function HeroSection() {
|
||||
playsInline
|
||||
className="absolute inset-0 w-full h-full object-cover z-0 scale-105"
|
||||
>
|
||||
<source src="/src/assets/images/bag.mp4" type="video/mp4" />
|
||||
<source src={bag} type="video/mp4" />
|
||||
</video>
|
||||
|
||||
{/* Cinematic overlay */}
|
||||
@@ -108,7 +109,7 @@ export default function HeroSection() {
|
||||
style={{ animation: 'pulse-slow 12s ease-in-out 3s infinite' }} />
|
||||
</div>
|
||||
|
||||
<ParticleNetwork />
|
||||
|
||||
|
||||
{/* Top & bottom edge lines */}
|
||||
<div className="absolute top-0 left-0 right-0 z-10 h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent" />
|
||||
@@ -151,7 +152,7 @@ export default function HeroSection() {
|
||||
}
|
||||
|
||||
.hero-main-title {
|
||||
font-family: "ZCOOL XiaoWei", "STSong", "SimSun", serif;
|
||||
font-family: "STSong", "SimSun", "NSimSun", serif;
|
||||
letter-spacing: 0.6em;
|
||||
color: white;
|
||||
text-shadow: 0 4px 60px rgba(0, 162, 234, 0.3),
|
||||
@@ -159,7 +160,7 @@ export default function HeroSection() {
|
||||
}
|
||||
|
||||
.hero-sec-title {
|
||||
font-family: "Ma Shan Zheng", "STXingkai", cursive;
|
||||
font-family: "STKaiti", "KaiTi", "DFKai-SB", cursive;
|
||||
letter-spacing: 0.5em;
|
||||
color: white;
|
||||
text-shadow: 0 2px 40px rgba(0, 162, 234, 0.25),
|
||||
@@ -167,7 +168,7 @@ export default function HeroSection() {
|
||||
}
|
||||
|
||||
.hero-desc {
|
||||
font-family: "Ma Shan Zheng", "STXingkai", cursive;
|
||||
font-family: "KaiTi", "STKaiti", "DFKai-SB", cursive;
|
||||
letter-spacing: 0.3em;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
text-shadow: 0 2px 40px rgba(0, 162, 234, 0.25),
|
||||
@@ -198,23 +199,23 @@ export default function HeroSection() {
|
||||
{/* Heading */}
|
||||
<h1 className="text-center"
|
||||
style={{ animation: 'fadeInUp 1.4s cubic-bezier(0.16, 1, 0.3, 1) 0.4s both' }}>
|
||||
<span className="block text-5xl md:text-8xl lg:text-[110px] font-black hero-main-title">
|
||||
<span className="block text-5xl md:text-8xl lg:text-[120px] font-black hero-main-title">
|
||||
智慧教育
|
||||
</span>
|
||||
<span className="block mt-3 text-3xl md:text-[42px] lg:text-[48px] font-extralight hero-sec-title">
|
||||
<span className="block mt-6 md:mt-15 text-3xl md:text-[42px] lg:text-[108px] font-extralight hero-sec-title">
|
||||
赋能未来
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="flex items-center justify-center mt-2 mb-2"
|
||||
<div className="flex items-center justify-center mt-6 mb-6"
|
||||
style={{ animation: 'fadeIn 1s ease-out 1s both' }}>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Subtitle */}
|
||||
<div style={{ animation: 'fadeInUp 1s cubic-bezier(0.16, 1, 0.3, 1) 1.1s both' }}>
|
||||
<p className="text-lg md:text-xl max-w-xs mx-auto leading-[2] hero-desc">
|
||||
<p className="text-lg lg:text-[38px] md:text-xl mx-auto leading-[2] hero-desc whitespace-nowrap">
|
||||
让校园管理更简单、更智能
|
||||
</p>
|
||||
</div>
|
||||
@@ -230,20 +231,7 @@ export default function HeroSection() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-10 left-1/2 -translate-x-1/2 z-10"
|
||||
style={{ animation: 'fadeIn 1s ease-out 1.8s both' }}>
|
||||
<a href="#data" className="flex flex-col items-center gap-3 group">
|
||||
<span className="text-[9px] font-extralight text-white/15 group-hover:text-white/30 transition-colors duration-700"
|
||||
style={{ letterSpacing: '0.6em' }}>
|
||||
SCROLL
|
||||
</span>
|
||||
<div className="w-px h-10 bg-white/[0.06] relative overflow-hidden rounded-full">
|
||||
<div className="absolute w-full h-4 bg-gradient-to-b from-[#004ec4]/60 to-transparent rounded-full"
|
||||
style={{ animation: 'scrollFlow 2.5s ease-in-out infinite' }} />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { Menu, X, Phone } from 'lucide-react';
|
||||
import { products } from '../data/products';
|
||||
@@ -8,7 +8,15 @@ export default function Navbar() {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
const location = useLocation();
|
||||
|
||||
|
||||
// 根据当前路由获取产品主题色
|
||||
const themeColor = useMemo(() => {
|
||||
const match = location.pathname.match(/^\/product\/(.+)$/);
|
||||
if (match) {
|
||||
const product = products.find(p => p.slug === match[1]);
|
||||
return product ? product.themeColor : null;
|
||||
}
|
||||
return null;
|
||||
}, [location.pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => setScrolled(window.scrollY > window.innerHeight * 0.7);
|
||||
@@ -44,9 +52,9 @@ export default function Navbar() {
|
||||
left: 10%;
|
||||
right: 10%;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, transparent, #3b82f6, transparent);
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 12px rgba(59, 130, 246, 0.5), 0 0 24px rgba(59, 130, 246, 0.2);
|
||||
box-shadow: 0 0 12px rgba(255,255,255,0.5), 0 0 24px rgba(255,255,255,0.2);
|
||||
}
|
||||
.nav-item {
|
||||
position: relative;
|
||||
@@ -67,8 +75,8 @@ export default function Navbar() {
|
||||
}
|
||||
`}</style>
|
||||
<nav
|
||||
className={`sticky top-0 z-50 transition-all duration-500 backdrop-blur-xl ${scrolled ? 'bg-[#0f172a]/95 shadow-[0_4px_30px_rgba(0,0,0,0.2)] border-b border-white/[0.06]' : 'bg-gradient-to-b from-black/40 to-transparent'}`}
|
||||
style={!scrolled ? undefined : undefined}
|
||||
className={`sticky top-0 z-50 transition-all duration-500 backdrop-blur-xl ${scrolled ? 'shadow-[0_4px_30px_rgba(0,0,0,0.2)] border-b border-white/[0.06]' : 'bg-gradient-to-b from-black/40 to-transparent'}`}
|
||||
style={scrolled ? { backgroundColor: themeColor ? `${themeColor}f0` : '#0f172af2' } : undefined}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center h-[80px] overflow-visible">
|
||||
@@ -78,7 +86,7 @@ export default function Navbar() {
|
||||
<Link to="/" className="flex items-center gap-3 group">
|
||||
<img src="/favicon.ico" alt="讯驰" className="w-[100px] h-auto" />
|
||||
<div className="flex flex-col leading-tight">
|
||||
<span className={`text-xl font-bold tracking-wide text-white transition-colors duration-500`}>讯驰科技</span>
|
||||
<span className={`text-3xl font-bold tracking-wide text-white transition-colors duration-500`}>讯驰科技</span>
|
||||
<span className={`text-[10px] tracking-[0.2em] uppercase font-medium text-white/80 transition-colors duration-500`}>XUNCHI TECH</span>
|
||||
</div>
|
||||
</Link>
|
||||
@@ -89,10 +97,10 @@ export default function Navbar() {
|
||||
<Link
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
className={`relative px-4 font-medium rounded-sm transition-all duration-300 nav-item ${
|
||||
className={`relative px-5 font-medium rounded-sm transition-all duration-300 nav-item ${
|
||||
location.pathname === item.to
|
||||
? 'nav-active-tab text-white font-semibold text-base'
|
||||
: 'text-white hover:text-white text-sm py-3'
|
||||
? 'nav-active-tab text-white font-semibold text-xl'
|
||||
: 'text-white hover:text-white text-lg py-3'
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
@@ -107,7 +115,7 @@ export default function Navbar() {
|
||||
<div className={`hidden lg:flex items-center shrink-0 transition-colors duration-500`}>
|
||||
<a
|
||||
href="tel:07713864294"
|
||||
className="flex items-center gap-1.5 text-sm font-medium text-white hover:text-white transition-all duration-300"
|
||||
className="flex items-center gap-1.5 text-lg font-medium text-white hover:text-white transition-all duration-300"
|
||||
>
|
||||
<Phone className="w-3.5 h-3.5" />
|
||||
0771-3864294
|
||||
@@ -131,12 +139,12 @@ export default function Navbar() {
|
||||
mobileOpen ? 'max-h-[800px]' : 'max-h-0'
|
||||
}`}
|
||||
>
|
||||
<div className="bg-[#0a1628]/95 backdrop-blur-2xl border-t border-white/[0.06] px-4 pb-6 pt-3 space-y-1">
|
||||
<div className="bg-[#0a1628]/95 backdrop-blur-2xl border-t border-white/[0.06] px-4 pb-6 pt-3 space-y-1" style={scrolled && themeColor ? { backgroundColor: `${themeColor}f0` } : undefined}>
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
className={`block px-4 py-3 rounded-xl text-sm font-medium transition-colors ${
|
||||
className={`block px-4 py-3 rounded-xl text-lg font-medium transition-colors ${
|
||||
location.pathname === item.to
|
||||
? 'text-white bg-white/[0.06]'
|
||||
: 'text-white/50 hover:bg-white/[0.04]'
|
||||
@@ -146,7 +154,7 @@ export default function Navbar() {
|
||||
</Link>
|
||||
))}
|
||||
<div className="pt-3 mt-2 border-t border-white/[0.06]">
|
||||
<a href="tel:07713864294" className="flex items-center gap-2 px-5 py-3.5 text-[#043b8f] text-base font-medium">
|
||||
<a href="tel:07713864294" className="flex items-center gap-2 px-5 py-3.5 text-[#f3f3f4] text-base font-medium">
|
||||
<Phone className="w-4 h-4" />
|
||||
0771-3864294
|
||||
</a>
|
||||
|
||||
@@ -5,11 +5,9 @@ const chartData = [
|
||||
{ value: 25, name: '校企益邦' },
|
||||
{ value: 25, name: '科研管理系统' },
|
||||
{ value: 25, name: '智慧党建平台' },
|
||||
{ value: 25, name: '商咖五级进阶' },
|
||||
{ value: 25, name: '实训管理平台' },
|
||||
];
|
||||
|
||||
const color = '#043b8f';
|
||||
|
||||
const rotationNeeded = [45, -45, -135, -225];
|
||||
|
||||
function normalizeAngle(a) {
|
||||
@@ -25,12 +23,23 @@ function shortestRotation(from, to) {
|
||||
return from + diff;
|
||||
}
|
||||
|
||||
export default function RosePieChart({ onSelect, activeIndex }) {
|
||||
/** 将 hex 颜色转为带透明度的 rgba */
|
||||
function hexToRgba(hex, alpha) {
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
return `rgba(${r},${g},${b},${alpha})`;
|
||||
}
|
||||
|
||||
export default function RosePieChart({ onSelect, activeIndex, colors }) {
|
||||
const containerRef = useRef(null);
|
||||
const chartRef = useRef(null);
|
||||
const rotationRef = useRef(0);
|
||||
const [rotation, setRotation] = useState(0);
|
||||
|
||||
// 默认回退颜色
|
||||
const safeColors = colors?.length === 4 ? colors : ['#60ce93', '#0c86cf', '#aa3130', '#8b50ee'];
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
@@ -47,7 +56,7 @@ export default function RosePieChart({ onSelect, activeIndex }) {
|
||||
},
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['20%', '68%'],
|
||||
radius: ['25%', '75%'],
|
||||
center: ['50%', '50%'],
|
||||
startAngle: 90,
|
||||
padAngle: 3,
|
||||
@@ -73,7 +82,7 @@ export default function RosePieChart({ onSelect, activeIndex }) {
|
||||
},
|
||||
data: chartData.map((d, i) => ({
|
||||
...d,
|
||||
itemStyle: { color, opacity: 1, borderRadius: 6, borderWidth: 0 },
|
||||
itemStyle: { color: safeColors[i], opacity: 1, borderRadius: 6, borderWidth: 0 },
|
||||
})),
|
||||
animationType: 'scale',
|
||||
animationEasing: 'elasticOut',
|
||||
@@ -106,9 +115,9 @@ export default function RosePieChart({ onSelect, activeIndex }) {
|
||||
series: [{
|
||||
data: chartData.map((d, i) => ({
|
||||
...d,
|
||||
label: { color: isActive && activeIndex === i ? '#fff' : '#043b8f' },
|
||||
label: { color: isActive && activeIndex === i ? '#fff' : safeColors[i] },
|
||||
itemStyle: {
|
||||
color: isActive && activeIndex !== i ? color + '30' : color,
|
||||
color: isActive && activeIndex !== i ? hexToRgba(safeColors[i], 0.2) : safeColors[i],
|
||||
opacity: 1,
|
||||
borderRadius: 6,
|
||||
borderColor: 'rgba(15,23,42,0.8)',
|
||||
@@ -140,7 +149,7 @@ export default function RosePieChart({ onSelect, activeIndex }) {
|
||||
transition: 'transform 1s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
}}
|
||||
>
|
||||
<div ref={containerRef} className="w-full h-[420px] md:h-[480px]" />
|
||||
<div ref={containerRef} className="w-full h-[600px] md:h-[720px]" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useLocation } from 'react-router-dom'
|
||||
export default function ScrollReveal({
|
||||
children,
|
||||
className = '',
|
||||
@@ -14,26 +14,51 @@ export default function ScrollReveal({
|
||||
}) {
|
||||
const ref = useRef(null);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { pathname } = useLocation()
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setVisible(false);
|
||||
}, 0);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [pathname]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el) return;
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting) {
|
||||
setVisible(true);
|
||||
if (once) observer.unobserve(el);
|
||||
} else if (!once) {
|
||||
setVisible(false);
|
||||
}
|
||||
},
|
||||
{ threshold, rootMargin: '0px 0px -60px 0px' }
|
||||
);
|
||||
let observer;
|
||||
let cancelled = false;
|
||||
|
||||
observer.observe(el);
|
||||
return () => observer.disconnect();
|
||||
}, [once, threshold]);
|
||||
const timer = setTimeout(() => {
|
||||
if (cancelled) return;
|
||||
|
||||
observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting) {
|
||||
setVisible(true);
|
||||
if (once) observer.unobserve(el);
|
||||
} else if (!once) {
|
||||
setVisible(false);
|
||||
}
|
||||
},
|
||||
{ threshold, rootMargin: '0px 0px -60px 0px' }
|
||||
);
|
||||
|
||||
observer.observe(el);
|
||||
}, 0);
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
clearTimeout(timer);
|
||||
if (observer) observer.disconnect();
|
||||
};
|
||||
}, [once, threshold, pathname]);
|
||||
|
||||
const transforms = {
|
||||
up: `translateY(${distance}px)`,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
/* ─── Animated counter ─── */
|
||||
export default function StatNumber({ target, suffix }) {
|
||||
const [count, setCount] = useState(0)
|
||||
const ref = useRef(null)
|
||||
const started = useRef(false)
|
||||
const { pathname } = useLocation()
|
||||
|
||||
useEffect(() => {
|
||||
started.current = false
|
||||
setTimeout(() => setCount(0), 0)
|
||||
}, [pathname])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current
|
||||
if (!el) return
|
||||
const obs = new IntersectionObserver(([e]) => {
|
||||
if (e.isIntersecting && !started.current) {
|
||||
started.current = true
|
||||
const dur = 2000
|
||||
const start = performance.now()
|
||||
const num = parseInt(target)
|
||||
function tick(now) {
|
||||
const p = Math.min((now - start) / dur, 1)
|
||||
setCount(Math.round((1 - Math.pow(1 - p, 3)) * num))
|
||||
if (p < 1) requestAnimationFrame(tick)
|
||||
}
|
||||
requestAnimationFrame(tick)
|
||||
obs.unobserve(el)
|
||||
}
|
||||
}, { threshold: 0.3 })
|
||||
obs.observe(el)
|
||||
return () => obs.disconnect()
|
||||
}, [target, pathname])
|
||||
|
||||
|
||||
|
||||
|
||||
return <span ref={ref}>{count}{suffix}</span>
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
|
||||
/**
|
||||
* 加载 SVG 文件并将指定颜色替换为主题色后内联渲染
|
||||
* @param {string} url - SVG 文件地址
|
||||
* @param {string} color - 替换的目标主题色 (hex)
|
||||
* @param {string} className - 外层容器样式
|
||||
*/
|
||||
export default function ThemedSvg({ url, color, className }) {
|
||||
const [content, setContent] = useState('');
|
||||
const ref = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
fetch(url)
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
if (cancelled) return;
|
||||
// 将 undraw 默认紫色 #6c63ff 替换为页面主题色
|
||||
const themed = text.replace(/#6c63ff/gi, color);
|
||||
setContent(themed);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setContent('');
|
||||
});
|
||||
return () => { cancelled = true; };
|
||||
}, [url, color]);
|
||||
|
||||
if (!content) {
|
||||
return <div className={className} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={className}
|
||||
dangerouslySetInnerHTML={{ __html: content }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
Building2, GraduationCap, BookOpen, ClipboardCheck
|
||||
Building2, GraduationCap, BookOpen, ClipboardCheck,
|
||||
} from 'lucide-react';
|
||||
|
||||
export const products = [
|
||||
@@ -7,31 +7,43 @@ export const products = [
|
||||
slug: 'smart-campus',
|
||||
name: '校企益邦',
|
||||
slogan: '实习过程全掌控,就业数据一目了然',
|
||||
themeColor: '#2563EB',
|
||||
themeColor: '#60ce93',
|
||||
heroImage: new URL('../assets/images/Carousel/xq.png', import.meta.url).href,
|
||||
themeFrom: '#1e40af',
|
||||
themeTo: '#3b82f6',
|
||||
screenshots: [
|
||||
{ url: new URL('../assets/images/xq/xq1.png', import.meta.url).href, name: '专业管理' },
|
||||
{ url: new URL('../assets/images/xq/xq2.png', import.meta.url).href, name: '数据大屏' },
|
||||
{ url: new URL('../assets/images/xq/xq3.png', import.meta.url).href, name: '辅导员工作台' },
|
||||
],
|
||||
themeFrom: '#047857',
|
||||
themeTo: '#34d399',
|
||||
icon: Building2,
|
||||
brief: '面向职业院校实习就业管理的专业化平台,覆盖实习计划制定、过程跟踪、数据采集、鉴定评价全流程,已服务广西多所职业院校,帮助学校轻松应对教育厅数据上报要求。',
|
||||
tags: ['实习计划管理', 'GPS签到+电子围栏', '问卷式日志', '多维鉴定评价'],
|
||||
stats: [
|
||||
{ num: '20+所', label: '覆盖学校' },
|
||||
{ num: '50,000+', label: '服务学生' },
|
||||
{ num: '100万+', label: '累计签到' },
|
||||
{ num: '20', suffix: '+所', label: '覆盖学校' },
|
||||
{ num: '50,000', suffix: '+', label: '服务学生' },
|
||||
{ num: '100', suffix: '万+', label: '累计签到' },
|
||||
],
|
||||
features: [
|
||||
{ emoji: '📋', title: '实习计划管理', desc: '按学期、专业、班级灵活制定实习计划,绑定不同实习规则,实现多批次差异化管理' },
|
||||
{ emoji: '📍', title: 'GPS签到+电子围栏', desc: '基于地理位置的真实考勤,自动判断签到有效性,未签到学生一键导出名单' },
|
||||
{ emoji: '📝', title: '问卷式日志', desc: '预设定向提问模板,引导学生深度反思,"流水账"变"成长档案"' },
|
||||
{ emoji: '📊', title: '多维鉴定评价', desc: '综合考勤、日志、教师评价、企业反馈,自动生成实习鉴定分数,客观公正' },
|
||||
{ emoji: '🔄', title: '一键同步教育厅平台', desc: '数据审核后直接同步至"广西职业院校学生实习管理平台",无缝对接省级管理要求' },
|
||||
{ emoji: '📱', title: '微信小程序加持', desc: '学生通过小程序签到、写日志、上传附件,无需下载额外App,使用门槛极低' },
|
||||
{ icon: 'CalendarCheck', title: '实习计划管理', desc: '按学期、专业、班级灵活制定实习计划,绑定不同实习规则,实现多批次差异化管理', image: new URL('../assets/Features/xq/xq-1.jpg', import.meta.url).href },
|
||||
{ icon: 'SearchCheck', title: 'GPS签到+电子围栏', desc: '基于地理位置的真实考勤,自动判断签到有效性,未签到学生一键导出名单', image: new URL('../assets/Features/xq/xq-2.png', import.meta.url).href },
|
||||
{ icon: 'ScrollText', title: '问卷式日志', desc: '预设定向提问模板,引导学生深度反思,"流水账"变"成长档案"', image: new URL('../assets/Features/xq/xq-3.png', import.meta.url).href, small: true },
|
||||
{ icon: 'FileDigit', title: '多维鉴定评价', desc: '综合考勤、日志、教师评价、企业反馈,自动生成实习鉴定分数,客观公正', image: new URL('../assets/Features/xq/xq-4.png', import.meta.url).href },
|
||||
{ icon: 'GitBranch', title: '一键同步教育厅平台', desc: '数据审核后直接同步至"广西职业院校学生实习管理平台",无缝对接省级管理要求', image: new URL('../assets/Features/xq/xq-5.png', import.meta.url).href },
|
||||
{ icon: 'Layers', title: '微信小程序加持', desc: '学生通过小程序签到、写日志、上传附件,无需下载额外App,使用门槛极低',
|
||||
image: new URL('../assets/Features/xq/xq-6.png', import.meta.url).href, small: true },
|
||||
],
|
||||
painPointsTitle: '校企益邦解决的核心问题',
|
||||
painPointsTitle: '校企益邦\n解决的核心问题',
|
||||
painPoints: [
|
||||
{ title: '没有统一的方案执行,学校难以管控学生的实习情况', desc: '平台提供丰富的实习规则定制,涵盖签到、汇报、评价、考核等要求。定制后的实习规则可作为实习要求模板应用于多个实习计划,管理不同批次的学生,省去重复配置众多实习要求的麻烦,体现模板化。' },
|
||||
{ title: '学生信息采集工作量大,授课教师苦不堪言', desc: '将学生实习信息采集工作分配给学生完成,指导老师只需对这些信息进行审核,减少老师在实习信息采集和整理环节的工作,保障信息准确性、规范性的同时,提高了信息收集效率。' },
|
||||
{ title: '学生配合的积极性较低,提交的数据不达标', desc: '实习日志采用"问卷式",有指向性地采集学生实习日志,让学生即使面对需要频繁提交的日志,也有汇报方向,减少"流水账式"汇报,提升汇报效果。' },
|
||||
{
|
||||
url: new URL('../assets/images/Carousel/zh-points-1.svg', import.meta.url).href,
|
||||
title: '没有统一的方案执行,学校难以管控学生的实习情况', desc: '平台提供丰富的实习规则定制,涵盖签到、汇报、评价、考核等要求。定制后的实习规则可作为实习要求模板应用于多个实习计划,管理不同批次的学生,省去重复配置众多实习要求的麻烦,体现模板化。', },
|
||||
{
|
||||
url: new URL('../assets/images/Carousel/Points-2.svg', import.meta.url).href,
|
||||
title: '学生信息采集工作量大,授课教师苦不堪言', desc: '将学生实习信息采集工作分配给学生完成,指导老师只需对这些信息进行审核,减少老师在实习信息采集和整理环节的工作,保障信息准确性、规范性的同时,提高了信息收集效率。', },
|
||||
{
|
||||
url: new URL('../assets/images/Carousel/Points-3.svg', import.meta.url).href,
|
||||
title: '学生配合的积极性较低,提交的数据不达标', desc: '实习日志采用"问卷式",有指向性地采集学生实习日志,让学生即使面对需要频繁提交的日志,也有汇报方向,减少"流水账式"汇报,提升汇报效果。', },
|
||||
],
|
||||
target: '职业院校教务处、实习管理科、各院系指导教师',
|
||||
faq: [
|
||||
@@ -45,33 +57,38 @@ export const products = [
|
||||
slug: 'exam-system',
|
||||
name: '科研管理系统',
|
||||
slogan: '让科研管理告别纸质时代',
|
||||
themeColor: '#EA580C',
|
||||
themeColor: '#0c86cf',
|
||||
heroImage: new URL('../assets/images/Carousel/ky.png', import.meta.url).href,
|
||||
themeFrom: '#c2410c',
|
||||
themeTo: '#f97316',
|
||||
screenshots: [
|
||||
{ url: new URL('../assets/images/ky/ky1.png', import.meta.url).href, name: '个人科研画像' },
|
||||
{ url: new URL('../assets/images/ky/ky2.jpeg', import.meta.url).href, name: '经办跟踪' },
|
||||
{ url: new URL('../assets/images/ky/ky3.jpeg', import.meta.url).href, name: '消息推送' },
|
||||
],
|
||||
themeFrom: '#075985',
|
||||
themeTo: '#38bdf8',
|
||||
icon: ClipboardCheck,
|
||||
brief: '面向高校及科研院所的全生命周期科研业务管理平台。覆盖项目申报、评审立项、经费管控、成果登记到数据统计的全流程数字化,已帮助多所高校实现科研管理从纸质流转到"一网通办"的跨越。',
|
||||
tags: ['在线申报审批', '智能查重防重复', '经费精细管控', '成果自动赋分'],
|
||||
stats: [
|
||||
{ num: '10+所', label: '服务高校' },
|
||||
{ num: '3,000+', label: '管理项目' },
|
||||
{ num: '8,000+', label: '登记成果' },
|
||||
{ num: '10', suffix: '+所', label: '服务高校' },
|
||||
{ num: '3000', suffix: '+', label: '管理项目' },
|
||||
{ num: '8000', suffix: '+', label: '登记成果' },
|
||||
],
|
||||
features: [
|
||||
{ emoji: '📝', title: '在线申报审批', desc: '项目申报、审核、立项全流程在线办理,智能校验引擎自动检查相似度和限项规则' },
|
||||
{ emoji: '🔍', title: '智能查重防重复', desc: '项目名称相似度超80%自动拦截,同一主持人月度限申报1次,杜绝重复申报' },
|
||||
{ emoji: '💰', title: '经费精细管控', desc: '纵向/横向分类管理,预算—报销实时关联,超预算自动预警,经费使用透明合规' },
|
||||
{ emoji: '🏆', title: '成果自动赋分', desc: '论文、专利、著作按级别自动量化评分,一次登记多处复用,告别重复填报' },
|
||||
{ emoji: '⏰', title: '关键节点预警', desc: '经费超期、结题到期、审批退回等场景自动推送提醒,确保每个环节不遗漏' },
|
||||
{ emoji: '📄', title: '年度报表一键导出', desc: '科研成果统计、项目经费汇总等年度报表自动生成,效率提升数十倍' },
|
||||
{ icon: 'FileStack', title: '在线申报审批', desc: '项目申报、审核、立项全流程在线办理,智能校验引擎自动检查相似度和限项规则', image: new URL('../assets/Features/ky/ky-1.png', import.meta.url).href },
|
||||
{ icon: 'SearchCheck', title: '智能查重防重复', desc: '项目名称相似度超80%自动拦截,同一主持人月度限申报1次,杜绝重复申报', image: new URL('../assets/Features/ky/ky-2.png', import.meta.url).href },
|
||||
{ icon: 'Banknote', title: '经费精细管控', desc: '纵向/横向分类管理,预算—报销实时关联,超预算自动预警,经费使用透明合规', image: new URL('../assets/Features/ky/ky-3.png', import.meta.url).href },
|
||||
{ icon: 'TrendingUp', title: '成果自动赋分', desc: '论文、专利、著作按级别自动量化评分,一次登记多处复用,告别重复填报', image: new URL('../assets/Features/ky/ky-4.png', import.meta.url).href },
|
||||
{ icon: 'Bell', title: '关键节点预警', desc: '经费超期、结题到期、审批退回等场景自动推送提醒,确保每个环节不遗漏', image: new URL('../assets/Features/ky/ky-5.png', import.meta.url).href },
|
||||
{ icon: 'FileDigit', title: '年度报表一键导出', desc: '科研成果统计、项目经费汇总等年度报表自动生成,效率提升数十倍', image: new URL('../assets/Features/ky/ky-6.png', import.meta.url).href },
|
||||
],
|
||||
painPointsTitle: '科研管理系统解决的核心问题',
|
||||
painPointsTitle: '科研管理系统\n解决的核心问题',
|
||||
painPoints: [
|
||||
{ title: '传统科研管理流程繁琐,纸质办公效率低下', desc: '全流程数字化,实现科研项目申报、审批、结题的全程在线办理,消除纸质办公,提升工作效率。' },
|
||||
{ title: '项目申报审核工作量大,人工审核成本高', desc: '智能校验引擎,内置项目查重(相似度检测)、限项检查、预算自动配套计算规则,大幅降低人工审核成本。' },
|
||||
{ title: '科研经费管理复杂,预算与报销脱节', desc: '经费精细化管控,支持纵向/横向经费分类管理,实时关联预算与报销进度,确保经费使用规范透明。' },
|
||||
{ title: '科研成果统计困难,年度报表制作耗时', desc: '成果分值量化,自动根据奖励办法对论文、专利、著作等成果进行赋分,支持一键导出年度统计报表。' },
|
||||
{ title: '项目进度监控不及时,关键节点容易遗漏', desc: '多维度预警,集成短信通知与站内提醒,涵盖预算超期、结题预警、流程回退等关键节点。' },
|
||||
{ url: new URL('../assets/images/Carousel/Points-1.svg', import.meta.url).href, title: '传统科研管理流程繁琐,纸质办公效率低下', desc: '全流程数字化,实现科研项目申报、审批、结题的全程在线办理,消除纸质办公,提升工作效率。'},
|
||||
{ url: new URL('../assets/images/Carousel/ky-Points-1.svg', import.meta.url).href, title: '项目申报审核工作量大,人工审核成本高', desc: '智能校验引擎,内置项目查重(相似度检测)、限项检查、预算自动配套计算规则,大幅降低人工审核成本。' },
|
||||
{ url: new URL('../assets/images/Carousel/ky-Points-3.svg', import.meta.url).href, title: '科研经费管理复杂,预算与报销脱节', desc: '经费精细化管控,支持纵向/横向经费分类管理,实时关联预算与报销进度,确保经费使用规范透明。' },
|
||||
{ url: new URL('../assets/images/Carousel/Points-4.svg', import.meta.url).href, title: '科研成果统计困难,年度报表制作耗时', desc: '成果分值量化,自动根据奖励办法对论文、专利、著作等成果进行赋分,支持一键导出年度统计报表。' },
|
||||
{ url: new URL('../assets/images/Carousel/Points-5.svg', import.meta.url).href, title: '项目进度监控不及时,关键节点容易遗漏', desc: '多维度预警,集成短信通知与站内提醒,涵盖预算超期、结题预警、流程回退等关键节点。' },
|
||||
],
|
||||
target: '高校科研处、财务处、各院系教师及科研项目负责人',
|
||||
faq: [
|
||||
@@ -85,40 +102,53 @@ export const products = [
|
||||
slug: 'teaching-resource',
|
||||
name: '智慧党建平台',
|
||||
slogan: '党建工作有痕,年终考核无忧',
|
||||
themeColor: '#7C3AED',
|
||||
themeColor: '#aa3130',
|
||||
heroImage: new URL('../assets/images/Carousel/zh.png', import.meta.url).href,
|
||||
themeFrom: '#6d28d9',
|
||||
themeTo: '#8b5cf6',
|
||||
heroSize: 'small',
|
||||
screenshots: [
|
||||
{ url: new URL('../assets/images/zh/zh1.png', import.meta.url).href, name: '消息推送' },
|
||||
{ url: new URL('../assets/images/zh/zh2.png', import.meta.url).href, name: '数据大屏' },
|
||||
{ url: new URL('../assets/images/zh/zh3.jpeg', import.meta.url).href, name: '发展党员管理' },
|
||||
],
|
||||
themeFrom: '#7f1d1d',
|
||||
themeTo: '#dc2626',
|
||||
icon: BookOpen,
|
||||
brief: '面向高校及职业院校各级党组织的智慧党建管理系统。以"党业融合、指标驱动、全程留痕"为核心理念,将三会一课、党员活动、工作记录等日常工作自动关联考核指标,实现年终考核"零重复填报"。',
|
||||
tags: ['三级考核指标', '三会一课数字化', '万能工作记录', '实时进度看板'],
|
||||
stats: [
|
||||
{ num: '150+', label: '服务支部' },
|
||||
{ num: '5,000+', label: '管理党员' },
|
||||
{ num: '200+', label: '考核指标' },
|
||||
{ num: '150', suffix: '+所', label: '服务支部' },
|
||||
{ num: '5000', suffix: '+', label: '管理党员' },
|
||||
{ num: '200', suffix: '+', label: '考核指标' },
|
||||
],
|
||||
features: [
|
||||
{ emoji: '📊', title: '三级考核指标', desc: '灵活构建校—院—支部三级指标树,分值自动汇总,考核部门与执行部门逐一对应' },
|
||||
{ emoji: '📋', title: '三会一课数字化', desc: '通知—签到—记录全流程闭环,二维码签到5分钟刷新,杜绝"代签""补签"' },
|
||||
{ emoji: '✍️', title: '万能工作记录', desc: '不受模块限制,任何业务工作均可灵活录入并关联考核指标,实现考核全覆盖' },
|
||||
{ emoji: '🔔', title: '实时进度看板', desc: '领导层穿透查看各项指标完成进度,哪项落后一目了然,变"年底算账"为"过程管控"' },
|
||||
{ emoji: '👥', title: '发展党员管理', desc: '内置入党全流程节点模型,支持自定义配置,关键节点到期自动提醒支部管理员' },
|
||||
{ emoji: '📡', title: '党建数据中心', desc: '全校党建数据可视化大屏——组织健康度、党员活跃度、重点工作督办一览无余' },
|
||||
{ icon: 'Pyramid', title: '三级考核指标', desc: '灵活构建校—院—支部三级指标树,分值自动汇总,考核部门与执行部门逐一对应', image: new URL('../assets/Features/zh/zh-1.png', import.meta.url).href },
|
||||
{ icon: 'CalendarCheck', title: '三会一课数字化', desc: '通知—签到—记录全流程闭环,二维码签到5分钟刷新,杜绝"代签""补签"', image: new URL('../assets/Features/zh/zh-2.png', import.meta.url).href },
|
||||
{ icon: 'ScrollText', title: '万能工作记录', desc: '不受模块限制,任何业务工作均可灵活录入并关联考核指标,实现考核全覆盖', image: new URL('../assets/Features/zh/zh-3.png', import.meta.url).href },
|
||||
{ icon: 'ChartBar', title: '实时进度看板', desc: '领导层穿透查看各项指标完成进度,哪项落后一目了然,变"年底算账"为"过程管控"', image: new URL('../assets/Features/zh/zh-4.png', import.meta.url).href },
|
||||
{ icon: 'Database', title: '发展党员管理', desc: '内置入党全流程节点模型,支持自定义配置,关键节点到期自动提醒支部管理员', image: new URL('../assets/Features/zh/zh-5.png', import.meta.url).href },
|
||||
{ icon: 'Activity', title: '党建数据中心', desc: '全校党建数据可视化大屏——组织健康度、党员活跃度、重点工作督办一览无余', image: new URL('../assets/Features/zh/zh-6.png', import.meta.url).href },
|
||||
],
|
||||
painPointsTitle: '智慧党建平台解决的核心问题',
|
||||
painPointsTitle: '智慧党建平台\n解决的核心问题',
|
||||
painPoints: [
|
||||
{ title: '党建工作与教学业务“两张皮”,考核指标繁杂多样,难以实现全口径统一管理', desc: '构建“专用模块+通用记录”的双重支撑体系。对于标准化党务,通过“三会一课”、“党员活动”等模块自动关联;对于教学科研等系统中无特定管理模块的考核任务,利用“工作记录”模块作为万能适配器进行灵活录入并关联指标。确保每一项考核指标(无论党务或业务)都有据可查,实现党建考核的100%全覆盖。' },
|
||||
{
|
||||
title: ' 年终考核“突击补材料”,重复填表耗时耗力,数据难追溯',
|
||||
desc: '推行“过程资产化”管理,日常工作(如会议、活动)录入即并关联考核指标,年终无需盘点,数据自动生成,拒绝重复劳动。'
|
||||
url: new URL('../assets/images/Carousel/zh-Points-1.svg', import.meta.url).href,
|
||||
title: '党建工作与教学业务”两张皮”,考核指标繁杂多样,难以实现全口径统一管理',
|
||||
desc: '构建”专用模块+通用记录”的双重支撑体系。对于标准化党务,通过”三会一课”、”党员活动”等模块自动关联;对于教学科研等系统中无特定管理模块的考核任务,利用”工作记录”模块作为万能适配器进行灵活录入并关联指标。确保每一项考核指标(无论党务或业务)都有据可查,实现党建考核的100%全覆盖。'},
|
||||
{
|
||||
url: new URL('../assets/images/Carousel/zh-Points-2.svg', import.meta.url).href,
|
||||
title: ' 年终考核”突击补材料”,重复填表耗时耗力,数据难追溯',
|
||||
desc: '推行”过程资产化”管理,日常工作(如会议、活动)录入即并关联考核指标,年终无需盘点,数据自动生成,拒绝重复劳动。',
|
||||
|
||||
},
|
||||
{ url: new URL('../assets/images/Carousel/Points-3.svg', import.meta.url).href, title: '”三会一课”组织难、签到难、记录难,合规性监管滞后',
|
||||
desc: '提供移动端全流程闭环,支持一键发布通知、现场扫码签到、会议纪要即时编辑上传,确保组织生活规范、留痕、可查。',
|
||||
|
||||
},
|
||||
{
|
||||
title: '“三会一课”组织难、签到难、记录难,合规性监管滞后',
|
||||
desc: '提供移动端全流程闭环,支持一键发布通知、现场扫码签到、会议纪要即时编辑上传,确保组织生活规范、留痕、可查。'
|
||||
},
|
||||
{
|
||||
title: '党建考核存在“层级衰减”与“管理盲区”,平时进度看不见,年底检查来不及',
|
||||
desc: '构建分层级可视化考核体系。系统打破科层壁垒,领导层通过“完成情况看板”直观监测各指标的实时进度一键穿透查看明细;执行层通过“指标明细”精准对应“自评”与“佐证材料”,明确“谁来做、谁来考、通过什么材料佐证”。让考核从“年底算总账”变为“全过程透明化管控”,确保压力无损传导至基层末梢。'
|
||||
url: new URL('../assets/images/Carousel/Points-4.svg', import.meta.url).href,
|
||||
title: '党建考核存在”层级衰减”与”管理盲区”,平时进度看不见,年底检查来不及',
|
||||
desc: '构建分层级可视化考核体系。系统打破科层壁垒,领导层通过”完成情况看板”直观监测各指标的实时进度一键穿透查看明细;执行层通过”指标明细”精准对应”自评”与”佐证材料”,明确”谁来做、谁来考、通过什么材料佐证”。让考核从”年底算总账”变为”全过程透明化管控”,确保压力无损传导至基层末梢。',
|
||||
|
||||
},
|
||||
],
|
||||
target: '高校党委组织部、各二级党委/党总支、基层党支部',
|
||||
@@ -131,38 +161,45 @@ export const products = [
|
||||
},
|
||||
{
|
||||
slug: 'internship',
|
||||
name: '商咖五级进阶',
|
||||
name: '实训管理平台',
|
||||
slogan: '五级渐进,让每一次成长都看得见',
|
||||
themeColor: '#059669',
|
||||
themeColor: '#8b50ee',
|
||||
heroImage: new URL('../assets/images/Carousel/sk.png', import.meta.url).href,
|
||||
themeFrom: '#047857',
|
||||
themeTo: '#10b981',
|
||||
screenshots: [
|
||||
{ url: new URL('../assets/images/sk/sk1.png', import.meta.url).href, name: '数据大屏' },
|
||||
{ url: new URL('../assets/images/sk/sk2.jpeg', import.meta.url).href, name: '角色管理' },
|
||||
{ url: new URL('../assets/images/sk/sk3.jpeg', import.meta.url).href, name: '消息推送' },
|
||||
],
|
||||
themeFrom: '#5b21b6',
|
||||
themeTo: '#a78bfa',
|
||||
icon: GraduationCap,
|
||||
brief: '专为职业院校商科专业群打造的实训项目管理系统。以"项目—模块—任务"三级结构为骨架,以"咖豆积分+技能画像"为引擎,将抽象的五级进阶培养模式变成可量化、可追踪、可激励的线上实战平台。',
|
||||
tags: ['三级精细管理', '咖豆积分引擎', '五级自动晋级', '动态技能画像'],
|
||||
stats: [
|
||||
{ num: '500+', label: '实训项目库' },
|
||||
{ num: '15+', label: '覆盖专业' },
|
||||
{ num: '200万+', label: '累计咖豆' },
|
||||
{ num: '500', suffix: '+', label: '实训项目库' },
|
||||
{ num: '15', suffix: '+', label: '覆盖专业' },
|
||||
{ num: '200', suffix: '万+', label: '累计咖豆' },
|
||||
],
|
||||
features: [
|
||||
{ emoji: '📦', title: '三级精细管理', desc: '项目→模块→任务三级结构,权重灵活分配,实训教学内容标准化、可复用' },
|
||||
{ emoji: '🫘', title: '咖豆积分引擎', desc: '成绩自动转换为虚拟积分,支持积分排行、兑换、晋级,让学习像游戏一样上瘾' },
|
||||
{ emoji: '⭐', title: '五级自动晋级', desc: '自定义等级名称、门槛积分和专属权益,达标自动晋升,成长路径一目了然' },
|
||||
{ emoji: '🎯', title: '动态技能画像', desc: '基于任务完成情况自动生成个人雷达图,技能点逐一点亮,优势短板清晰可见' },
|
||||
{ emoji: '📈', title: '人才培养驾驶舱', desc: '全校实训数据一屏呈现——项目热度、参与度、完成率、经费使用,决策有据可依' },
|
||||
{ emoji: '🎁', title: '积分商城', desc: '咖豆可兑换实物或虚拟礼品,构建"学、练、评、换"完整激励闭环' },
|
||||
{ icon: 'Layers', title: '三级精细管理', desc: '项目→模块→任务三级结构,权重灵活分配,实训教学内容标准化、可复用', image: new URL('../assets/Features/sk/sk-1.png', import.meta.url).href },
|
||||
{ icon: 'Database', title: '咖豆积分引擎', desc: '成绩自动转换为虚拟积分,支持积分排行、兑换、晋级,让学习像游戏一样上瘾', image: new URL('../assets/Features/sk/sk-2.png', import.meta.url).href },
|
||||
{ icon: 'TrendingUp', title: '五级自动晋级', desc: '自定义等级名称、门槛积分和专属权益,达标自动晋升,成长路径一目了然', small: true, image: new URL('../assets/Features/sk/sk-3.png', import.meta.url).href },
|
||||
{ icon: 'Activity', title: '动态技能画像', desc: '基于任务完成情况自动生成个人雷达图,技能点逐一点亮,优势短板清晰可见', small: true, image: new URL('../assets/Features/sk/sk-4.png', import.meta.url).href },
|
||||
{ icon: 'ChartBar', title: '人才培养驾驶舱', desc: '全校实训数据一屏呈现——项目热度、参与度、完成率、经费使用,决策有据可依', image: new URL('../assets/Features/sk/sk-5.png', import.meta.url).href },
|
||||
{ icon: 'Banknote', title: '积分商城', desc: '咖豆可兑换实物或虚拟礼品,构建"学、练、评、换"完整激励闭环', small: true, image: new URL('../assets/Features/sk/sk-6.png', import.meta.url).href },
|
||||
],
|
||||
painPoints: [
|
||||
{ title: '人才培养模式落地难,教学管理与“五级进阶”理念脱节。',
|
||||
desc: '系统内置“项目-模块-任务”三级结构与积分晋级规则,将抽象的“五级进阶”理念转化为可量化、可执行、可追踪的线上流程。学生通过完成任务获得积分,自动点亮技能点,实现逐级晋升,确保培养模式的精准落地。' },
|
||||
|
||||
{
|
||||
title: ' 实训项目数据散落,缺乏统一管理与深度分析',
|
||||
desc: '建立统一的校级实训项目库,实现项目创建、审批、排课、执行到归档的全生命周期管理。同时,建设可视化数据大屏,为管理层提供各学院项目数量、学生参与度、完成情况等全景决策数据。' },
|
||||
{
|
||||
title: '技能成长过程不可视,学生缺乏明确的学习目标和动力。',
|
||||
desc: '系统根据学生参与的实训任务、积分获取情况,自动生成动态的个人技能画像。学生可以直观看到自己已掌握的“技能点”以及距离下一等级的差距,明确优势与不足,并获得持续进阶的动力。' },
|
||||
|
||||
url: new URL('../assets/images/Carousel/sx-Points-2.svg', import.meta.url).href, title: '人才培养模式落地难,教学管理与”五级进阶”理念脱节。',
|
||||
desc: '系统内置”项目-模块-任务”三级结构与积分晋级规则,将抽象的”五级进阶”理念转化为可量化、可执行、可追踪的线上流程。学生通过完成任务获得积分,自动点亮技能点,实现逐级晋升,确保培养模式的精准落地。', },
|
||||
{ url: new URL('../assets/images/Carousel/Points-2.svg', import.meta.url).href,
|
||||
title: ' 实训项目数据散落,缺乏统一管理与深度分析',
|
||||
desc: '建立统一的校级实训项目库,实现项目创建、审批、排课、执行到归档的全生命周期管理。同时,建设可视化数据大屏,为管理层提供各学院项目数量、学生参与度、完成情况等全景决策数据。', },
|
||||
{ url: new URL('../assets/images/Carousel/Points-3.svg', import.meta.url).href,
|
||||
title: '技能成长过程不可视,学生缺乏明确的学习目标和动力。',
|
||||
desc: '系统根据学生参与的实训任务、积分获取情况,自动生成动态的个人技能画像。学生可以直观看到自己已掌握的”技能点”以及距离下一等级的差距,明确优势与不足,并获得持续进阶的动力。', },
|
||||
|
||||
],
|
||||
target: '商科专业群、实训中心、教务处',
|
||||
faq: [
|
||||
|
||||
@@ -55,7 +55,7 @@ body {
|
||||
|
||||
/* Product page hero art titles */
|
||||
.hero-product-title {
|
||||
font-family: "ZCOOL XiaoWei", "STSong", "SimSun", serif;
|
||||
font-family: "STSong", "SimSun", "NSimSun", serif;
|
||||
letter-spacing: 0.3em;
|
||||
color: white;
|
||||
text-shadow: 0 4px 60px rgba(0, 162, 234, 0.3),
|
||||
@@ -63,9 +63,115 @@ body {
|
||||
}
|
||||
|
||||
.hero-product-slogan {
|
||||
font-family: "Ma Shan Zheng", "STXingkai", cursive;
|
||||
font-family: "STKaiti", "KaiTi", "DFKai-SB", cursive;
|
||||
letter-spacing: 0.15em;
|
||||
color: white;
|
||||
text-shadow: 0 2px 40px rgba(0, 162, 234, 0.25),
|
||||
0 0 80px rgba(0, 162, 234, 0.15);
|
||||
}
|
||||
|
||||
/* ── 台式显示器外框 ── */
|
||||
.monitor-frame {
|
||||
position: relative;
|
||||
background: #1a1a2e;
|
||||
border-radius: 8px;
|
||||
padding: 6px 6px 3px 6px;
|
||||
box-shadow:
|
||||
0 0 0 1px #2a2a3e,
|
||||
0 2px 12px rgba(0, 0, 0, 0.3);
|
||||
max-width: 750px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.monitor-screen {
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.monitor-chin {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px 0 2px 0;
|
||||
}
|
||||
|
||||
.monitor-chin-label {
|
||||
font-size: 9px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
letter-spacing: 0.06em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.monitor-stand-neck {
|
||||
width: 24px;
|
||||
height: 18px;
|
||||
background: linear-gradient(180deg, #2a2a3e 0%, #222236 100%);
|
||||
margin: 0 auto;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.monitor-stand-base {
|
||||
width: 100px;
|
||||
height: 5px;
|
||||
margin: 0 auto;
|
||||
border-radius: 3px;
|
||||
background: var(--monitor-theme, #60ce93);
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
/* sm */
|
||||
@media (min-width: 640px) {
|
||||
.monitor-frame {
|
||||
max-width: 700px;
|
||||
border-radius: 10px;
|
||||
padding: 8px 8px 4px 8px;
|
||||
box-shadow:
|
||||
0 0 0 1.5px #2a2a3e,
|
||||
0 3px 16px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.monitor-screen {
|
||||
border-radius: 3px;
|
||||
height: 260px;
|
||||
}
|
||||
.monitor-chin { padding: 6px 0 3px 0; }
|
||||
.monitor-chin-label { font-size: 10px; }
|
||||
.monitor-stand-neck { width: 30px; height: 24px; border-radius: 0 0 5px 5px; }
|
||||
.monitor-stand-base { width: 130px; height: 7px; border-radius: 4px; }
|
||||
}
|
||||
|
||||
/* md */
|
||||
@media (min-width: 768px) {
|
||||
.monitor-frame {
|
||||
max-width: 780px;
|
||||
border-radius: 12px;
|
||||
padding: 10px 10px 6px 10px;
|
||||
box-shadow:
|
||||
0 0 0 2px #2a2a3e,
|
||||
0 4px 24px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.monitor-screen {
|
||||
border-radius: 4px;
|
||||
height: 360px;
|
||||
}
|
||||
.monitor-chin { padding: 8px 0 4px 0; }
|
||||
.monitor-chin-label { font-size: 11px; }
|
||||
.monitor-stand-neck { width: 36px; height: 30px; border-radius: 0 0 6px 6px; }
|
||||
.monitor-stand-base { width: 150px; height: 8px; border-radius: 4px; }
|
||||
}
|
||||
|
||||
/* lg */
|
||||
@media (min-width: 1024px) {
|
||||
.monitor-frame { max-width: 820px; }
|
||||
.monitor-screen { height: 440px; }
|
||||
}
|
||||
|
||||
/* xl */
|
||||
@media (min-width: 1280px) {
|
||||
.monitor-frame { max-width: 860px; }
|
||||
.monitor-screen { height: 500px; }
|
||||
.monitor-stand-neck { width: 40px; height: 36px; }
|
||||
.monitor-stand-base { width: 180px; height: 10px; border-radius: 5px; }
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@ export default function Contact() {
|
||||
<section className="relative py-32 md:py-40 text-white overflow-hidden">
|
||||
{/* Background image */}
|
||||
<div className="absolute inset-0">
|
||||
<img src={new URL('../assets/images/Carousel/huaban.jpg', import.meta.url).href} alt="" className="w-full h-full object-cover" />
|
||||
<img src={new URL('../../public/huaban.jpg', import.meta.url).href} alt="" className="w-full h-full object-cover" />
|
||||
</div>
|
||||
{/* Black overlay */}
|
||||
<div className="absolute inset-0 bg-black/50" />
|
||||
<div className="relative max-w-4xl mx-auto px-6 text-center pt-32">
|
||||
<h1 className="text-4xl md:text-6xl font-bold mb-10 hero-product-title">携手合作</h1>
|
||||
<h1 className="text-4xl md:text-6xl font-bold mb-10 hero-product-title">共建智慧校园</h1>
|
||||
<p className="text-xl md:text-2xl max-w-2xl mx-auto leading-loose hero-product-slogan">
|
||||
<h1 className="text-3xl xs:text-4xl sm:text-5xl md:text-6xl font-bold mb-6 md:mb-10 hero-product-title">携手合作</h1>
|
||||
<h1 className="text-3xl xs:text-4xl sm:text-5xl md:text-6xl font-bold mb-6 md:mb-10 hero-product-title">共建智慧校园</h1>
|
||||
<p className="text-base xs:text-lg sm:text-xl md:text-2xl max-w-2xl mx-auto leading-loose hero-product-slogan">
|
||||
诚邀广西各界教育伙伴,共同为职业院校提供优质的数字化解决方案
|
||||
</p>
|
||||
</div>
|
||||
@@ -45,15 +45,15 @@ export default function Contact() {
|
||||
<ScrollReveal className="mb-16 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">Contact</span>
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#004ec4]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#004ec4]">Contact</span>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
联系方式
|
||||
</h2>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 md:gap-6">
|
||||
{[
|
||||
{ icon: MapPin, title: '公司地址', text: '南宁市总部路3号中国东盟科技企业孵化基地二期9号厂房二楼212房' },
|
||||
{ icon: Phone, title: '联系电话', text: '0771-3864294' },
|
||||
@@ -62,21 +62,20 @@ export default function Contact() {
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<ScrollReveal key={i} delay={i * 0.08}>
|
||||
<div className="relative bg-[#fafbfc] rounded-2xl p-8 md:p-10 h-full border border-gray-100 hover:shadow-xl hover:shadow-[#043b8f]/5 transition-all duration-500 group overflow-hidden">
|
||||
<div className="relative bg-[#fafbfc] rounded-xl md:rounded-2xl p-6 sm:p-8 md:p-10 h-full border border-gray-100 hover:shadow-xl hover:shadow-[#004ec4]/5 transition-all duration-500 group overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-28 h-28 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-16 h-16 border border-[#043b8f]/[0.06] rounded-tr-3xl" />
|
||||
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #004ec4, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-20 sm:w-28 h-20 sm:h-28 bg-[#004ec4]/[0.06] rounded-bl-full" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center gap-3 mb-5">
|
||||
<div className="w-11 h-11 rounded-xl flex items-center justify-center bg-[#043b8f]/[0.06] border border-[#043b8f]/10">
|
||||
<Icon className="w-5 h-5 text-[#043b8f]" />
|
||||
<div className="flex items-center gap-3 mb-4 md:mb-5">
|
||||
<div className="w-9 h-9 sm:w-11 sm:h-11 rounded-xl flex items-center justify-center bg-[#004ec4]/[0.12] border border-[#004ec4]/20">
|
||||
<Icon className="w-4 h-4 sm:w-5 sm:h-5 text-[#004ec4]" />
|
||||
</div>
|
||||
<div className="h-px flex-1 bg-gradient-to-r from-[#043b8f]/10 to-transparent" />
|
||||
<div className="h-px flex-1 bg-gradient-to-r from-[#004ec4]/25 to-transparent" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#0f172a] mb-3">{item.title}</h3>
|
||||
<p className="text-[#64748b] text-sm leading-relaxed">{item.text}</p>
|
||||
<h3 className="text-lg sm:text-xl font-bold text-[#0f172a] mb-2 md:mb-3">{item.title}</h3>
|
||||
<p className="text-[#64748b] text-sm sm:text-base leading-relaxed">{item.text}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
@@ -92,34 +91,33 @@ export default function Contact() {
|
||||
<ScrollReveal className="mb-16 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">Partnership</span>
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#004ec4]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#004ec4]">Partnership</span>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
成为代理商
|
||||
</h2>
|
||||
<p className="text-[#475569] text-lg md:text-xl mt-5 max-w-xl leading-[2]">
|
||||
<p className="text-[#475569] text-sm sm:text-base md:text-lg lg:text-xl mt-4 md:mt-5 max-w-xl leading-[1.8] md:leading-[2]">
|
||||
诚邀广西各地区具有教育行业资源的合作伙伴,共享职业院校信息化发展机遇
|
||||
</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-14 max-w-3xl mx-auto">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6 mb-10 md:mb-14 max-w-3xl mx-auto">
|
||||
{agentBenefits.map((item, i) => {
|
||||
return (
|
||||
<ScrollReveal key={i} delay={i * 0.05}>
|
||||
<div className="relative bg-white rounded-2xl p-8 md:p-10 h-full border border-gray-100 hover:shadow-xl hover:shadow-[#043b8f]/5 transition-all duration-500 group overflow-hidden">
|
||||
<div className="relative bg-white rounded-xl md:rounded-2xl p-6 sm:p-8 md:p-10 h-full border border-gray-100 hover:shadow-xl hover:shadow-[#004ec4]/5 transition-all duration-500 group overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-20 h-20 border border-[#043b8f]/[0.06] rounded-tr-3xl" />
|
||||
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #004ec4, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-24 sm:w-32 h-24 sm:h-32 bg-[#004ec4]/[0.06] rounded-bl-full" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<span className="flex items-center justify-center w-8 h-8 rounded-md bg-[#043b8f]/[0.06] text-xs font-black text-[#043b8f]">0{i + 1}</span>
|
||||
<div className="h-px flex-1 bg-gradient-to-r from-[#043b8f]/10 to-transparent" />
|
||||
<div className="flex items-center gap-3 mb-3 md:mb-4">
|
||||
<span className="flex items-center justify-center w-7 h-7 sm:w-8 sm:h-8 rounded-md bg-[#004ec4]/[0.12] text-xs font-black text-[#004ec4]">0{i + 1}</span>
|
||||
<div className="h-px flex-1 bg-gradient-to-r from-[#004ec4]/25 to-transparent" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#0f172a] mb-3">{item.title}</h3>
|
||||
<p className="text-[#64748b] text-lg leading-relaxed">{item.desc}</p>
|
||||
<h3 className="text-lg sm:text-xl font-bold text-[#0f172a] mb-2 md:mb-3">{item.title}</h3>
|
||||
<p className="text-[#64748b] text-sm sm:text-base md:text-lg leading-relaxed">{item.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
@@ -129,18 +127,18 @@ export default function Contact() {
|
||||
|
||||
<ScrollReveal>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="relative bg-white rounded-2xl p-8 md:p-10 border border-gray-100 overflow-hidden">
|
||||
<div className="relative bg-white rounded-xl md:rounded-2xl p-6 sm:p-8 md:p-10 border border-gray-100 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-100"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-28 h-28 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-16 h-16 border border-[#043b8f]/[0.06] rounded-tr-3xl" />
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #004ec4, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-20 sm:w-28 h-20 sm:h-28 bg-[#004ec4]/[0.06] rounded-bl-full" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<h3 className="text-2xl md:text-3xl font-black text-[#0f172a] mb-10 tracking-tight leading-[1.1]">合作基本要求</h3>
|
||||
<div className="space-y-6">
|
||||
<h3 className="text-xl sm:text-2xl md:text-3xl font-black text-[#0f172a] mb-6 md:mb-10 tracking-tight leading-[1.1]">合作基本要求</h3>
|
||||
<div className="space-y-4 md:space-y-6">
|
||||
{requirements.map((req, i) => (
|
||||
<div key={i} className="flex items-center gap-5">
|
||||
<span className="flex items-center justify-center w-9 h-9 rounded-lg bg-[#043b8f]/[0.06] text-sm font-black text-[#043b8f] shrink-0">{i + 1}</span>
|
||||
<span className="text-[#334155] text-lg leading-relaxed">{req}</span>
|
||||
<div key={i} className="flex items-center gap-4 md:gap-5">
|
||||
<span className="flex items-center justify-center w-7 h-7 sm:w-9 sm:h-9 rounded-lg bg-[#004ec4]/[0.12] text-xs sm:text-sm font-black text-[#004ec4] shrink-0">{i + 1}</span>
|
||||
<span className="text-[#334155] text-sm sm:text-base md:text-lg leading-relaxed">{req}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -164,22 +162,22 @@ export default function Contact() {
|
||||
/>
|
||||
<div className="relative max-w-3xl mx-auto text-center">
|
||||
<ScrollReveal>
|
||||
<h2 className="text-4xl md:text-6xl font-bold text-white mb-8">携手讯驰 共建智慧校园</h2>
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-6xl font-bold text-white mb-6 md:mb-8">携手讯驰 共建智慧校园</h2>
|
||||
|
||||
<p className="text-white text-md mb-14 max-w-xl mx-auto leading-relaxed">
|
||||
<p className="text-white text-sm xs:text-base sm:text-lg mb-10 md:mb-14 max-w-xl mx-auto leading-relaxed">
|
||||
获取产品演示与个性化方案,迈出数字化转型第一步
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<div className="flex flex-col sm:flex-row gap-3 xs:gap-4 justify-center">
|
||||
<Link
|
||||
to="/"
|
||||
className="inline-flex items-center gap-2 px-8 py-3 rounded-xl text-sm font-semibold text-white border border-white hover:bg-white/10 transition-all"
|
||||
className="inline-flex items-center justify-center gap-2 px-6 xs:px-8 py-2.5 xs:py-3 rounded-xl text-xs xs:text-sm font-semibold text-white border border-white hover:bg-white/10 transition-all"
|
||||
>
|
||||
返回首页
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
<ArrowRight className="w-3.5 h-3.5 xs:w-4 xs:h-4" />
|
||||
</Link>
|
||||
<a
|
||||
href="tel:07713864294"
|
||||
className="inline-flex items-center gap-2 px-8 py-3 rounded-xl text-sm font-semibold text-white border border-white hover:bg-white/10 transition-all"
|
||||
className="inline-flex items-center justify-center gap-2 px-6 xs:px-8 py-2.5 xs:py-3 rounded-xl text-xs xs:text-sm font-semibold text-white border border-white hover:bg-white/10 transition-all"
|
||||
>
|
||||
致电 0771-3864294
|
||||
</a>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { Link } from 'react-router-dom';
|
||||
import HeroSection from '../components/HeroSection'
|
||||
|
||||
import ScrollReveal from '../components/ScrollReveal'
|
||||
import CertificateCarousel from '../components/CertificateCarousel'
|
||||
import { products } from '../data/products'
|
||||
import RosePieChart from '../components/RosePieChart'
|
||||
import { ArrowRight, MapPin, Award, Headphones, Shield } from 'lucide-react'
|
||||
import StatNumber from '../components/StatNumber'
|
||||
import hunBg from '../assets/images/hun.jpg'
|
||||
import {ArrowRight, Play, Users, Building2} from 'lucide-react'
|
||||
|
||||
/* ─── Section 3: 数据亮点 ─── */
|
||||
const stats = [
|
||||
{ num: '40', suffix: '+', label: '软件著作权' },
|
||||
{ num: '5', suffix: '项', label: 'ISO体系认证' },
|
||||
{ num: '15', suffix: '年', label: '行业深耕经验' },
|
||||
{ num: '16', suffix: '年', label: '行业深耕经验' },
|
||||
{ num: '94', suffix: '+', label: '合作院校覆盖' },
|
||||
]
|
||||
|
||||
@@ -41,92 +41,29 @@ const capabilities = [
|
||||
|
||||
|
||||
|
||||
/* ─── Section 7: 客户认可 ─── */
|
||||
const customerCards = [
|
||||
{
|
||||
type: 'school',
|
||||
icon: Building2,
|
||||
title: 'ISO 9001 质量管理体系',
|
||||
|
||||
},
|
||||
{
|
||||
type: 'video',
|
||||
icon: Play,
|
||||
title: 'ISO 14001 环境管理体系',
|
||||
|
||||
},
|
||||
{
|
||||
type: 'satisfaction',
|
||||
icon: Users,
|
||||
title: 'ISO 45001 职业健康安全管理体系',
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
type: 'satisfaction',
|
||||
icon: Users,
|
||||
title: 'ISO 27001 信息安全管理体系',
|
||||
|
||||
},
|
||||
{
|
||||
type: 'satisfaction',
|
||||
icon: Users,
|
||||
title: 'ISO 20000 信息技术服务管理体系',
|
||||
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
/* ─── Animated counter ─── */
|
||||
function StatNumber({ target, suffix }) {
|
||||
const [count, setCount] = useState(0)
|
||||
const ref = useRef(null)
|
||||
const started = useRef(false)
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current
|
||||
if (!el) return
|
||||
const obs = new IntersectionObserver(([e]) => {
|
||||
if (e.isIntersecting && !started.current) {
|
||||
started.current = true
|
||||
const dur = 2000
|
||||
const start = performance.now()
|
||||
const num = parseInt(target)
|
||||
function tick(now) {
|
||||
const p = Math.min((now - start) / dur, 1)
|
||||
setCount(Math.round((1 - Math.pow(1 - p, 3)) * num))
|
||||
if (p < 1) requestAnimationFrame(tick)
|
||||
}
|
||||
requestAnimationFrame(tick)
|
||||
obs.unobserve(el)
|
||||
}
|
||||
}, { threshold: 0.3 })
|
||||
obs.observe(el)
|
||||
return () => obs.disconnect()
|
||||
}, [target])
|
||||
|
||||
return <span ref={ref}>{count}{suffix}</span>
|
||||
}
|
||||
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
|
||||
export default function Home() {
|
||||
const [activeCapability, setActiveCapability] = useState(0)
|
||||
const [tagRadius, setTagRadius] = useState(68)
|
||||
const [activeStep, setActiveStep] = useState(0)
|
||||
const [lightPos, setLightPos] = useState(0) // 光点位置(立即移动)
|
||||
const timerRef = useRef(null)
|
||||
const activeColor = products[activeCapability]?.themeColor || '#043b8f'
|
||||
|
||||
const handleStepClick = (i) => {
|
||||
if (timerRef.current) clearTimeout(timerRef.current)
|
||||
setLightPos(i) // 光点立即开始滑动
|
||||
timerRef.current = setTimeout(() => {
|
||||
setActiveStep(i) // 700ms 后节点变色
|
||||
}, 700)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const updateRadius = () => {
|
||||
const w = window.innerWidth
|
||||
if (w < 480) setTagRadius(40)
|
||||
else if (w < 768) setTagRadius(48)
|
||||
else if (w < 1024) setTagRadius(54)
|
||||
else setTagRadius(60)
|
||||
}
|
||||
updateRadius()
|
||||
window.addEventListener('resize', updateRadius)
|
||||
return () => window.removeEventListener('resize', updateRadius)
|
||||
return () => { if (timerRef.current) clearTimeout(timerRef.current) }
|
||||
}, [])
|
||||
|
||||
return (
|
||||
@@ -159,98 +96,108 @@ export default function Home() {
|
||||
|
||||
{/* ─── 4. 开放能力区(白底) ─── */}
|
||||
<section id="products" className="py-20 px-4 bg-white">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<ScrollReveal className="text-center mb-14">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<ScrollReveal className="text-center mb-8 md:mb-14">
|
||||
<p className="text-[10px] xs:text-xs text-[#004ec4] tracking-[0.25em] uppercase mb-3 font-semibold">Core Capabilities</p>
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-7xl font-bold text-[#0f172a] mb-6">四大产品体系</h2>
|
||||
<p className="text-[#64748b] text-sm xs:text-base md:text-lg lg:text-xl mx-auto md:whitespace-nowrap mb-4 leading-relaxed">全面覆盖职业院校教学、管理、党建、科研四大核心场景,为数字化校园建设提供一站式解决方案</p>
|
||||
<h2 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl lg:text-7xl font-bold text-[#0f172a] mb-6">四大产品体系</h2>
|
||||
<p className="text-[#64748b] text-sm xs:text-base md:text-lg lg:text-xl xl:text-2xl mx-auto max-w-3xl md:whitespace-nowrap mb-4 leading-relaxed px-2">全面覆盖职业院校教学、管理、党建、科研四大核心场景,为数字化校园建设提供一站式解决方案</p>
|
||||
</ScrollReveal>
|
||||
|
||||
{/* Tab bar */}
|
||||
<ScrollReveal>
|
||||
<div className="flex justify-center gap-1 mb-12 flex-wrap">
|
||||
{products.map((p, i) => (
|
||||
<div className="flex flex-wrap justify-center gap-1 sm:gap-1.5 mb-8 md:mb-26">
|
||||
{products.map((p, i) => {
|
||||
const isActive = activeCapability === i
|
||||
return (
|
||||
<button
|
||||
key={p.slug}
|
||||
onClick={() => setActiveCapability(i)}
|
||||
className={`flex items-center gap-1.5 xs:gap-2 px-3 xs:px-4 sm:px-6 py-2 xs:py-3 rounded-lg text-xs xs:text-sm font-medium transition-all border ${activeCapability === i
|
||||
? 'text-[#043b8f] border-[#043b8f]'
|
||||
: 'text-[#475569] border-gray-200 hover:text-[#043b8f] hover:border-[#043b8f]'
|
||||
}`}
|
||||
className="flex items-center justify-center gap-1 xs:gap-2 sm:gap-3 px-2 xs:px-3 sm:px-5 md:px-7 py-2 xs:py-2.5 sm:py-3.5 rounded-lg text-xs xs:text-sm sm:text-base md:text-lg lg:text-xl font-bold transition-all border w-[calc(50%-0.25rem)] xs:w-[calc(50%-0.375rem)] sm:w-auto"
|
||||
style={{
|
||||
color: isActive ? p.themeColor : '#475569',
|
||||
borderColor: isActive ? p.themeColor : '#e5e7eb',
|
||||
}}
|
||||
onMouseEnter={(e) => { if (!isActive) { e.target.style.color = p.themeColor; e.target.style.borderColor = p.themeColor; } }}
|
||||
onMouseLeave={(e) => { if (!isActive) { e.target.style.color = '#475569'; e.target.style.borderColor = '#e5e7eb'; } }}
|
||||
>
|
||||
<p.icon className="w-4 h-4 xs:w-5 xs:h-5" style={{ color: activeCapability === i ? '#043b8f' : p.themeColor }} />
|
||||
<p.icon className="w-3 h-3 xs:w-4 xs:h-4 sm:w-5 sm:h-5" style={{ color: isActive ? p.themeColor : p.themeColor }} />
|
||||
{p.name}
|
||||
</button>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
{/* Left-right layout */}
|
||||
<ScrollReveal>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center mb-12">
|
||||
{/* Left: visual */}
|
||||
<div className="flex justify-center">
|
||||
<RosePieChart onSelect={setActiveCapability} activeIndex={activeCapability} />
|
||||
<div className="flex flex-col mb-16 md:mb-32 mt-4 md:mt-8 bg-white rounded-2xl md:rounded-3xl border border-gray-200 shadow-lg overflow-hidden">
|
||||
{/* ── 窗口标题栏(macOS 风格) ── */}
|
||||
<div className="flex items-center gap-2 px-4 py-2.5 md:px-5 md:py-3 bg-gray-100 border-b border-gray-200">
|
||||
<div className="w-3 h-3 rounded-full bg-red-400 flex-shrink-0" />
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-400 flex-shrink-0" />
|
||||
<div className="w-3 h-3 rounded-full bg-green-400 flex-shrink-0" />
|
||||
<span className="text-xs text-gray-400 ml-2 font-medium truncate">
|
||||
{capabilities[activeCapability].title} — 产品详情
|
||||
</span>
|
||||
</div>
|
||||
{/* ── 内容区 ── */}
|
||||
<div className="flex flex-col lg:flex-row gap-6 md:gap-8 lg:gap-12 xl:gap-24 lg:items-stretch p-6 sm:p-8 md:p-10 lg:p-12 bg-gradient-to-br from-gray-50 to-white lg:h-[520px]">
|
||||
{/* Left: visual — 产品图片 */}
|
||||
<div className="w-full lg:w-1/2 lg:max-w-xl flex items-center justify-center">
|
||||
{products[activeCapability]?.heroImage && (
|
||||
<img src={products[activeCapability].heroImage} alt={products[activeCapability].name} className="w-full h-auto max-h-full object-contain" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right: text */}
|
||||
<div className="space-y-4">
|
||||
{(activeCapability !== null ? [capabilities[activeCapability]] : capabilities).map((c, i) => {
|
||||
const idx = activeCapability !== null ? activeCapability : i
|
||||
return (
|
||||
<div key={idx} className={`relative p-8 rounded-2xl transition-all duration-500 cursor-pointer group overflow-hidden ${activeCapability === idx
|
||||
? 'bg-white border border-[#043b8f]/20 shadow-[0_4px_24px_rgba(4,59,199,0.12)]'
|
||||
: 'hover:bg-gray-50/80 border border-gray-100'
|
||||
}`} onClick={() => setActiveCapability(idx)}>
|
||||
{activeCapability === idx && (
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px]"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
)}
|
||||
<div className="absolute top-0 right-0 w-24 h-24 bg-[#043b8f]/[0.03] rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="absolute bottom-0 left-0 w-16 h-16 border border-[#043b8f]/[0.06] rounded-tr-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<span className={`flex items-center justify-center w-7 h-7 rounded-md text-[11px] font-black transition-colors duration-300 ${activeCapability === idx
|
||||
? 'bg-[#043b8f]/[0.08] text-[#043b8f]'
|
||||
: 'bg-gray-100 text-[#94a3b8]'
|
||||
}`}>0{idx + 1}</span>
|
||||
<div className={`h-px flex-1 transition-colors duration-300 ${activeCapability === idx
|
||||
? 'bg-gradient-to-r from-[#043b8f]/15 to-transparent'
|
||||
: 'bg-gray-100'
|
||||
}`} />
|
||||
</div>
|
||||
<h3 className={`text-lg xs:text-xl sm:text-2xl font-bold transition-colors duration-300 ${activeCapability === idx ? 'text-[#043b8f]' : 'text-[#0f172a]'
|
||||
}`}>{c.title}</h3>
|
||||
<p className={`text-sm xs:text-base mt-1.5 font-medium transition-colors duration-300 ${activeCapability === idx ? 'text-[#043b8f]/60' : 'text-[#94a3b8]'
|
||||
}`}>{c.sub}</p>
|
||||
<p className="text-sm xs:text-base text-[#334155] leading-[2] mt-4">{c.desc}</p>
|
||||
{c.tip && (
|
||||
<div className="mt-5 flex flex-wrap gap-2">
|
||||
{c.tip.split('、').map((t, ti) => (
|
||||
<span key={ti} className={`px-3 py-1 xs:px-4 xs:py-1.5 text-xs xs:text-sm font-medium rounded-md transition-all duration-200 ${
|
||||
activeCapability === idx
|
||||
? 'text-[#043b8f] bg-[#043b8f]/[0.08]'
|
||||
: 'text-[#94a3b8] bg-gray-50'
|
||||
}`}>
|
||||
{t}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{activeCapability === idx && (
|
||||
<div className="mt-5 flex justify-end">
|
||||
<Link to={`/product/${c.slug}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="text-sm text-[#043b8f]/60 hover:text-[#043b8f] hover:underline flex items-center gap-1 transition-colors duration-200">
|
||||
查看全部
|
||||
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7" /></svg>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{/* Right: text — 纯文字布局 */}
|
||||
<div className="w-full lg:w-1/2 lg:max-w-xl flex flex-col justify-center">
|
||||
{/* 顶部装饰线 + 标签 */}
|
||||
<div className="flex items-center gap-3 mb-3 md:mb-4">
|
||||
<span className="w-6 md:w-8 h-[2px] rounded-full" style={{ backgroundColor: activeColor + '66' }} />
|
||||
<span className="text-xs sm:text-sm md:text-lg font-bold tracking-[0.22em] uppercase" style={{ color: activeColor + '99' }}>
|
||||
Core Capability
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 标题 */}
|
||||
<h3 className="text-xl sm:text-2xl md:text-3xl lg:text-4xl xl:text-5xl font-black text-[#0f172a] tracking-tight leading-[1.1] mb-2">
|
||||
{capabilities[activeCapability].title}
|
||||
</h3>
|
||||
|
||||
{/* 副标题 */}
|
||||
<p className="text-sm sm:text-base md:text-lg lg:text-xl font-semibold mb-4 md:mb-5" style={{ color: activeColor + 'aa' }}>
|
||||
{capabilities[activeCapability].sub}
|
||||
</p>
|
||||
|
||||
{/* 正文 */}
|
||||
<p className="text-[#334155] text-sm sm:text-base md:text-lg lg:text-xl leading-[1.7] md:leading-[1.8] font-medium mb-4 md:mb-6">
|
||||
{capabilities[activeCapability].desc}
|
||||
</p>
|
||||
|
||||
{/* Tags — 只展示前 3 个 */}
|
||||
{capabilities[activeCapability].tip && (
|
||||
<div className="flex flex-wrap items-center gap-1.5 md:gap-2 pt-4 md:pt-5 border-t border-gray-100">
|
||||
{capabilities[activeCapability].tip.split('、').slice(0, 3).map((t, ti) => (
|
||||
<span key={ti} className="px-2 md:px-3 py-1 text-xs sm:text-sm md:text-base font-semibold rounded-lg border transition-all duration-300 hover:-translate-y-1 cursor-default"
|
||||
style={{ color: activeColor, borderColor: activeColor + '40', backgroundColor: activeColor + '0a' }}>
|
||||
{t}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 查看全部 */}
|
||||
<div className="mt-auto pt-4 md:pt-5 flex justify-end">
|
||||
<Link to={`/product/${capabilities[activeCapability].slug}`}
|
||||
className="inline-flex items-center gap-1.5 px-3 md:px-4 py-1.5 md:py-2 rounded-lg text-sm md:text-base font-semibold transition-all duration-300 hover:brightness-110"
|
||||
style={{ color: '#fff', backgroundColor: activeColor }}>
|
||||
查看全部
|
||||
<svg className="w-3 h-3 md:w-3.5 md:h-3.5 transition-transform duration-300 group-hover:translate-x-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7" /></svg>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
{/* Bottom button */}
|
||||
@@ -266,150 +213,164 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ─── 5. 企业级解决方案区(深色) ─── */}
|
||||
<section className="py-20 px-4 relative overflow-hidden"
|
||||
style={{ background: `linear-gradient(180deg, rgba(0,10,30,0.7) 0%, rgba(0,20,50,0.5) 50%, rgba(0,10,30,0.7) 100%), url(${hunBg}) center/cover no-repeat` }}>
|
||||
{/* ─── 5. 为什么选择讯驰 ─── */}
|
||||
<section className="py-20 md:py-32 px-4 sm:px-6 md:px-10 relative overflow-hidden"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, rgba(10,22,40,0.75), rgba(15,31,58,0.75)), url(${hunBg}) center/cover no-repeat`,
|
||||
}}>
|
||||
{/* 大型光晕 */}
|
||||
<div className="absolute top-0 left-1/4 w-[800px] h-[800px] rounded-full opacity-[0.04]"
|
||||
style={{ background: 'radial-gradient(circle, #004ec4, transparent 60%)' }}
|
||||
/>
|
||||
<div className="absolute bottom-0 right-1/4 w-[600px] h-[600px] rounded-full opacity-[0.04]"
|
||||
style={{ background: 'radial-gradient(circle, #2563eb, transparent 60%)' }}
|
||||
/>
|
||||
|
||||
<div className="relative max-w-5xl mx-auto text-center">
|
||||
<div className="relative max-w-7xl mx-auto">
|
||||
{/* 标题 */}
|
||||
<ScrollReveal>
|
||||
<p className="text-[10px] xs:text-xs text-white/80 tracking-[0.3em] uppercase mb-4 font-semibold">Why Choose Us</p>
|
||||
<h2 className="text-3xl xs:text-4xl md:text-6xl font-black mb-6 leading-tight text-white"
|
||||
style={{
|
||||
textShadow: '0 4px 30px rgba(59,130,246,0.3), 0 2px 4px rgba(0,0,0,0.4)',
|
||||
}}>为什么选择讯驰</h2>
|
||||
<div className="flex items-center justify-center gap-3 mb-16">
|
||||
<span className="w-12 h-px bg-gradient-to-r from-transparent to-white/60" />
|
||||
<p className="text-white text-base xs:text-lg sm:text-xl md:text-2xl font-medium tracking-wider">AAA级信用企业 · 高新技术企业</p>
|
||||
<span className="w-12 h-px bg-gradient-to-l from-transparent to-white/60" />
|
||||
<div className="text-center mb-12 md:mb-20">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-2 md:gap-3 mb-4 md:mb-5">
|
||||
<span className="w-6 md:w-8 h-[2px] rounded-full bg-white/30" />
|
||||
<span className="text-[10px] md:text-[11px] font-bold tracking-[0.22em] uppercase text-white/60">Why Choose Us</span>
|
||||
<span className="w-6 md:w-8 h-[2px] rounded-full bg-white/30" />
|
||||
</div>
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-black text-white tracking-tight leading-[1.1] mb-3 md:mb-4"
|
||||
style={{ textShadow: '0 4px 60px rgba(59,130,246,0.25), 0 2px 8px rgba(0,0,0,0.5)' }}>
|
||||
为什么选择讯驰
|
||||
</h2>
|
||||
<p className="text-white/50 text-sm xs:text-base md:text-lg font-medium tracking-wider">
|
||||
AAA级信用企业 · 高新技术企业 · 16年行业深耕
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
{/* Surrounding tags */}
|
||||
<ScrollReveal>
|
||||
<div className="relative w-[280px] h-[280px] xs:w-[320px] xs:h-[320px] md:w-[420px] md:h-[420px] lg:w-[500px] lg:h-[500px] mx-auto mb-16">
|
||||
{/* Outer rings */}
|
||||
<div className="absolute inset-0 rounded-full border border-white/[0.08]" />
|
||||
<div className="absolute inset-6 xs:inset-8 md:inset-10 lg:inset-12 rounded-full border border-white/[0.06]" />
|
||||
<div className="absolute inset-12 xs:inset-16 md:inset-20 lg:inset-24 rounded-full border border-white/[0.04]" />
|
||||
|
||||
{/* Orbiting dots */}
|
||||
<div className="absolute w-2 h-2 rounded-full bg-[#004ec4]"
|
||||
style={{ top: '8%', left: '50%', transform: 'translateX(-50%)', boxShadow: '0 0 10px rgba(0,78,196,0.6)' }} />
|
||||
<div className="absolute w-1.5 h-1.5 rounded-full bg-[#f08519]"
|
||||
style={{ bottom: '12%', right: '15%', boxShadow: '0 0 8px rgba(240,133,25,0.6)' }} />
|
||||
|
||||
{/* Tags around circle */}
|
||||
{[
|
||||
{ text: '深耕广西,扎根本土', angle: 250 },
|
||||
{ text: '产品成熟,实战验证', angle: 300 },
|
||||
{ text: '贴心服务,全程陪伴', angle: 55 },
|
||||
{ text: '数据安全,合规可靠', angle: 120 },
|
||||
].map((tag, i) => {
|
||||
const rad = (tag.angle * Math.PI) / 180
|
||||
const r = tagRadius
|
||||
const x = 50 + r * Math.sin(rad)
|
||||
const y = 50 - r * Math.cos(rad)
|
||||
const colors = [
|
||||
{ bg: 'linear-gradient(135deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%)', dark: 'rgba(255,255,255,0.2)', glow: 'rgba(255,255,255,0.1)', border: 'rgba(255,255,255,0.25)' },
|
||||
{ bg: 'linear-gradient(135deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%)', dark: 'rgba(255,255,255,0.2)', glow: 'rgba(255,255,255,0.1)', border: 'rgba(255,255,255,0.25)' },
|
||||
{ bg: 'linear-gradient(135deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%)', dark: 'rgba(255,255,255,0.2)', glow: 'rgba(255,255,255,0.1)', border: 'rgba(255,255,255,0.25)' },
|
||||
{ bg: 'linear-gradient(135deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%)', dark: 'rgba(255,255,255,0.2)', glow: 'rgba(255,255,255,0.1)', border: 'rgba(255,255,255,0.25)' },
|
||||
]
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute whitespace-nowrap"
|
||||
style={{
|
||||
left: `${x}%`,
|
||||
top: `${y}%`,
|
||||
transform: 'translate(-50%, -50%)',
|
||||
}}
|
||||
>
|
||||
{/* 书签主体 */}
|
||||
<div
|
||||
className="relative px-3 py-2 xs:px-4 xs:py-2.5 md:px-6 md:py-3.5 lg:px-7 lg:py-4 text-xs xs:text-sm md:text-base lg:text-lg font-bold text-white/95 overflow-hidden"
|
||||
style={{
|
||||
background: colors[i].bg,
|
||||
borderRadius: '12px 12px 4px 4px',
|
||||
border: `1px solid ${colors[i].border}`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
boxShadow: `0 0 25px ${colors[i].glow}, 0 6px 16px rgba(0,0,0,0.25)`,
|
||||
}}
|
||||
>
|
||||
{/* 顶部高光条 */}
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px]"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent)' }}
|
||||
/>
|
||||
{/* 左侧折角 */}
|
||||
<div className="absolute top-0 left-0 w-4 h-4"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(255,255,255,0.2) 50%, transparent 50%)',
|
||||
borderRadius: '12px 0 0 0',
|
||||
}}
|
||||
/>
|
||||
{i < 2
|
||||
? <>{tag.text}<span className="inline-block w-1.5 h-1.5 xs:w-2 xs:h-2 rounded-full bg-white/80 ml-1.5 xs:ml-2 align-middle" /></>
|
||||
: <><span className="inline-block w-1.5 h-1.5 xs:w-2 xs:h-2 rounded-full bg-white/80 mr-1.5 xs:mr-2 align-middle" />{tag.text}</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
{/* Bottom button */}
|
||||
<ScrollReveal>
|
||||
<Link
|
||||
to="/contact"
|
||||
className="inline-flex items-center gap-2 px-6 xs:px-8 py-2.5 xs:py-3 rounded-full text-sm xs:text-base font-medium text-white border border-white/20 hover:bg-white/10 hover:border-white/40 transition-all duration-300"
|
||||
style={{ boxShadow: '0 4px 20px rgba(0,0,0,0.2)' }}
|
||||
>
|
||||
获取解决方案
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</Link>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
{/* ─── 7. 客户认可区(白底) ─── */}
|
||||
<section className="py-20 px-4 bg-[#f8fafc]">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<ScrollReveal className="text-center mb-14">
|
||||
<p className="text-[10px] xs:text-xs text-[#004ec4] tracking-[0.25em] uppercase mb-3 font-semibold">Recognition</p>
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-6xl font-bold text-[#0f172a] mb-4">资质与认证</h2>
|
||||
<p className="text-[#64748b] text-sm xs:text-base max-w-xl mx-auto">AAA级信用企业 · 高新技术企业</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{customerCards.map((card, i) => {
|
||||
const Icon = card.icon
|
||||
{/* 4 大优势 — 响应式不换行 */}
|
||||
<div className="flex flex-wrap md:flex-nowrap justify-center gap-2 sm:gap-4 md:gap-6 lg:gap-10 mb-12 md:mb-16">
|
||||
{[
|
||||
{ icon: MapPin, title: '深耕广西' },
|
||||
{ icon: Award, title: '产品成熟'},
|
||||
{ icon: Headphones, title: '贴心服务'},
|
||||
{ icon: Shield, title: '数据安全' },
|
||||
].map((item, i) => {
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<ScrollReveal key={i} delay={i * 0.1}>
|
||||
<div className="group relative bg-white rounded-2xl p-8 border border-gray-100 text-center h-full flex flex-col items-center transition-all duration-500 hover:shadow-xl hover:shadow-[#043b8f]/5 hover:-translate-y-1 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #043b8f, transparent)' }} />
|
||||
<div className="absolute top-0 right-0 w-20 h-20 bg-[#043b8f]/[0.03] rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="absolute bottom-0 left-0 w-14 h-14 border border-[#043b8f]/[0.06] rounded-tr-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
{/* 图标 */}
|
||||
<div className="w-12 h-12 xs:w-14 xs:h-14 sm:w-16 sm:h-16 rounded-xl bg-[#043b8f]/[0.06] border border-[#043b8f]/10 flex items-center justify-center mb-5 group-hover:bg-[#043b8f]/10 transition-all duration-300">
|
||||
<Icon className="w-6 h-6 xs:w-7 xs:h-7 sm:w-8 sm:h-8 text-[#043b8f]" />
|
||||
<div className="group relative block w-[42vw] sm:w-[42vw] md:w-48 lg:w-56 xl:w-64 2xl:w-72 cursor-pointer flex-shrink-0" onClick={() => handleStepClick(i)}>
|
||||
<div className="relative bg-white/[0.04] border border-white/[0.06] rounded-2xl md:rounded-3xl p-3 sm:p-4 md:p-6 lg:p-8 text-center transition-all duration-500 hover:bg-white/[0.08] hover:border-[#004ec4]/40 hover:-translate-y-1 h-36 sm:h-44 md:h-52 lg:h-56 xl:h-60 2xl:h-64 flex flex-col items-center justify-center"
|
||||
style={{ boxShadow: '0 8px 40px rgba(0,0,0,0.2)' }}
|
||||
>
|
||||
{/* hover 高光线 */}
|
||||
<div className="absolute top-0 left-6 right-6 md:left-8 md:right-8 h-[2px] opacity-0 group-hover:opacity-100 transition-all duration-700 rounded-full"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, #004ec4 20%, #004ec4 80%, transparent)' }}
|
||||
/>
|
||||
{/* 图标 */}
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 md:w-14 md:h-14 lg:w-16 lg:h-16 rounded-xl md:rounded-2xl bg-gradient-to-br from-[#004ec4]/25 to-[#004ec4]/5 flex items-center justify-center mx-auto mb-3 sm:mb-4 md:mb-5 group-hover:from-[#004ec4]/35 group-hover:to-[#004ec4]/15 group-hover:scale-105 group-hover:shadow-xl group-hover:shadow-[#004ec4]/15 transition-all duration-500">
|
||||
<Icon className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 lg:w-8 lg:h-8" style={{ color: '#74b0ff' }} strokeWidth={1.5} />
|
||||
</div>
|
||||
{/* 标题 */}
|
||||
<h3 className="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl font-bold text-white mb-1 md:mb-2">{item.title}</h3>
|
||||
{/* 描述 */}
|
||||
<p className="text-[10px] sm:text-xs md:text-sm text-white/45 leading-relaxed">{item.desc}</p>
|
||||
</div>
|
||||
{/* 数字 */}
|
||||
<div className="text-3xl xs:text-4xl sm:text-5xl font-black text-transparent bg-clip-text bg-gradient-to-b from-[#0f172a] to-[#334155] mb-1">{card.count}</div>
|
||||
{/* 标题 */}
|
||||
<h3 className="text-sm xs:text-base sm:text-lg font-bold text-[#0f172a] mb-3">{card.title}</h3>
|
||||
{/* 分隔线 */}
|
||||
<div className="w-8 h-px bg-gradient-to-r from-transparent via-[#043b8f]/20 to-transparent mb-3" />
|
||||
{/* 描述 */}
|
||||
<p className="text-sm text-[#64748b] leading-relaxed">{card.desc}</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
|
||||
{/* ── 流动光速时间线 ── */}
|
||||
<div className="relative max-w-2xl mx-auto mt-12 md:mt-20 mb-12 md:mb-20 px-4">
|
||||
{/* 光束外层光晕 */}
|
||||
<div className="absolute top-1/2 -translate-y-1/2 left-[8%] right-[8%] h-4 rounded-full"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, rgba(0,78,196,0.08) 15%, rgba(0,78,196,0.15) 50%, rgba(0,78,196,0.08) 85%, transparent)',
|
||||
filter: 'blur(6px)',
|
||||
}}
|
||||
/>
|
||||
{/* 光束中层 */}
|
||||
<div className="absolute top-1/2 -translate-y-1/2 left-[8%] right-[8%] h-1.5 rounded-full"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, rgba(59,130,246,0.2) 10%, rgba(96,165,250,0.5) 30%, rgba(147,197,253,0.7) 50%, rgba(96,165,250,0.5) 70%, rgba(59,130,246,0.2) 90%, transparent)',
|
||||
filter: 'blur(3px)',
|
||||
}}
|
||||
/>
|
||||
{/* 光束核心 */}
|
||||
<div className="relative h-1 rounded-full"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, rgba(59,130,246,0.4) 10%, rgba(147,197,253,0.8) 30%, #93c5fd 50%, rgba(147,197,253,0.8) 70%, rgba(59,130,246,0.4) 90%, transparent)',
|
||||
boxShadow: '0 0 12px rgba(59,130,246,0.3), 0 0 24px rgba(59,130,246,0.1)',
|
||||
}}>
|
||||
{/* 流动光点 */}
|
||||
<div className="absolute top-1/2 -translate-y-1/2 w-3 h-3 rounded-full transition-all duration-700 ease-out"
|
||||
style={{
|
||||
left: `${12 + lightPos * 25}%`,
|
||||
background: '#e0f2fe',
|
||||
boxShadow: '0 0 12px #93c5fd, 0 0 28px #60a5fa, 0 0 56px #3b82f6, 0 0 84px #1d4ed8',
|
||||
}}
|
||||
/>
|
||||
{/* 4 个节点标记 */}
|
||||
{[0, 1, 2, 3].map(n => (
|
||||
<div key={n} className="absolute top-1/2 -translate-y-1/2 w-3 h-3 rounded-full border-2 transition-all duration-500"
|
||||
style={{
|
||||
left: `${12 + n * 25}%`,
|
||||
borderColor: n <= activeStep ? '#93c5fd' : 'rgba(147,197,253,0.25)',
|
||||
background: n <= activeStep ? '#3b82f6' : 'rgba(10,22,40,0.9)',
|
||||
boxShadow: n <= activeStep ? '0 0 10px rgba(147,197,253,0.7), 0 0 20px rgba(59,130,246,0.4)' : '0 0 4px rgba(0,78,196,0.2)',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{/* 底部按钮 */}
|
||||
<ScrollReveal className="text-center">
|
||||
<Link
|
||||
to="/contact"
|
||||
className="inline-flex items-center gap-2 md:gap-3 px-6 sm:px-8 md:px-10 py-3 md:py-4 rounded-24 text-sm md:text-base font-bold text-white bg-[#1266e5cb] hover:bg-[#005ce6] transition-all duration-300 hover:shadow-2xl hover:shadow-[#004ec4]/30 hover:scale-105"
|
||||
>
|
||||
获取专属解决方案
|
||||
<ArrowRight className="w-5 h-5" />
|
||||
</Link>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
{/* ─── 7. 资质与认证 ─── */}
|
||||
<section className="py-24 px-4 bg-gradient-to-b from-white via-[#f8fafc] to-white">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<ScrollReveal className="text-center mb-16">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-8 h-[2px] rounded-full bg-[#004ec4]/40" />
|
||||
<span className="text-[11px] font-bold tracking-[0.22em] uppercase text-[#004ec4]/60">Recognition</span>
|
||||
<span className="w-8 h-[2px] rounded-full bg-[#004ec4]/40" />
|
||||
</div>
|
||||
<h2 className="text-4xl xs:text-5xl sm:text-6xl md:text-7xl font-black text-[#0f172a] tracking-tight leading-[1.1] mb-4">资质与认证</h2>
|
||||
<p className="text-[#64748b] text-base xs:text-lg font-medium">AAA级信用企业 · 高新技术企业</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
|
||||
{/* 5 个 ISO 认证证书 — 轮播图 */}
|
||||
<ScrollReveal>
|
||||
<CertificateCarousel />
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,13 +1,37 @@
|
||||
import { useParams, Link } from 'react-router-dom'
|
||||
import { ChevronDown, ArrowRight, Shield, Clock, Headphones, AlertCircle } from 'lucide-react'
|
||||
import { getProduct } from '../data/products'
|
||||
import ScrollReveal from '../components/ScrollReveal'
|
||||
import { useParams, Link } from "react-router-dom"
|
||||
import { useState, useEffect, useRef } from "react"
|
||||
import { ChevronDown, ArrowRight, Shield, Clock, Headphones, Cpu, Monitor, HardDrive, AlertCircle, GitBranch, FileStack, MessageCircleX, FileDigit, SearchCheck, Banknote, ChartBar, Bell, Layers, ScrollText, CalendarCheck, TrendingUp, Pyramid, Database, Activity, Star } from "lucide-react"
|
||||
import { getProduct } from "../data/products"
|
||||
import ScrollReveal from "../components/ScrollReveal"
|
||||
import StatNumber from "../components/StatNumber"
|
||||
import Carousel from "../components/Carousel"
|
||||
import ThemedSvg from "../components/ThemedSvg"
|
||||
|
||||
// 图标映射表 — 所有图标均来自 Lucide React (MIT License,免费商用)
|
||||
const iconMap = {
|
||||
GitBranch, FileStack, MessageCircleX, FileDigit, SearchCheck,
|
||||
Banknote, ChartBar, Bell, Layers, ScrollText, CalendarCheck,
|
||||
TrendingUp, Pyramid, Database, Activity,
|
||||
}
|
||||
|
||||
export default function ProductPage() {
|
||||
const { slug } = useParams()
|
||||
const product = getProduct(slug)
|
||||
const [activeStep, setActiveStep] = useState(0)
|
||||
const [lightPos, setLightPos] = useState(0)
|
||||
const timerRef = useRef(null)
|
||||
|
||||
|
||||
const handleStepClick = (i) => {
|
||||
if (timerRef.current) clearTimeout(timerRef.current)
|
||||
setLightPos(i)
|
||||
timerRef.current = setTimeout(() => {
|
||||
setActiveStep(i)
|
||||
}, 700)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
return () => { if (timerRef.current) clearTimeout(timerRef.current) }
|
||||
}, [])
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
@@ -21,118 +45,268 @@ export default function ProductPage() {
|
||||
)
|
||||
}
|
||||
|
||||
// 将 hex 主题色转为 RGB 分量,用于 rgba() 可变透明度
|
||||
const hex = product.themeColor.replace('#', '')
|
||||
const r = parseInt(hex.slice(0, 2), 16)
|
||||
const g = parseInt(hex.slice(2, 4), 16)
|
||||
const b = parseInt(hex.slice(4, 6), 16)
|
||||
|
||||
// const Icon = product.icon
|
||||
// const otherProducts = products.filter(p => p.slug !== slug)
|
||||
|
||||
return (
|
||||
<main className="bg-white">
|
||||
<main
|
||||
className="bg-white"
|
||||
style={{
|
||||
'--theme': product.themeColor,
|
||||
'--theme-r': r,
|
||||
'--theme-g': g,
|
||||
'--theme-b': b,
|
||||
}}
|
||||
>
|
||||
{/* ── Hero ── */}
|
||||
<div className="relative -mt-[70px]">
|
||||
<section className="relative py-32 md:py-40 text-white overflow-hidden">
|
||||
{/* Background image */}
|
||||
{product.heroImage && (
|
||||
<div className="absolute inset-0">
|
||||
<img src={product.heroImage} alt="" className="w-full h-full object-cover" />
|
||||
<section className="relative overflow-hidden" style={{ backgroundColor: product.themeColor }}>
|
||||
{/* Desktop: grid 布局 — 统一宽度/高度/间距 */}
|
||||
<div className="hidden md:grid grid-cols-2 gap-12 lg:gap-20 xl:gap-28 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 min-h-[920px] items-center">
|
||||
{/* Image - left */}
|
||||
<div className="flex items-center justify-center">
|
||||
{product.heroImage && (
|
||||
<img src={product.heroImage} alt="" className="w-full h-auto object-contain" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/* Black overlay */}
|
||||
<div className="absolute inset-0 bg-black/50" />
|
||||
{/* Content - right */}
|
||||
<div className="flex flex-col items-center justify-center gap-5 md:gap-6">
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-extrabold text-center tracking-tight leading-[1.1] text-white hero-product-title">
|
||||
{product.name}
|
||||
</h1>
|
||||
<p className="text-lg sm:text-xl md:text-2xl lg:text-3xl text-center leading-relaxed text-white/80 hero-product-slogan">
|
||||
{product.slogan}
|
||||
</p>
|
||||
{product.stats && (
|
||||
<div className="grid grid-flow-col auto-cols-fr gap-5 md:gap-6 w-full mt-6 md:mt-8">
|
||||
{product.stats.map((s, i) => (
|
||||
<div key={i} className="rounded-2xl p-4 text-center border border-white/20 bg-white/10">
|
||||
<div className="text-2xl md:text-3xl font-extrabold tracking-tight text-white">
|
||||
<StatNumber target={s.num} suffix={s.suffix} />
|
||||
</div>
|
||||
<div className="text-xs text-white/60 mt-1.5 font-medium">{s.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-4xl mx-auto px-6 text-center pt-32">
|
||||
|
||||
|
||||
<h1 className="text-4xl md:text-7xl font-extrabold mb-5 tracking-tight leading-[1.1] text-white hero-product-title">
|
||||
{product.name}
|
||||
</h1>
|
||||
<p className="text-2xl md:text-3xl mb-6 max-w-xl mx-auto leading-relaxed hero-product-slogan">
|
||||
{product.slogan}
|
||||
</p>
|
||||
|
||||
{/* Stats */}
|
||||
{product.stats && (
|
||||
<div className="flex justify-center mt-14 rounded-2xl border border-white/10 overflow-hidden max-w-xl mx-auto"
|
||||
style={{ backgroundColor: 'rgba(255,255,255,0.08)', backdropFilter: 'blur(8px)' }}>
|
||||
{product.stats.map((s, i) => (
|
||||
<div key={i} className={`flex flex-col items-center justify-center px-6 md:px-10 py-5 ${i < product.stats.length - 1 ? 'border-r border-white/10' : ''}`}>
|
||||
<div className="text-2xl md:text-3xl font-extrabold tracking-tight text-white">{s.num}</div>
|
||||
<div className="text-xs text-white/50 mt-2 font-medium">{s.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{/* Mobile: stacked layout */}
|
||||
<div className="md:hidden flex flex-col items-center px-6 pt-32 pb-16">
|
||||
{product.heroImage && (
|
||||
<img src={product.heroImage} alt="" className={`w-4/5 max-w-xs h-auto object-contain mb-8 sm:mb-10 ${product.heroSize === 'small' ? 'max-h-[150px]' : 'max-h-[200px]'}`} />
|
||||
)}
|
||||
<div className="text-center w-full">
|
||||
<span className="inline-block px-3 sm:px-4 py-1 sm:py-1.5 rounded-full text-[10px] sm:text-xs font-bold tracking-wider uppercase mb-4 sm:mb-5"
|
||||
style={{ backgroundColor: product.themeColor + '18', color: product.themeColor }}>
|
||||
智慧教育解决方案
|
||||
</span>
|
||||
<h1 className="text-2xl xs:text-3xl sm:text-4xl font-extrabold mb-3 sm:mb-4 tracking-tight leading-[1.1] text-white hero-product-title">
|
||||
{product.name}
|
||||
</h1>
|
||||
<p className="text-base xs:text-lg sm:text-xl mb-5 sm:mb-6 leading-relaxed text-white/80 hero-product-slogan">
|
||||
{product.slogan}
|
||||
</p>
|
||||
{product.stats && (
|
||||
<div className="grid grid-cols-3 gap-2 sm:gap-3 mt-3 sm:mt-4">
|
||||
{product.stats.map((s, i) => (
|
||||
<div key={i} className="rounded-xl sm:rounded-2xl p-2 sm:p-3 text-center border border-white/20 bg-white/10">
|
||||
<div className="text-lg xs:text-xl sm:text-2xl font-extrabold tracking-tight text-white">
|
||||
<StatNumber target={s.num} suffix={s.suffix} />
|
||||
</div>
|
||||
<div className="text-[10px] xs:text-[11px] sm:text-xs text-white/60 mt-1 font-medium">{s.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* ── Brief ── */}
|
||||
<section className="py-20 px-6 bg-white">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
{/* ── Brief / 产品简介 ── */}
|
||||
<section className="py-16 md:py-20 px-6 bg-[#f8fafc]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<ScrollReveal>
|
||||
<div className="relative bg-[#f8fafc] rounded-3xl p-10 md:p-14 overflow-hidden">
|
||||
{/* Floating decorative shapes */}
|
||||
<div className="absolute -top-6 -right-6 w-24 h-24 rounded-full bg-[#043b8f]" />
|
||||
<div className="absolute -bottom-8 -left-8 w-20 h-20 rounded-2xl rotate-12 bg-[#043b8f]" />
|
||||
<div className="absolute top-1/2 -right-4 w-8 h-8 rounded-full border-2 border-[#043b8f]" />
|
||||
{/* ═══ 折角卡片 ═══ */}
|
||||
<div className="relative bg-white rounded-2xl shadow-[0_4px_32px_-8px_rgba(0,0,0,0.08),0_0_0_1px_rgba(0,0,0,0.04)]">
|
||||
|
||||
<p className="text-[#334155] text-lg md:text-xl leading-loose relative z-10">
|
||||
{product.brief}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{product.tags && (
|
||||
<div className="flex flex-wrap items-center justify-center gap-3 mt-10">
|
||||
{product.tags.map((tag, i) => (
|
||||
<span key={i}
|
||||
className="relative px-6 py-2 text-sm font-bold text-white transition-all duration-200 hover:scale-105 hover:-translate-y-0.5"
|
||||
style={{ backgroundColor: '#043b8f' }}>
|
||||
<span className="relative z-10">{tag}</span>
|
||||
<svg className="absolute -bottom-2 left-0 w-full h-2 text-white/20" viewBox="0 0 100 8" preserveAspectRatio="none">
|
||||
<path d="M0 0 L35 8 L65 8 L100 0" fill="currentColor" />
|
||||
</svg>
|
||||
<span className="absolute top-1/2 -translate-y-1/2 -left-2 w-1 h-4 rounded-full" style={{ backgroundColor: '#043b8f' }} />
|
||||
</span>
|
||||
))}
|
||||
{/* ── 右上折角 ── */}
|
||||
<div className="absolute top-0 right-0 w-[100px] h-[100px] md:w-[130px] md:h-[130px] overflow-hidden rounded-tr-2xl z-20 pointer-events-none">
|
||||
{/* 折角在卡片上投下的阴影 */}
|
||||
<div className="absolute top-0 right-0 w-full h-full"
|
||||
style={{
|
||||
clipPath: 'polygon(100% 0, 100% 100%, 0 0)',
|
||||
background: 'rgba(0,0,0,0.1)',
|
||||
filter: 'blur(4px)',
|
||||
transform: 'translate(2px, 2px)',
|
||||
}}
|
||||
/>
|
||||
{/* 折角主体 — 品牌色渐变,模拟纸张背面 */}
|
||||
<div className="absolute top-0 right-0 w-full h-full"
|
||||
style={{
|
||||
clipPath: 'polygon(100% 0, 100% 100%, 0 0)',
|
||||
background: `linear-gradient(225deg, ${product.themeColor} 0%, rgba(${r},${g},${b},0.78) 100%)`,
|
||||
}}
|
||||
/>
|
||||
{/* 折角内面高光 */}
|
||||
<div className="absolute top-0 right-0 w-full h-full"
|
||||
style={{
|
||||
clipPath: 'polygon(100% 0, 100% 100%, 0 0)',
|
||||
background: `linear-gradient(225deg, rgba(255,255,255,0.28) 0%, transparent 50%)`,
|
||||
}}
|
||||
/>
|
||||
{/* 折痕线 */}
|
||||
<div className="absolute top-0 right-0 w-full h-full"
|
||||
style={{
|
||||
background: `linear-gradient(225deg, transparent 37%, rgba(0,0,0,0.07) 39%, rgba(0,0,0,0.03) 41%, transparent 43%)`,
|
||||
}}
|
||||
/>
|
||||
{/* 图标 */}
|
||||
<Star className="absolute w-[16px] h-[16px] md:w-[20px] md:h-[20px] text-yellow-400 fill-yellow-400 drop-shadow-sm"
|
||||
style={{ top: '18px', right: '14px', transform: 'rotate(45deg)' }}
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── 内容区 ── */}
|
||||
<div className="relative p-6 sm:p-8 md:p-10 lg:p-14">
|
||||
{/* 顶部装饰线 + 标签 */}
|
||||
<div className="flex items-center gap-3 mb-4 md:mb-5">
|
||||
<span className="w-8 md:w-10 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
<span className="text-xs sm:text-sm md:text-base font-bold tracking-[0.22em] uppercase text-[var(--theme)]/60">
|
||||
Brief
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 标题 */}
|
||||
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1] mb-4 md:mb-6">
|
||||
产品简介
|
||||
</h2>
|
||||
|
||||
{/* 正文 */}
|
||||
<p className="text-[#334155] text-sm sm:text-base md:text-lg lg:text-xl leading-[1.7] md:leading-[1.9] font-medium">
|
||||
{product.brief}
|
||||
</p>
|
||||
|
||||
{/* ═══ 底部标签 ═══ */}
|
||||
{product.tags && (
|
||||
<div className="flex flex-wrap items-center justify-center gap-3 mt-7 pt-7 border-t border-gray-100">
|
||||
{product.tags.map((tag, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="px-3 sm:px-5 py-1.5 sm:py-2 text-sm sm:text-base md:text-lg font-bold rounded-lg border transition-all duration-300 hover:-translate-y-1 cursor-default"
|
||||
style={{
|
||||
color: product.themeColor,
|
||||
borderColor: `rgba(${r},${g},${b},0.25)`,
|
||||
backgroundColor: `rgba(${r},${g},${b},0.04)`,
|
||||
}}
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Pain Points ── */}
|
||||
{product.painPoints && product.painPoints.length > 0 && (
|
||||
<section className="py-24 px-6 bg-[#fafbfc]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<ScrollReveal className="mb-14 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">Pain Points</span>
|
||||
</div>
|
||||
<h2 className="text-2xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
{product.painPointsTitle || `${product.name}解决的核心问题`}
|
||||
</h2>
|
||||
<p className="text-[#475569] text-lg md:text-xl mt-6 max-w-xl leading-relaxed">深入理解管理难题,提供经过实战验证的解决方案</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
<div className="space-y-5">
|
||||
<section className="py-24 md:py-32 px-6 bg-gradient-to-b from-white via-[#fafbfc] to-white overflow-hidden">
|
||||
{/* ── 标题区 ── */}
|
||||
<div className="text-center mb-16 md:mb-20">
|
||||
<span className="inline-flex items-center gap-2 text-sm font-bold tracking-[0.2em] uppercase text-[var(--theme)] mb-4">
|
||||
<span className="w-8 h-px bg-[var(--theme)]/40" />
|
||||
Pain Points & Solutions
|
||||
<span className="w-8 h-px bg-[var(--theme)]/40" />
|
||||
</span>
|
||||
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.3] md:leading-[1.8] mb-3 md:mb-4 whitespace-pre-line">
|
||||
{product.painPointsTitle || `${product.name}\n解决的核心问题`}
|
||||
</h2>
|
||||
<p className="mt-3 md:mt-4 text-[#64748b] text-sm sm:text-base md:text-lg max-w-2xl mx-auto">
|
||||
直击业务痛点,提供经过实战验证的完整解决方案
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
{/* ── 响应式布局:移动端堆叠,md+ 左右对半 ── */}
|
||||
<div className="flex flex-col gap-16 md:gap-24 lg:gap-32">
|
||||
{product.painPoints.map((item, i) => (
|
||||
<ScrollReveal key={i} delay={i * 0.08}>
|
||||
<div className="relative bg-white rounded-2xl p-10 border border-gray-100 hover:shadow-lg hover:shadow-gray-200/50 transition-all duration-300 group h-full">
|
||||
<div className="absolute top-0 left-0 right-0 h-1 rounded-t-2 bg-[#043b8f] opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
{/* Pain point */}
|
||||
<div className="flex items-start gap-3 mb-5 pb-5 border-b border-dashed border-gray-200">
|
||||
<div className="shrink-0 w-9 h-9 rounded-full bg-red-50 flex items-center justify-center">
|
||||
<AlertCircle className="w-5 h-5 text-red-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-[#0f172a] leading-relaxed">{item.title}</h3>
|
||||
</div>
|
||||
{/* Solution */}
|
||||
<div className="ml-11 pl-5 border-l-2 border-[#043b8f] bg-[#043b8f]/[0.03] rounded-r-lg py-4 pr-4">
|
||||
<span className="inline-block text-sm font-semibold text-white bg-[#043b8f] rounded px-3 py-1.5 mb-3">解决方案</span>
|
||||
<p className="text-[#334155] text-xl leading-[1.9]">{item.desc}</p>
|
||||
<div key={i} className={`flex flex-col md:flex-row items-center gap-8 md:gap-12 lg:gap-20 ${i % 2 === 1 ? 'md:flex-row-reverse' : ''}`}>
|
||||
{/* ═══ 配图 ═══ */}
|
||||
<div className="w-full md:w-1/2 flex justify-center">
|
||||
<div className="relative w-full max-w-[320px] sm:max-w-[360px] md:w-4/5 lg:w-3/5">
|
||||
{item.url ? (
|
||||
item.url.endsWith('.svg') ? (
|
||||
<ThemedSvg
|
||||
url={item.url}
|
||||
color={product.themeColor}
|
||||
className="relative z-10 w-full mx-auto [&>svg]:w-full [&>svg]:h-auto"
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
src={item.url}
|
||||
alt={item.title}
|
||||
className="relative z-10 w-full mx-auto"
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<div className="relative z-10 w-full mx-auto aspect-[4/3] rounded-2xl bg-gray-100 flex items-center justify-center">
|
||||
<span className="text-gray-400 text-sm">暂无配图</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
{/* ═══ 文字 ═══ */}
|
||||
<div className="w-full md:w-1/2">
|
||||
<div className="space-y-6 md:space-y-8 lg:space-y-10">
|
||||
{/* ── 痛点书签卡 ── */}
|
||||
<div className="relative">
|
||||
<div className="relative bg-white rounded-2xl shadow-[0_6px_28px_-8px_rgba(239,68,68,0.15)] border border-red-200 overflow-visible">
|
||||
<div className="absolute -top-4 sm:-top-5 md:-top-6 left-4 sm:left-6 md:left-8 px-3 sm:px-4 md:px-5 py-1 sm:py-1.5 md:py-2 rounded-t-lg md:rounded-t-xl bg-red-400 shadow-[0_-2px_8px_rgba(239,68,68,0.2)]">
|
||||
<span className="text-xs sm:text-sm md:text-base font-black tracking-[0.1em] uppercase text-white">痛点</span>
|
||||
</div>
|
||||
<div className="absolute left-0 top-0 bottom-0 w-1.5 bg-red-400 rounded-l-2xl" />
|
||||
<div className="pl-6 sm:pl-8 md:pl-10 pr-4 sm:pr-6 md:pr-8 py-4 sm:py-5 md:py-8 pt-8 sm:pt-10 md:pt-12">
|
||||
<p className="text-[#1e293b] text-sm sm:text-base md:text-lg leading-[1.7] md:leading-[1.9] font-bold">
|
||||
{item.title}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── 解决方案书签卡 ── */}
|
||||
<div className="relative">
|
||||
<div className="relative bg-white rounded-2xl shadow-[0_6px_28px_-8px_rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.15)] border overflow-visible"
|
||||
style={{ borderColor: `${product.themeColor}30` }}>
|
||||
<div className="absolute -top-4 sm:-top-5 md:-top-6 left-4 sm:left-6 md:left-8 px-3 sm:px-4 md:px-5 py-1 sm:py-1.5 md:py-2 rounded-t-lg md:rounded-t-xl shadow-[0_-2px_8px_rgba(0,0,0,0.1)]"
|
||||
style={{ backgroundColor: product.themeColor }}>
|
||||
<span className="text-xs sm:text-sm md:text-base font-black tracking-[0.1em] uppercase text-white">解决方案</span>
|
||||
</div>
|
||||
<div className="absolute left-0 top-0 bottom-0 w-1.5 rounded-l-2xl"
|
||||
style={{ backgroundColor: product.themeColor }} />
|
||||
<div className="pl-6 sm:pl-8 md:pl-10 pr-4 sm:pr-6 md:pr-8 py-4 sm:py-5 md:py-8 pt-8 sm:pt-10 md:pt-12">
|
||||
<p className="text-[#1e293b] text-sm sm:text-base md:text-lg leading-[1.7] md:leading-[1.9] font-bold">
|
||||
{item.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,23 +314,24 @@ export default function ProductPage() {
|
||||
)}
|
||||
|
||||
{/* ── Core Features ── */}
|
||||
<section className="py-24 px-6 bg-[#fafbfc]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<section className="py-24 px-6 bg-white">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<ScrollReveal className="mb-16 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">Core Features</span>
|
||||
<span className="w-8 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
<span className="text-[11px] font-bold tracking-[0.22em] uppercase text-[var(--theme)]/60">Core Features</span>
|
||||
<span className="w-8 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
</div>
|
||||
<h2 className="text-3xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
核心功能
|
||||
</h2>
|
||||
{product.target && (
|
||||
<div className="mt-5 flex flex-col items-center gap-3">
|
||||
<span className="text-lg text-[#0f172a] font-bold">适用对象:</span>
|
||||
<div className="flex flex-wrap justify-center gap-3">
|
||||
<div className="mt-6 flex flex-col items-center gap-4">
|
||||
<span className="text-sm sm:text-base md:text-lg font-extrabold text-[#0f172a]">适用对象</span>
|
||||
<div className="flex flex-wrap justify-center gap-2 md:gap-3">
|
||||
{product.target.split('、').map((t, i) => (
|
||||
<span key={i} className="px-4 py-1.5 rounded-lg text-sm font-bold text-[#043b8f] border border-[#043b8f]/30">{t.trim()}</span>
|
||||
<span key={i} className="px-3 sm:px-5 py-1.5 sm:py-2 rounded-lg text-sm sm:text-base md:text-lg font-bold text-[var(--theme)] border border-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.3)] bg-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.03)]">{t.trim()}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -164,22 +339,222 @@ export default function ProductPage() {
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* ── 桌面端:每个功能一行卡片(左文字 + 右截图) ── */}
|
||||
<div className="hidden lg:flex flex-col gap-6">
|
||||
{product.features.map((f, i) => (
|
||||
<ScrollReveal key={i} delay={i * 0.05}>
|
||||
<div className="relative bg-white rounded-2xl p-8 md:p-10 h-full border border-gray-100 hover:shadow-xl hover:shadow-[#043b8f]/5 transition-all duration-500 group overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
||||
style={{ background: `linear-gradient(90deg, transparent, ${product.themeColor}, transparent)` }} />
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-20 h-20 border border-[#043b8f]/[0.06] rounded-tr-3xl" />
|
||||
<div className={`group relative flex rounded-2xl bg-white border border-gray-100 overflow-hidden transition-all duration-500 hover:border-[var(--theme)]/20 hover:shadow-[0_8px_32px_-8px_rgba(0,0,0,0.10)] shadow-[0_1px_8px_-2px_rgba(0,0,0,0.05)] ${i % 2 === 1 ? 'flex-row-reverse' : ''}`}>
|
||||
{/* hover 边框光 */}
|
||||
<div className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-transparent group-hover:ring-[var(--theme)]/10 transition-all duration-700 pointer-events-none z-10" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<span className="flex items-center justify-center w-8 h-8 rounded-md bg-[#043b8f]/[0.06] text-xs font-black text-[#043b8f]">0{i + 1}</span>
|
||||
<div className="h-px flex-1 bg-gradient-to-r from-[#043b8f]/10 to-transparent" />
|
||||
{/* 文字区 */}
|
||||
<div className={`relative w-1/2 flex flex-col justify-center p-12 xl:p-14 ${i % 2 === 1 ? 'pl-10 xl:pl-12' : 'pr-10 xl:pr-12'}`}>
|
||||
{/* 序号 + 标签 */}
|
||||
<div className="flex items-center gap-3 mb-5">
|
||||
<span className="shrink-0 flex items-center justify-center w-10 h-10 rounded-xl text-white"
|
||||
style={{ backgroundColor: product.themeColor, boxShadow: `0 4px 12px ${product.themeColor}30` }}>
|
||||
{f.icon && iconMap[f.icon] ? (() => { const Icon = iconMap[f.icon]; return <Icon className="w-5 h-5" strokeWidth={2} /> })() : <span className="text-sm font-black">{String(i + 1).padStart(2, '0')}</span>}
|
||||
</span>
|
||||
<div>
|
||||
<span className="text-[10px] font-bold tracking-[0.2em] uppercase text-[var(--theme)]/50">Core Feature</span>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#0f172a] mb-3">{f.title}</h3>
|
||||
<p className="text-[#64748b] text-lg leading-relaxed">{f.desc}</p>
|
||||
{/* 标题 */}
|
||||
<h3 className="text-2xl lg:text-[1.65rem] font-extrabold text-[#0f172a] leading-[1.2] mb-4 tracking-tight">
|
||||
{f.title}
|
||||
</h3>
|
||||
{/* 分隔线 */}
|
||||
<div className="w-10 h-[3px] rounded-full mb-4" style={{ backgroundColor: product.themeColor, opacity: 0.25 }} />
|
||||
{/* 描述 */}
|
||||
<p className="text-[#475569] text-base leading-[1.8] max-w-md">
|
||||
{f.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 截图区 */}
|
||||
<div className="relative w-1/2 flex items-center justify-center p-6 lg:p-8 bg-[#f8fafc]">
|
||||
{f.image ? (
|
||||
<div className="relative w-full">
|
||||
{f.small ? (
|
||||
/* 手机模型外壳 */
|
||||
<div className="relative mx-auto w-[140px]">
|
||||
<div className="relative bg-[#1a1a2e] rounded-[18px] p-[3px] shadow-[0_12px_36px_-10px_rgba(0,0,0,0.25)] transition-all duration-500 group-hover:shadow-[0_18px_44px_-12px_rgba(0,0,0,0.30)] group-hover:-translate-y-1">
|
||||
<div className="flex justify-center pt-0.5">
|
||||
<div className="flex items-center gap-0.5">
|
||||
<span className="w-1 h-1 rounded-full bg-[#0f0f1a]" />
|
||||
<span className="w-4 h-0.5 bg-[#0f0f1a] rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-0.5 rounded-[6px] overflow-hidden bg-white">
|
||||
<img src={f.image} alt={f.title} className="w-full h-auto object-contain max-h-[280px]" />
|
||||
</div>
|
||||
<div className="flex justify-center pt-1.5 pb-0.5">
|
||||
<div className="w-5 h-[2px] bg-white/15 rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
/* 浏览器窗口效果 */
|
||||
<div className="rounded-lg overflow-hidden shadow-[0_6px_24px_-6px_rgba(0,0,0,0.10)] ring-1 ring-black/5 transition-all duration-500 group-hover:shadow-[0_10px_32px_-10px_rgba(0,0,0,0.15)] group-hover:-translate-y-1 w-4/5 mx-auto">
|
||||
<div className="flex items-center gap-1 px-2.5 py-1.5 bg-[#1e293b]">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-red-400/80" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400/80" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400/80" />
|
||||
<span className="ml-2 text-[8px] text-white/30 font-mono truncate">{f.title}</span>
|
||||
</div>
|
||||
<img src={f.image} alt={f.title} className="w-full h-auto" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-lg overflow-hidden ring-1 ring-gray-200 w-4/5 mx-auto">
|
||||
<div className="flex items-center gap-0.5 px-2 py-1.5 bg-[#1e293b]">
|
||||
<span className="w-1 h-1 rounded-full bg-red-400/60" />
|
||||
<span className="w-1 h-1 rounded-full bg-amber-400/60" />
|
||||
<span className="w-1 h-1 rounded-full bg-emerald-400/60" />
|
||||
</div>
|
||||
<div className="aspect-[4/3] bg-white border border-dashed border-gray-200 flex items-center justify-center">
|
||||
<span className="text-gray-300 text-sm">暂无截图</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* ── 移动端:紧凑卡片 ── */}
|
||||
<div className="lg:hidden flex flex-col gap-4">
|
||||
{product.features.map((f, i) => (
|
||||
<ScrollReveal key={i} delay={i * 0.05}>
|
||||
<div className="bg-white rounded-2xl border border-gray-100 overflow-hidden shadow-[0_1px_8px_-2px_rgba(0,0,0,0.05)]">
|
||||
<div className="p-5">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<span className="shrink-0 flex items-center justify-center w-8 h-8 rounded-lg text-white"
|
||||
style={{ backgroundColor: product.themeColor }}>
|
||||
{f.icon && iconMap[f.icon] ? (() => { const Icon = iconMap[f.icon]; return <Icon className="w-4 h-4" strokeWidth={2} /> })() : <span className="text-xs font-black">{String(i + 1).padStart(2, '0')}</span>}
|
||||
</span>
|
||||
<span className="text-[10px] font-bold tracking-[0.15em] uppercase text-[var(--theme)]/50">核心功能</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-extrabold text-[#0f172a] mb-2 leading-snug">{f.title}</h3>
|
||||
<p className="text-[#475569] text-sm leading-relaxed">{f.desc}</p>
|
||||
</div>
|
||||
{f.image && (
|
||||
<div className="mx-3 mb-3 bg-[#f8fafc] rounded-xl p-3">
|
||||
{f.small ? (
|
||||
<div className="relative mx-auto w-[130px]">
|
||||
<div className="relative bg-[#1a1a2e] rounded-[16px] p-[3px] shadow-[0_12px_36px_-10px_rgba(0,0,0,0.25)]">
|
||||
<div className="flex justify-center pt-1">
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="w-1 h-1 rounded-full bg-[#0f0f1a]" />
|
||||
<span className="w-5 h-0.5 bg-[#0f0f1a] rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-0.5 rounded-[8px] overflow-hidden bg-white">
|
||||
<img src={f.image} alt={f.title} className="w-full h-auto object-contain max-h-[240px]" />
|
||||
</div>
|
||||
<div className="flex justify-center pt-1 pb-0.5">
|
||||
<div className="w-4 h-[2px] bg-white/15 rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-lg overflow-hidden shadow-[0_4px_16px_-4px_rgba(0,0,0,0.08)] ring-1 ring-black/5 w-4/5 mx-auto">
|
||||
<div className="flex items-center gap-0.5 px-2 py-1.5 bg-[#1e293b]">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-red-400/80" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400/80" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400/80" />
|
||||
<span className="ml-1.5 text-[7px] text-white/30 font-mono truncate">{f.title}</span>
|
||||
</div>
|
||||
<img src={f.image} alt={f.title} className="w-full h-auto" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Product Showcase ── */}
|
||||
{product.screenshots && product.screenshots.length > 0 && (
|
||||
<section className="py-24 px-6 bg-[#fafbfc]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<ScrollReveal className="mb-16 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-lg bg-[var(--theme)]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[var(--theme)]">Product Showcase</span>
|
||||
</div>
|
||||
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
产品展示
|
||||
</h2>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<Carousel images={product.screenshots} themeColor={product.themeColor} />
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* ── 国产化支持 ── */}
|
||||
<section className="py-24 px-6 bg-white">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<ScrollReveal className="mb-16 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-8 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
<span className="text-[11px] font-bold tracking-[0.22em] uppercase text-[var(--theme)]/60">Localization</span>
|
||||
<span className="w-8 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
</div>
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
国产化支持
|
||||
</h2>
|
||||
<p className="mt-3 md:mt-4 text-[#64748b] text-sm sm:text-base md:text-lg max-w-2xl mx-auto">
|
||||
全面适配国产信创生态,赋能教育信息化自主可控
|
||||
</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{[
|
||||
{ icon: Cpu, title: '国产芯片兼容', desc: '全面适配鲲鹏、飞腾、龙芯等国产CPU架构,从底层保障系统安全可控' },
|
||||
{ icon: Monitor, title: '国产操作系统', desc: '完美运行于统信UOS、麒麟等国产操作系统,桌面端与服务端全覆盖' },
|
||||
{ icon: HardDrive, title: '国产数据库', desc: '支持达梦、人大金仓、GaussDB等国产数据库,数据存储自主可靠' },
|
||||
].map((item, i) => (
|
||||
<ScrollReveal key={i} delay={i * 0.08}>
|
||||
<div className="group relative bg-white rounded-xl md:rounded-2xl p-6 sm:p-8 md:p-10 lg:p-12 h-full border border-gray-100 shadow-[0_2px_16px_-6px_rgba(0,0,0,0.06)] hover:shadow-[0_12px_40px_-12px_rgba(0,0,0,0.12)] transition-all duration-500 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-1 transition-all duration-500"
|
||||
style={{ background: `linear-gradient(90deg, transparent, ${product.themeColor}, transparent)`, opacity: 0 }}
|
||||
/>
|
||||
<div className="absolute bottom-0 left-0 right-0 h-[3px] transition-all duration-500"
|
||||
style={{
|
||||
background: `linear-gradient(90deg, transparent, ${product.themeColor}60, transparent)`,
|
||||
opacity: 0.5,
|
||||
}}
|
||||
/>
|
||||
<div className="relative z-10 flex flex-col items-center text-center">
|
||||
<div className="mb-5 md:mb-7">
|
||||
<div className="w-16 h-16 sm:w-20 sm:h-20 md:w-[88px] md:h-[88px] rounded-2xl flex items-center justify-center transition-all duration-500 group-hover:scale-110 group-hover:shadow-lg"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${product.themeColor}12, ${product.themeColor}08)`,
|
||||
border: `1px solid ${product.themeColor}20`,
|
||||
boxShadow: `0 4px 20px ${product.themeColor}15`,
|
||||
}}
|
||||
>
|
||||
<item.icon className="w-8 h-8 sm:w-9 sm:h-9 md:w-10 md:h-10 transition-all duration-500 group-hover:scale-110" strokeWidth={1.5} style={{ color: product.themeColor }} />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg sm:text-xl md:text-2xl font-extrabold text-[#0f172a] mb-2 md:mb-3 tracking-tight">
|
||||
{item.title}
|
||||
</h3>
|
||||
<div className="w-8 md:w-10 h-[3px] rounded-full mb-3 md:mb-4" style={{ backgroundColor: product.themeColor, opacity: 0.3 }} />
|
||||
<p className="text-[#64748b] text-sm sm:text-base md:text-lg leading-relaxed">
|
||||
{item.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
@@ -189,47 +564,116 @@ export default function ProductPage() {
|
||||
</section>
|
||||
|
||||
{/* ── Advantages ── */}
|
||||
<section className="py-24 px-6 bg-white">
|
||||
<section className="py-24 md:py-32 px-6 bg-[#f8fafc]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<ScrollReveal className="mb-16 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">Why Choose Us</span>
|
||||
<span className="w-8 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
<span className="text-[11px] font-bold tracking-[0.22em] uppercase text-[var(--theme)]/60">Why Choose Us</span>
|
||||
<span className="w-8 h-[2px] rounded-full bg-[var(--theme)]/40" />
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
<h2 className="text-3xl xs:text-4xl sm:text-5xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
为什么选择我们
|
||||
</h2>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
||||
{[
|
||||
{ icon: Shield, title: '安全可靠', desc: '等保三级认证,银行级加密存储,多机房容灾备份' },
|
||||
{ icon: Clock, title: '快速部署', desc: 'SaaS 即开即用,私有化部署最快 3 天交付上线' },
|
||||
{ icon: Headphones, title: '专属服务', desc: '7×24 小时响应,专属客户经理全程陪伴' },
|
||||
].map((item, i) => (
|
||||
<ScrollReveal key={i} delay={i * 0.08}>
|
||||
<div className="relative bg-[#fafbfc] rounded-2xl p-8 md:p-10 h-full border border-gray-100 hover:shadow-xl hover:shadow-[#043b8f]/5 transition-all duration-500 group overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
||||
style={{ background: `linear-gradient(90deg, transparent, ${product.themeColor}, transparent)` }} />
|
||||
<div className="absolute top-0 right-0 w-28 h-28 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<div className="absolute bottom-0 left-0 w-16 h-16 border border-[#043b8f]/[0.06] rounded-tr-3xl" />
|
||||
<div className="group relative bg-white rounded-xl md:rounded-2xl p-6 sm:p-8 md:p-10 lg:p-12 h-full border border-gray-100 shadow-[0_2px_16px_-6px_rgba(0,0,0,0.06)] hover:shadow-[0_12px_40px_-12px_rgba(0,0,0,0.12)] transition-all duration-500 overflow-hidden cursor-pointer" onClick={() => handleStepClick(i)}>
|
||||
{/* 顶部品牌色条 — hover 时滑入 */}
|
||||
<div className="absolute top-0 left-0 right-0 h-1 transition-all duration-500"
|
||||
style={{ background: `linear-gradient(90deg, transparent, ${product.themeColor}, transparent)`, opacity: 0 }}
|
||||
/>
|
||||
{/* 底部品牌色条 — 始终可见 */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-[3px] transition-all duration-500"
|
||||
style={{
|
||||
background: `linear-gradient(90deg, transparent, ${product.themeColor}60, transparent)`,
|
||||
opacity: 0.5,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center gap-3 mb-5">
|
||||
<div className="w-11 h-11 rounded-xl flex items-center justify-center bg-[#043b8f]/[0.06] border border-[#043b8f]/10">
|
||||
<item.icon className="w-5 h-5" style={{ color: '#043b8f' }} />
|
||||
<div className="relative z-10 flex flex-col items-center text-center">
|
||||
{/* 图标 — 大圆形容器 */}
|
||||
<div className="mb-5 md:mb-7">
|
||||
<div className="w-16 h-16 sm:w-20 sm:h-20 md:w-[88px] md:h-[88px] rounded-2xl flex items-center justify-center transition-all duration-500 group-hover:scale-110 group-hover:shadow-lg"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${product.themeColor}12, ${product.themeColor}08)`,
|
||||
border: `1px solid ${product.themeColor}20`,
|
||||
boxShadow: `0 4px 20px ${product.themeColor}15`,
|
||||
}}
|
||||
>
|
||||
<item.icon className="w-8 h-8 sm:w-9 sm:h-9 md:w-10 md:h-10 transition-all duration-500 group-hover:scale-110" strokeWidth={1.5} style={{ color: product.themeColor }} />
|
||||
</div>
|
||||
<div className="h-px flex-1 bg-gradient-to-r from-[#043b8f]/10 to-transparent" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#0f172a] mb-3">{item.title}</h3>
|
||||
<p className="text-[#64748b] text-lg leading-relaxed">{item.desc}</p>
|
||||
|
||||
{/* 标题 */}
|
||||
<h3 className="text-lg sm:text-xl md:text-2xl font-extrabold text-[#0f172a] mb-2 md:mb-3 tracking-tight">
|
||||
{item.title}
|
||||
</h3>
|
||||
|
||||
{/* 分隔线 */}
|
||||
<div className="w-8 md:w-10 h-[3px] rounded-full mb-3 md:mb-4" style={{ backgroundColor: product.themeColor, opacity: 0.3 }} />
|
||||
|
||||
{/* 描述 */}
|
||||
<p className="text-[#64748b] text-sm sm:text-base md:text-lg leading-relaxed">
|
||||
{item.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* ── 流动光速时间线 ── */}
|
||||
<div className="relative max-w-md mx-auto mt-8 md:mt-24 mb-4">
|
||||
{/* 光束外层光晕 */}
|
||||
<div className="absolute top-1/2 -translate-y-1/2 left-[8%] right-[8%] h-4 rounded-full"
|
||||
style={{
|
||||
background: `linear-gradient(90deg, transparent, ${product.themeColor}15, ${product.themeColor}25, ${product.themeColor}15, transparent)`,
|
||||
filter: 'blur(6px)',
|
||||
}}
|
||||
/>
|
||||
{/* 光束中层 */}
|
||||
<div className="absolute top-1/2 -translate-y-1/2 left-[8%] right-[8%] h-1.5 rounded-full"
|
||||
style={{
|
||||
background: `linear-gradient(90deg, transparent, ${product.themeColor}30, ${product.themeColor}60, ${product.themeColor}30, transparent)`,
|
||||
filter: 'blur(3px)',
|
||||
}}
|
||||
/>
|
||||
{/* 光束核心 */}
|
||||
<div className="relative h-1 rounded-full"
|
||||
style={{
|
||||
background: `linear-gradient(90deg, transparent, ${product.themeColor}60, ${product.themeColor}, ${product.themeColor}60, transparent)`,
|
||||
boxShadow: `0 0 12px ${product.themeColor}40, 0 0 24px ${product.themeColor}20`,
|
||||
}}>
|
||||
{/* 流动光点 */}
|
||||
<div className="absolute top-1/2 -translate-y-1/2 w-3 h-3 rounded-full transition-all duration-700 ease-out"
|
||||
style={{
|
||||
left: `${15 + lightPos * 35}%`,
|
||||
background: '#ffffff',
|
||||
boxShadow: `0 0 12px ${product.themeColor}, 0 0 28px ${product.themeColor}, 0 0 56px ${product.themeColor}, 0 0 84px ${product.themeColor}`,
|
||||
}}
|
||||
/>
|
||||
{/* 3 个节点标记 */}
|
||||
{[0, 1, 2].map(n => (
|
||||
<div key={n} className="absolute top-1/2 -translate-y-1/2 w-3 h-3 rounded-full border-2 transition-all duration-500"
|
||||
style={{
|
||||
left: `${15 + n * 35}%`,
|
||||
borderColor: n <= activeStep ? product.themeColor : `${product.themeColor}40`,
|
||||
background: n <= activeStep ? product.themeColor : '#ffffff',
|
||||
boxShadow: n <= activeStep ? `0 0 10px ${product.themeColor}80, 0 0 20px ${product.themeColor}40` : `0 0 4px ${product.themeColor}20`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -240,10 +684,10 @@ export default function ProductPage() {
|
||||
<ScrollReveal className="mb-14 text-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="inline-flex items-center gap-3 mb-5">
|
||||
<span className="w-5 h-[2px] rounded-full bg-[#043b8f]" />
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.25em] text-[#043b8f]">FAQ</span>
|
||||
<span className="w-5 h-[2px] rounded-lg bg-[var(--theme)]" />
|
||||
<span className="text-sm font-semibold uppercase tracking-[0.25em] text-[var(--theme)]">FAQ</span>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-[3.5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl lg:text-[5rem] font-black text-[#0f172a] tracking-tight leading-[1.1]">
|
||||
常见问题
|
||||
</h2>
|
||||
</div>
|
||||
@@ -252,21 +696,21 @@ export default function ProductPage() {
|
||||
<div className="space-y-4 max-w-3xl mx-auto">
|
||||
{product.faq.map((item, i) => (
|
||||
<ScrollReveal key={i} delay={i * 0.04}>
|
||||
<details className="group relative bg-white rounded-2xl border border-gray-100 hover:shadow-lg hover:shadow-[#043b8f]/5 transition-all duration-300 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 w-1 h-full bg-[#043b8f]/10 group-open:bg-[#043b8f] transition-colors duration-300" />
|
||||
<div className="absolute top-0 right-0 w-24 h-24 bg-[#043b8f]/[0.02] rounded-bl-full" />
|
||||
<summary className="relative flex items-center justify-between px-8 py-6 cursor-pointer list-none select-none">
|
||||
<div className="flex items-center gap-4 pr-4">
|
||||
<span className="flex items-center justify-center w-8 h-8 rounded-lg bg-[#043b8f]/[0.06] text-xs font-black text-[#043b8f] shrink-0">Q{i + 1}</span>
|
||||
<h3 className="text-lg font-bold text-[#0f172a]">{item.q}</h3>
|
||||
<details className="group relative bg-white rounded-2xl border border-gray-100 hover:shadow-lg hover:shadow-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.05)] transition-all duration-300 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 w-1 h-full bg-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.1)] group-open:bg-[var(--theme)] transition-colors duration-300" />
|
||||
<div className="absolute top-0 right-0 w-24 h-24 bg-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.02)] rounded-bl-full" />
|
||||
<summary className="relative flex items-center justify-between px-4 sm:px-6 md:px-8 py-4 sm:py-5 md:py-6 cursor-pointer list-none select-none">
|
||||
<div className="flex items-center gap-3 md:gap-4 pr-4">
|
||||
<span className="flex items-center justify-center w-7 h-7 sm:w-8 sm:h-8 rounded-lg bg-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.06)] text-xs font-black text-[var(--theme)] shrink-0">Q{i + 1}</span>
|
||||
<h3 className="text-base sm:text-lg md:text-xl font-bold text-[#0f172a]">{item.q}</h3>
|
||||
</div>
|
||||
<div className="w-8 h-8 rounded-full bg-[#043b8f]/[0.06] border border-[#043b8f]/10 flex items-center justify-center shrink-0 group-open:rotate-180 transition-transform duration-300">
|
||||
<ChevronDown className="w-4 h-4 text-[#043b8f]" />
|
||||
<div className="w-7 h-7 sm:w-8 sm:h-8 rounded-lg bg-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.06)] border border-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.1)] flex items-center justify-center shrink-0 group-open:rotate-180 transition-transform duration-300">
|
||||
<ChevronDown className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--theme)]" />
|
||||
</div>
|
||||
</summary>
|
||||
<div className="relative px-8 pb-7">
|
||||
<div className="ml-12 pl-5 border-l-2 border-[#043b8f]/10 bg-[#043b8f]/[0.02] rounded-r-lg py-4 pr-4">
|
||||
<p className="text-[#64748b] text-lg leading-relaxed">{item.a}</p>
|
||||
<div className="relative px-4 sm:px-6 md:px-8 pb-5 sm:pb-6 md:pb-7">
|
||||
<div className="ml-10 sm:ml-12 pl-4 sm:pl-5 border-l-2 border-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.1)] bg-[rgba(var(--theme-r),var(--theme-g),var(--theme-b),0.02)] rounded-r-lg py-3 sm:py-4 pr-3 sm:pr-4">
|
||||
<p className="text-[#64748b] text-sm sm:text-base md:text-lg lg:text-xl leading-relaxed">{item.a}</p>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
@@ -279,10 +723,10 @@ export default function ProductPage() {
|
||||
|
||||
{/* ── CTA ── */}
|
||||
<section className="py-40 px-4 relative overflow-hidden"
|
||||
style={{ background: 'linear-gradient(135deg, #0a1628, #0f1f3a)' }}>
|
||||
style={{ background: `linear-gradient(135deg, ${product.themeFrom || '#0a1628'}, ${product.themeTo || '#0f1f3a'})` }}>
|
||||
<div className="absolute inset-0 opacity-[0.04]"
|
||||
style={{
|
||||
backgroundImage: 'radial-gradient(#004ec4 1px, transparent 1px)',
|
||||
backgroundImage: `radial-gradient(${product.themeColor} 1px, transparent 1px)`,
|
||||
backgroundSize: '24px 24px',
|
||||
}}
|
||||
/>
|
||||
@@ -310,8 +754,6 @@ export default function ProductPage() {
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,20 @@ import react from '@vitejs/plugin-react'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
plugins: [
|
||||
react(),
|
||||
tailwindcss(),
|
||||
{
|
||||
name: 'txt-charset',
|
||||
configureServer(server) {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (req.url.endsWith('.txt')) {
|
||||
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
|
||||
}
|
||||
next()
|
||||
})
|
||||
},
|
||||
},
|
||||
],
|
||||
base: '/',
|
||||
})
|
||||
})
|
||||