first commit
This commit is contained in:
parent
0b5ed8476b
commit
124596ae94
3
.eslintrc.json
Normal file
3
.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
||||
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
11
.prettierrc
Normal file
11
.prettierrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"jsxSingleQuote": false,
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
273
README.md
Normal file
273
README.md
Normal file
@ -0,0 +1,273 @@
|
||||
# HaoAWS官方网站
|
||||
|
||||
<p align="center">
|
||||
<img src="public/images/logo-text.png" alt="HaoAWS" width="200" />
|
||||
</p>
|
||||
|
||||
一个现代化的多语言企业云服务官网,基于 Next.js 14 构建,支持完全静态导出和多语言国际化。
|
||||
|
||||
## ✨ 项目特性
|
||||
|
||||
- 🌍 **多语言支持** - 简体中文、繁体中文、英文
|
||||
- 📱 **响应式设计** - 完美适配桌面、平板、手机
|
||||
- ⚡ **静态导出** - 支持完全静态化部署,加载速度极快
|
||||
- 🔍 **SEO 优化** - 完整的 Meta 标签、结构化数据、多语言 sitemap
|
||||
- 📰 **新闻系统** - 基于 Markdown 的内容管理系统
|
||||
- 🎨 **现代 UI** - 使用 Tailwind CSS 和 ShadCN 组件
|
||||
- 🚀 **性能优化** - 代码分割、图片优化、预加载
|
||||
- 📦 **部署友好** - 支持 Netlify、Vercel、GitHub Pages 等平台
|
||||
|
||||
## 🛠️ 技术栈
|
||||
|
||||
- **前端框架**: [Next.js 14](https://nextjs.org/) (App Router)
|
||||
- **样式**: [Tailwind CSS](https://tailwindcss.com/)
|
||||
- **组件**: [ShadCN/UI](https://ui.shadcn.com/)
|
||||
- **国际化**: 自定义 i18n 解决方案
|
||||
- **内容管理**: Markdown + Gray Matter
|
||||
- **类型安全**: TypeScript
|
||||
- **代码规范**: ESLint + Prettier
|
||||
|
||||
## 📁 项目结构
|
||||
|
||||
```
|
||||
kejiyun/
|
||||
├── app/ # Next.js App Router
|
||||
│ ├── [locale]/ # 多语言路由
|
||||
│ │ ├── about/ # 关于我们页面
|
||||
│ │ ├── news/ # 新闻列表和详情
|
||||
│ │ ├── products/ # 产品页面
|
||||
│ │ ├── support/ # 支持页面
|
||||
│ │ └── layout.tsx # 多语言布局
|
||||
│ ├── news/[id]/ # 默认语言新闻详情
|
||||
│ ├── globals.css # 全局样式
|
||||
│ └── layout.tsx # 根布局
|
||||
├── components/ # 可复用组件
|
||||
│ ├── about/ # 关于页面组件
|
||||
│ ├── LanguageSwitcher.tsx # 语言切换器
|
||||
│ ├── Layout.tsx # 布局组件
|
||||
│ └── SEOPreview.tsx # SEO 预览
|
||||
├── data/ # 数据文件
|
||||
│ └── locales/ # 多语言翻译文件
|
||||
│ ├── en/ # 英文翻译
|
||||
│ ├── zh-CN/ # 简体中文翻译
|
||||
│ └── zh-TW/ # 繁体中文翻译
|
||||
├── docs/ # 文档和新闻内容
|
||||
│ └── news/ # 新闻 Markdown 文件
|
||||
├── lib/ # 工具函数
|
||||
│ ├── i18n.ts # 国际化配置
|
||||
│ ├── markdown.ts # Markdown 解析
|
||||
│ └── seo.ts # SEO 工具
|
||||
├── public/ # 静态资源
|
||||
└── middleware.ts # 路由中间件
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 安装依赖
|
||||
|
||||
```bash
|
||||
npm install
|
||||
# 或
|
||||
yarn install
|
||||
```
|
||||
|
||||
### 开发模式
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
打开 [http://localhost:3000](http://localhost:3000) 查看网站。
|
||||
|
||||
### 构建生产版本
|
||||
|
||||
```bash
|
||||
# 普通构建
|
||||
npm run build
|
||||
|
||||
# 静态导出构建
|
||||
npm run build:static
|
||||
```
|
||||
|
||||
### 本地预览静态版本
|
||||
|
||||
```bash
|
||||
npm run serve
|
||||
# 或
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## 🌍 多语言支持
|
||||
|
||||
### 支持的语言
|
||||
|
||||
- **简体中文** (`zh-CN`) - 默认语言,路径: `/`
|
||||
- **繁体中文** (`zh-TW`) - 路径: `/zh-TW/`
|
||||
- **英文** (`en`) - 路径: `/en/`
|
||||
|
||||
### 路由示例
|
||||
|
||||
```
|
||||
/ # 简体中文首页
|
||||
/about/ # 简体中文关于页面
|
||||
/news/article-id/ # 简体中文新闻详情
|
||||
|
||||
/zh-TW/ # 繁体中文首页
|
||||
/zh-TW/about/ # 繁体中文关于页面
|
||||
/zh-TW/news/article-id/ # 繁体中文新闻详情
|
||||
|
||||
/en/ # 英文首页
|
||||
/en/about/ # 英文关于页面
|
||||
/en/news/article-id/ # 英文新闻详情
|
||||
```
|
||||
|
||||
### 添加新语言
|
||||
|
||||
1. 在 `lib/i18n.ts` 中添加语言配置
|
||||
2. 在 `data/locales/` 中创建对应的翻译文件
|
||||
3. 在 `docs/news/` 中添加对应语言的新闻文件
|
||||
4. 更新各页面的 `generateStaticParams` 函数
|
||||
|
||||
## 📰 新闻系统
|
||||
|
||||
### 新闻文件结构
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "文章标题"
|
||||
description: "文章描述"
|
||||
date: "2024-01-01"
|
||||
author: "作者"
|
||||
tags: ["标签1", "标签2"]
|
||||
---
|
||||
|
||||
# 文章内容
|
||||
|
||||
这里是 Markdown 格式的文章内容...
|
||||
```
|
||||
|
||||
### 添加新新闻
|
||||
|
||||
1. 在 `docs/news/[语言]/` 目录下创建新的 `.md` 文件
|
||||
2. 更新 `app/[locale]/news/[id]/page.tsx` 中的 `generateStaticParams` 函数
|
||||
3. 重新构建网站
|
||||
|
||||
## 🔍 SEO 优化
|
||||
|
||||
### 已实现的 SEO 功能
|
||||
|
||||
- ✅ 多语言 Meta 标签
|
||||
- ✅ Open Graph 标签
|
||||
- ✅ Twitter Card 支持
|
||||
- ✅ 结构化数据 (JSON-LD)
|
||||
- ✅ 自动生成 sitemap.xml
|
||||
- ✅ robots.txt 配置
|
||||
- ✅ 语言链接标签 (hreflang)
|
||||
|
||||
### SEO 配置
|
||||
|
||||
在 `lib/seo.ts` 中配置默认的 SEO 设置,每个页面可以覆盖这些设置。
|
||||
|
||||
## 📦 部署
|
||||
|
||||
### 静态部署(推荐)
|
||||
|
||||
#### Netlify
|
||||
```bash
|
||||
# 构建命令
|
||||
npm run build:static
|
||||
|
||||
# 发布目录
|
||||
out
|
||||
```
|
||||
|
||||
#### Vercel
|
||||
```bash
|
||||
npm install -g vercel
|
||||
vercel --prod
|
||||
```
|
||||
|
||||
#### GitHub Pages
|
||||
```bash
|
||||
npm run build:static
|
||||
# 将 out/ 目录内容推送到 gh-pages 分支
|
||||
```
|
||||
|
||||
### 服务器部署
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm start
|
||||
```
|
||||
|
||||
## 🎨 自定义和扩展
|
||||
|
||||
### 添加新页面
|
||||
|
||||
1. 在 `app/[locale]/` 目录下创建新页面
|
||||
2. 添加对应的翻译文件
|
||||
3. 更新导航菜单
|
||||
4. 添加 `generateStaticParams` 函数(如果需要静态导出)
|
||||
|
||||
### 修改样式
|
||||
|
||||
项目使用 Tailwind CSS,可以在以下文件中修改样式:
|
||||
- `app/globals.css` - 全局样式
|
||||
- `tailwind.config.ts` - Tailwind 配置
|
||||
- 各组件文件中的 className
|
||||
|
||||
### 添加新组件
|
||||
|
||||
在 `components/` 目录下创建新组件,遵循现有的命名和结构规范。
|
||||
|
||||
## 🔧 开发指南
|
||||
|
||||
### 代码规范
|
||||
|
||||
```bash
|
||||
# 代码格式化
|
||||
npm run format
|
||||
|
||||
# 代码检查
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Windows 开发
|
||||
|
||||
如果在 Windows 上遇到权限问题,请参考 [WINDOWS_BUILD_GUIDE.md](./WINDOWS_BUILD_GUIDE.md)。
|
||||
|
||||
## 📋 可用脚本
|
||||
|
||||
```bash
|
||||
npm run dev # 开发模式
|
||||
npm run build # 生产构建
|
||||
npm run build:static # 静态导出构建
|
||||
npm run build:simple # 简化构建(解决权限问题)
|
||||
npm run start # 启动生产服务器
|
||||
npm run lint # 代码检查
|
||||
npm run format # 代码格式化
|
||||
npm run serve # 本地预览静态文件
|
||||
npm run preview # 构建并预览
|
||||
```
|
||||
|
||||
## 🐛 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **构建权限错误** - 参考 [WINDOWS_BUILD_GUIDE.md](./WINDOWS_BUILD_GUIDE.md)
|
||||
2. **语言切换不工作** - 检查 Cookie 设置和客户端 JavaScript
|
||||
3. **静态导出失败** - 确保所有动态路由都有 `generateStaticParams`
|
||||
|
||||
### 获取帮助
|
||||
|
||||
- 查看 [静态部署指南](./STATIC_DEPLOYMENT.md)
|
||||
- 查看 [Windows 构建指南](./WINDOWS_BUILD_GUIDE.md)
|
||||
- 检查 Next.js 官方文档
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
本项目采用 MIT 许可证。
|
||||
|
||||
---
|
||||
|
||||
**提示**: 这是一个完全静态化的网站,构建后可以部署到任何静态文件托管服务,无需 Node.js 服务器环境。
|
||||
166
STATIC_DEPLOYMENT.md
Normal file
166
STATIC_DEPLOYMENT.md
Normal file
@ -0,0 +1,166 @@
|
||||
# 静态部署指南
|
||||
|
||||
## 🚀 静态打包命令
|
||||
|
||||
### 构建静态文件
|
||||
```bash
|
||||
npm run build:static
|
||||
```
|
||||
|
||||
### 本地预览静态网站
|
||||
```bash
|
||||
npm run preview
|
||||
```
|
||||
|
||||
### 仅构建(不启动服务器)
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 仅启动静态文件服务器
|
||||
```bash
|
||||
npm run serve
|
||||
```
|
||||
|
||||
## 📁 输出目录
|
||||
|
||||
静态文件将生成在 `out/` 目录中,包含:
|
||||
|
||||
```
|
||||
out/
|
||||
├── index.html # 首页 (简体中文)
|
||||
├── zh-TW/
|
||||
│ ├── index.html # 繁体中文首页
|
||||
│ ├── about/index.html # 关于我们页面
|
||||
│ ├── products/index.html # 产品页面
|
||||
│ ├── news/
|
||||
│ │ ├── index.html # 新闻列表
|
||||
│ │ └── [id]/index.html # 新闻详情
|
||||
│ └── support/index.html # 支持页面
|
||||
├── en/
|
||||
│ ├── index.html # 英文首页
|
||||
│ └── ... # 其他英文页面
|
||||
├── news/
|
||||
│ ├── index.html # 默认语言新闻列表
|
||||
│ └── [id]/index.html # 默认语言新闻详情
|
||||
├── about/index.html # 默认语言关于页面
|
||||
├── products/index.html # 默认语言产品页面
|
||||
├── support/index.html # 默认语言支持页面
|
||||
└── _next/ # Next.js 静态资源
|
||||
```
|
||||
|
||||
## 🌐 部署到不同平台
|
||||
|
||||
### 1. Netlify
|
||||
1. 将 `out/` 目录拖拽到 Netlify 控制台
|
||||
2. 或连接 Git 仓库,设置构建命令:
|
||||
```
|
||||
Build command: npm run build:static
|
||||
Publish directory: out
|
||||
```
|
||||
|
||||
### 2. Vercel
|
||||
```bash
|
||||
npx vercel --prod
|
||||
```
|
||||
|
||||
### 3. GitHub Pages
|
||||
1. 将 `out/` 目录内容推送到 `gh-pages` 分支
|
||||
2. 在仓库设置中启用 GitHub Pages
|
||||
|
||||
### 4. 服务器部署
|
||||
将 `out/` 目录上传到服务器的网站根目录
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
### 基础路径配置
|
||||
如果需要部署到子目录,修改 `next.config.mjs`:
|
||||
|
||||
```js
|
||||
const nextConfig = {
|
||||
output: 'export',
|
||||
basePath: '/your-subdirectory', // 取消注释并设置路径
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### 图片优化
|
||||
静态导出中图片优化已设置为:
|
||||
```js
|
||||
images: {
|
||||
unoptimized: true, // 静态导出必需
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 多语言路由说明
|
||||
|
||||
静态导出后的路由结构:
|
||||
|
||||
- **简体中文 (默认)**:`/`, `/about`, `/news/xxx`
|
||||
- **繁体中文**:`/zh-TW/`, `/zh-TW/about`, `/zh-TW/news/xxx`
|
||||
- **英文**:`/en/`, `/en/about`, `/en/news/xxx`
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 静态导出限制
|
||||
1. **无服务器端渲染**:所有页面在构建时生成
|
||||
2. **无中间件**:语言切换依赖客户端逻辑
|
||||
3. **无动态API路由**:不能使用 `/api` 路由
|
||||
4. **无服务器端重定向**:依赖客户端跳转
|
||||
|
||||
### 语言切换机制
|
||||
在静态模式下:
|
||||
- 中间件不会执行
|
||||
- 语言切换完全依赖客户端 JavaScript
|
||||
- Cookie 设置在客户端进行
|
||||
|
||||
### 新增文章
|
||||
如需添加新文章,需要:
|
||||
1. 在 `docs/news/` 中添加 Markdown 文件
|
||||
2. 更新页面中的 `generateStaticParams` 函数
|
||||
3. 重新构建
|
||||
|
||||
## 🧪 测试
|
||||
|
||||
### 本地测试
|
||||
```bash
|
||||
# 构建并预览
|
||||
npm run preview
|
||||
|
||||
# 访问 http://localhost:3000
|
||||
```
|
||||
|
||||
### 构建验证
|
||||
```bash
|
||||
# 检查构建输出
|
||||
npm run build:static
|
||||
ls -la out/
|
||||
|
||||
# 验证多语言页面
|
||||
ls -la out/zh-TW/
|
||||
ls -la out/en/
|
||||
```
|
||||
|
||||
## 🔧 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **页面404**:检查 `generateStaticParams` 是否包含所有路由
|
||||
2. **样式丢失**:确认 CSS 文件正确引入
|
||||
3. **图片不显示**:检查图片路径和 `unoptimized: true` 设置
|
||||
4. **语言切换无效**:确认 JavaScript 已启用
|
||||
|
||||
### 调试步骤
|
||||
1. 检查 `out/` 目录结构
|
||||
2. 查看浏览器开发者工具控制台
|
||||
3. 验证静态文件访问路径
|
||||
|
||||
## 📈 性能优化
|
||||
|
||||
- ✅ 自动代码分割
|
||||
- ✅ 静态资源优化
|
||||
- ✅ CSS 压缩
|
||||
- ✅ JavaScript 压缩
|
||||
- ✅ 预加载关键资源
|
||||
|
||||
静态导出的网站加载速度极快,适合 CDN 分发!
|
||||
185
WINDOWS_BUILD_GUIDE.md
Normal file
185
WINDOWS_BUILD_GUIDE.md
Normal file
@ -0,0 +1,185 @@
|
||||
# Windows 静态构建指南
|
||||
|
||||
## 🚨 常见权限问题解决方案
|
||||
|
||||
### 方法一:使用管理员权限
|
||||
1. 右键点击 PowerShell 或 CMD
|
||||
2. 选择"以管理员身份运行"
|
||||
3. 导航到项目目录:`cd "E:\成品的网站\kejiyun"`
|
||||
4. 运行构建:`npm run build:static`
|
||||
|
||||
### 方法二:修改杀毒软件设置
|
||||
1. 临时关闭实时保护(Windows Defender 或其他杀毒软件)
|
||||
2. 将项目目录添加到杀毒软件白名单
|
||||
3. 重新尝试构建
|
||||
|
||||
### 方法三:使用简化构建命令
|
||||
```bash
|
||||
# 方法 1
|
||||
npm run build:simple
|
||||
|
||||
# 方法 2
|
||||
npx next build
|
||||
|
||||
# 方法 3(如果上面的失败)
|
||||
set NEXT_DISABLE_TELEMETRY=1
|
||||
set NODE_ENV=production
|
||||
npx next build
|
||||
```
|
||||
|
||||
## 🔧 手动构建步骤
|
||||
|
||||
### 1. 清理环境
|
||||
```powershell
|
||||
# 停止所有Node进程
|
||||
Get-Process node -ErrorAction SilentlyContinue | Stop-Process -Force
|
||||
|
||||
# 清理缓存目录
|
||||
Remove-Item -Path ".next", "out" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# 清理npm缓存
|
||||
npm cache clean --force
|
||||
```
|
||||
|
||||
### 2. 检查文件权限
|
||||
```powershell
|
||||
# 检查当前目录权限
|
||||
Get-Acl . | Format-List
|
||||
|
||||
# 如果需要,修改目录权限
|
||||
icacls . /grant $env:USERNAME:F /t
|
||||
```
|
||||
|
||||
### 3. 重新安装依赖
|
||||
```bash
|
||||
# 删除node_modules
|
||||
Remove-Item -Path "node_modules" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# 重新安装
|
||||
npm install
|
||||
```
|
||||
|
||||
### 4. 构建
|
||||
```bash
|
||||
npm run build:static
|
||||
```
|
||||
|
||||
## 🚀 成功构建后的验证
|
||||
|
||||
构建成功后,您应该看到:
|
||||
|
||||
```
|
||||
out/
|
||||
├── index.html # ✅ 简体中文首页
|
||||
├── about/
|
||||
│ └── index.html # ✅ 关于页面
|
||||
├── news/
|
||||
│ ├── index.html # ✅ 新闻列表
|
||||
│ ├── ai-transformation-2024/
|
||||
│ ├── cloud-security-best-practices/
|
||||
│ └── company-expansion-2024/
|
||||
├── products/
|
||||
├── support/
|
||||
├── zh-TW/ # ✅ 繁体中文版本
|
||||
├── en/ # ✅ 英文版本
|
||||
└── _next/ # ✅ 静态资源
|
||||
```
|
||||
|
||||
## 🌐 本地预览
|
||||
|
||||
```bash
|
||||
# 启动静态服务器
|
||||
npm run serve
|
||||
|
||||
# 或者使用Python(如果安装了)
|
||||
python -m http.server 3000 --directory out
|
||||
|
||||
# 或者使用其他静态服务器
|
||||
npx http-server out -p 3000
|
||||
```
|
||||
|
||||
## 🔍 故障排除
|
||||
|
||||
### 错误:EPERM: operation not permitted
|
||||
**原因**:文件权限或进程锁定问题
|
||||
|
||||
**解决方案**:
|
||||
1. 以管理员身份运行终端
|
||||
2. 确保没有其他进程正在使用项目文件
|
||||
3. 临时关闭杀毒软件
|
||||
4. 重启电脑后重试
|
||||
|
||||
### 错误:构建过程中卡住
|
||||
**解决方案**:
|
||||
1. 按 `Ctrl+C` 停止进程
|
||||
2. 运行:`npm run build:simple`
|
||||
3. 或使用 `npx next build --debug`
|
||||
|
||||
### 错误:out目录为空或缺少文件
|
||||
**检查**:
|
||||
1. 查看构建日志中的错误信息
|
||||
2. 确认 `generateStaticParams` 函数正确
|
||||
3. 检查是否有动态导入或服务器端功能
|
||||
|
||||
### 错误:语言切换不工作
|
||||
这是正常的,静态导出模式下:
|
||||
- 中间件不会执行
|
||||
- 语言切换依赖客户端JavaScript
|
||||
- 需要在浏览器中测试
|
||||
|
||||
## 📦 部署选项
|
||||
|
||||
### 1. Netlify(推荐)
|
||||
```bash
|
||||
# 方法1:拖拽部署
|
||||
# 将整个 out/ 目录拖拽到 https://app.netlify.com/drop
|
||||
|
||||
# 方法2:命令行部署
|
||||
npm install -g netlify-cli
|
||||
netlify deploy --prod --dir=out
|
||||
```
|
||||
|
||||
### 2. Vercel
|
||||
```bash
|
||||
npm install -g vercel
|
||||
vercel --prod
|
||||
```
|
||||
|
||||
### 3. GitHub Pages
|
||||
```bash
|
||||
# 推送 out/ 内容到 gh-pages 分支
|
||||
git subtree push --prefix out origin gh-pages
|
||||
```
|
||||
|
||||
### 4. 传统服务器
|
||||
- 上传 `out/` 目录到服务器的网站根目录
|
||||
- 确保服务器支持SPA路由(对于多语言URL)
|
||||
|
||||
## ⚡ 性能优化
|
||||
|
||||
构建后的静态网站已经包含:
|
||||
- ✅ 代码分割
|
||||
- ✅ 资源压缩
|
||||
- ✅ 图片优化
|
||||
- ✅ CSS/JS 最小化
|
||||
- ✅ 预加载关键资源
|
||||
|
||||
## 🔄 更新流程
|
||||
|
||||
当您修改内容后:
|
||||
1. 更新相应的Markdown或JSON文件
|
||||
2. 如果添加新文章,更新 `generateStaticParams`
|
||||
3. 重新运行 `npm run build:static`
|
||||
4. 重新部署 `out/` 目录
|
||||
|
||||
## 📞 需要帮助?
|
||||
|
||||
如果仍然遇到问题:
|
||||
1. 确保使用管理员权限
|
||||
2. 检查Windows版本兼容性
|
||||
3. 尝试在不同的文件夹位置重新克隆项目
|
||||
4. 考虑使用WSL(Windows Subsystem for Linux)
|
||||
|
||||
---
|
||||
|
||||
**记住**:静态导出的网站速度极快,完全不需要Node.js服务器,可以部署到任何静态网站托管服务!
|
||||
90
app/[locale]/about/page.tsx
Normal file
90
app/[locale]/about/page.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import Layout from '@/components/Layout';
|
||||
import CompanyOverview from '@/components/about/CompanyOverview';
|
||||
import CompanyMilestones from '@/components/about/CompanyMilestones';
|
||||
import TeamSection from '@/components/about/TeamSection';
|
||||
import CertificationsSection from '@/components/about/CertificationsSection';
|
||||
|
||||
interface AboutPageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
return locales.map((locale) => ({
|
||||
locale,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: AboutPageProps) {
|
||||
return generateSEOMetadata(params.locale, 'about');
|
||||
}
|
||||
|
||||
export default async function AboutPage({ params }: AboutPageProps) {
|
||||
const { locale } = params;
|
||||
const [common, about] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getTranslations(locale, 'about'),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid=".vgb:d0">
|
||||
{/* Hero Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50" data-oid="jwd3d81">
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="0ac1nh.">
|
||||
<h1
|
||||
className="text-4xl md:text-6xl font-light leading-tight mb-8 text-gray-900"
|
||||
data-oid="stkif1b"
|
||||
>
|
||||
{about.title}
|
||||
</h1>
|
||||
<p
|
||||
className="text-xl md:text-2xl text-gray-600 mb-12 font-light"
|
||||
data-oid="k-s6de:"
|
||||
>
|
||||
{about.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Company Overview */}
|
||||
<CompanyOverview data={about.sections.company} data-oid="mu4bpdw" />
|
||||
|
||||
{/* Company Milestones */}
|
||||
<CompanyMilestones data={about.sections.milestones} data-oid="mcpsf6k" />
|
||||
|
||||
{/* Team Section */}
|
||||
<TeamSection data={about.sections.team} data-oid="t32recr" />
|
||||
|
||||
{/* Certifications */}
|
||||
<CertificationsSection data={about.sections.certifications} data-oid="pc5azh2" />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
14
app/[locale]/layout.tsx
Normal file
14
app/[locale]/layout.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { Locale } from '@/lib/i18n';
|
||||
|
||||
interface LocaleLayoutProps {
|
||||
children: React.ReactNode;
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export default function LocaleLayout({ children, params }: LocaleLayoutProps) {
|
||||
// 在动态路由布局中,我们只需要返回children
|
||||
// 语言属性通过generateMetadata在页面级别设置
|
||||
return <>{children}</>;
|
||||
}
|
||||
147
app/[locale]/news/[id]/not-found.tsx
Normal file
147
app/[locale]/news/[id]/not-found.tsx
Normal file
@ -0,0 +1,147 @@
|
||||
import Link from 'next/link';
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import Layout from '@/components/Layout';
|
||||
|
||||
export default async function NewsNotFound() {
|
||||
// Since we can't access params in not-found.tsx, we'll use the default locale
|
||||
const locale: Locale = 'zh-CN';
|
||||
const common = await getTranslations(locale, 'common');
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid="_3j68t9">
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50 min-h-screen flex items-center"
|
||||
data-oid="byufenu"
|
||||
>
|
||||
<div className="max-w-2xl mx-auto text-center" data-oid="d7nio8r">
|
||||
<div className="mb-8" data-oid="jsety51">
|
||||
<div
|
||||
className="w-24 h-24 mx-auto mb-6 bg-gray-200 rounded-full flex items-center justify-center"
|
||||
data-oid="5ihesur"
|
||||
>
|
||||
<svg
|
||||
className="w-12 h-12 text-gray-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="kjp5851"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
data-oid="fi-bv88"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h1
|
||||
className="text-4xl md:text-5xl font-light mb-4 text-gray-900"
|
||||
data-oid="9oigcow"
|
||||
>
|
||||
404
|
||||
</h1>
|
||||
|
||||
<h2
|
||||
className="text-2xl md:text-3xl font-light mb-6 text-gray-700"
|
||||
data-oid="e04ibd."
|
||||
>
|
||||
文章未找到
|
||||
</h2>
|
||||
|
||||
<p
|
||||
className="text-lg text-gray-600 mb-8 leading-relaxed"
|
||||
data-oid="pec0pi4"
|
||||
>
|
||||
抱歉,您请求的新闻文章不存在,或者该文章的当前语言版本尚未提供。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4" data-oid="zq.yd55">
|
||||
<p className="text-gray-600 mb-6" data-oid="lq5sfie">
|
||||
可能的原因:
|
||||
</p>
|
||||
|
||||
<ul
|
||||
className="text-left text-gray-600 space-y-2 mb-8 max-w-md mx-auto"
|
||||
data-oid="hwob-h0"
|
||||
>
|
||||
<li className="flex items-start space-x-2" data-oid="z.xttum">
|
||||
<span className="text-blue-600 mt-1" data-oid="ivn4wke">
|
||||
•
|
||||
</span>
|
||||
<span data-oid="uvhrz0m">文章链接已过期或不正确</span>
|
||||
</li>
|
||||
<li className="flex items-start space-x-2" data-oid="49u2bhz">
|
||||
<span className="text-blue-600 mt-1" data-oid="e6cgf9o">
|
||||
•
|
||||
</span>
|
||||
<span data-oid="1vzafpj">该文章尚未翻译成当前语言</span>
|
||||
</li>
|
||||
<li className="flex items-start space-x-2" data-oid="ooz29p4">
|
||||
<span className="text-blue-600 mt-1" data-oid="w99sjj5">
|
||||
•
|
||||
</span>
|
||||
<span data-oid="yl74i72">文章已被移除或归档</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center"
|
||||
data-oid="nz.s4ql"
|
||||
>
|
||||
<Link
|
||||
href={
|
||||
navigationPaths.find((p) => p.key === 'news')?.path || '/news'
|
||||
}
|
||||
className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors font-light"
|
||||
data-oid="c45-.pd"
|
||||
>
|
||||
返回新闻列表
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'home')?.path || '/'}
|
||||
className="bg-gray-100 text-gray-700 px-6 py-3 rounded-lg hover:bg-gray-200 transition-colors font-light"
|
||||
data-oid="vzzstbf"
|
||||
>
|
||||
返回首页
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-12 pt-8 border-t border-gray-200" data-oid="y88ceui">
|
||||
<p className="text-sm text-gray-500" data-oid="bu7u61n">
|
||||
如果您认为这是一个错误,请联系我们的技术支持团队。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
467
app/[locale]/news/[id]/page.tsx
Normal file
467
app/[locale]/news/[id]/page.tsx
Normal file
@ -0,0 +1,467 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import { getNewsArticle, getAvailableLocalesForArticle, checkArticleExists } from '@/lib/markdown';
|
||||
import Layout from '@/components/Layout';
|
||||
import LanguageSwitcher from '@/components/LanguageSwitcher';
|
||||
import Link from 'next/link';
|
||||
|
||||
interface NewsDetailPageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
const articles = ['ai-transformation-2024', 'cloud-security-best-practices', 'company-expansion-2024'];
|
||||
|
||||
const params = [];
|
||||
for (const locale of locales) {
|
||||
for (const id of articles) {
|
||||
params.push({ locale, id });
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: NewsDetailPageProps) {
|
||||
const { locale, id } = params;
|
||||
|
||||
// Check if article exists
|
||||
if (!checkArticleExists(id, locale)) {
|
||||
return {
|
||||
title: 'Article Not Found',
|
||||
description: 'The requested article could not be found.',
|
||||
};
|
||||
}
|
||||
|
||||
const article = await getNewsArticle(id, locale);
|
||||
if (!article) {
|
||||
return {
|
||||
title: 'Article Not Found',
|
||||
description: 'The requested article could not be found.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: article.title,
|
||||
description: article.excerpt,
|
||||
openGraph: {
|
||||
title: article.title,
|
||||
description: article.excerpt,
|
||||
type: 'article',
|
||||
publishedTime: article.date,
|
||||
authors: [article.author],
|
||||
tags: article.tags,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function NewsDetailPage({ params }: NewsDetailPageProps) {
|
||||
const { locale, id } = params;
|
||||
|
||||
// Check if article exists in the requested locale
|
||||
if (!checkArticleExists(id, locale)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const article = await getNewsArticle(id, locale);
|
||||
if (!article) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const [common, availableLocales] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getAvailableLocalesForArticle(id),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid="c6mjboc">
|
||||
{/* Breadcrumb */}
|
||||
<section className="py-4 px-4 sm:px-6 lg:px-8 bg-gray-50 border-b" data-oid="7s5l-j9">
|
||||
<div className="max-w-4xl mx-auto" data-oid="hqsvp79">
|
||||
<nav
|
||||
className="flex items-center space-x-2 text-sm text-gray-600"
|
||||
data-oid="m0w56xh"
|
||||
>
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'home')?.path || '/'}
|
||||
className="hover:text-blue-600 transition-colors"
|
||||
data-oid="kpvk_7j"
|
||||
>
|
||||
{common.navigation.home}
|
||||
</Link>
|
||||
<span data-oid="tw5-oe_">/</span>
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'news')?.path || '/news'}
|
||||
className="hover:text-blue-600 transition-colors"
|
||||
data-oid=":-tqwq_"
|
||||
>
|
||||
{common.navigation.news}
|
||||
</Link>
|
||||
<span data-oid="o12p947">/</span>
|
||||
<span className="text-gray-900" data-oid="49bdp62">
|
||||
{article.title}
|
||||
</span>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Language Switcher */}
|
||||
<section className="py-4 px-4 sm:px-6 lg:px-8 bg-white border-b" data-oid="zmlodji">
|
||||
<div className="max-w-4xl mx-auto" data-oid="gxv6myl">
|
||||
<div className="flex items-center justify-between" data-oid="1c10d2u">
|
||||
<div className="flex items-center space-x-2" data-oid="5c7b2mr">
|
||||
<span className="text-sm text-gray-600" data-oid="wrn.7x1">
|
||||
{locale === 'en'
|
||||
? 'Available in:'
|
||||
: locale === 'zh-TW'
|
||||
? '可用語言:'
|
||||
: '可用语言:'}
|
||||
</span>
|
||||
<LanguageSwitcher
|
||||
currentLocale={locale}
|
||||
availableLocales={availableLocales}
|
||||
articleId={id}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Back to News */}
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'news')?.path || '/news'}
|
||||
className="text-sm text-blue-600 hover:text-blue-800 flex items-center space-x-1"
|
||||
data-oid="eatue3o"
|
||||
>
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="k:sapi1"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M15 19l-7-7 7-7"
|
||||
data-oid="e06c-co"
|
||||
/>
|
||||
</svg>
|
||||
<span data-oid="efqxeqy">
|
||||
{locale === 'en'
|
||||
? 'Back to News'
|
||||
: locale === 'zh-TW'
|
||||
? '返回新聞'
|
||||
: '返回新闻'}
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Article Header */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 bg-white" data-oid="h:ik7pu">
|
||||
<div className="max-w-4xl mx-auto" data-oid="j8v8ces">
|
||||
<div className="mb-8" data-oid="p.xgl5-">
|
||||
<div className="flex items-center space-x-4 mb-6" data-oid="zsrn6ji">
|
||||
<span
|
||||
className="px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full font-medium"
|
||||
data-oid="wy0nqoy"
|
||||
>
|
||||
{article.category}
|
||||
</span>
|
||||
{article.featured && (
|
||||
<span
|
||||
className="px-3 py-1 bg-red-100 text-red-800 text-sm rounded-full font-medium"
|
||||
data-oid="x-9lbop"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Featured'
|
||||
: locale === 'zh-TW'
|
||||
? '精選'
|
||||
: '精选'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<h1
|
||||
className="text-4xl md:text-5xl font-light leading-tight mb-6 text-gray-900"
|
||||
data-oid="gd_tb.u"
|
||||
>
|
||||
{article.title}
|
||||
</h1>
|
||||
|
||||
<div
|
||||
className="flex flex-wrap items-center gap-6 text-gray-600 mb-6"
|
||||
data-oid="h1xbibw"
|
||||
>
|
||||
<div className="flex items-center space-x-2" data-oid="hpuafgc">
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="1dedyyy"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
data-oid="iwixjjh"
|
||||
/>
|
||||
</svg>
|
||||
<span data-oid="4tznx3q">{article.date}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2" data-oid="65jmrbx">
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="y9xj5gd"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
data-oid="i1u38j6"
|
||||
/>
|
||||
</svg>
|
||||
<span data-oid="m76y57i">{article.author}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2" data-oid="844.7pi">
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="re-164m"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
data-oid="b0q9r7."
|
||||
/>
|
||||
</svg>
|
||||
<span data-oid="49cu0of">{article.readTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
className="text-xl text-gray-600 font-light leading-relaxed"
|
||||
data-oid="b2er1ct"
|
||||
>
|
||||
{article.excerpt}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
{article.tags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2 mb-8" data-oid="i2rwhiz">
|
||||
{article.tags.map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full"
|
||||
data-oid="mo3ug:j"
|
||||
>
|
||||
#{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Article Content */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 bg-white" data-oid="d02:vlw">
|
||||
<div className="max-w-4xl mx-auto" data-oid=".8y4h8a">
|
||||
<div className="prose prose-lg prose-gray max-w-none" data-oid="blhf5-s">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
h1: ({ children }) => (
|
||||
<h1
|
||||
className="text-3xl font-light mb-6 text-gray-900 border-b border-gray-200 pb-4"
|
||||
data-oid="k2f36kp"
|
||||
>
|
||||
{children}
|
||||
</h1>
|
||||
),
|
||||
|
||||
h2: ({ children }) => (
|
||||
<h2
|
||||
className="text-2xl font-light mb-4 mt-8 text-gray-900"
|
||||
data-oid="us4v-ay"
|
||||
>
|
||||
{children}
|
||||
</h2>
|
||||
),
|
||||
|
||||
h3: ({ children }) => (
|
||||
<h3
|
||||
className="text-xl font-light mb-3 mt-6 text-gray-900"
|
||||
data-oid="9h758:b"
|
||||
>
|
||||
{children}
|
||||
</h3>
|
||||
),
|
||||
|
||||
p: ({ children }) => (
|
||||
<p
|
||||
className="mb-4 leading-relaxed text-gray-700"
|
||||
data-oid="v.5:d5y"
|
||||
>
|
||||
{children}
|
||||
</p>
|
||||
),
|
||||
|
||||
ul: ({ children }) => (
|
||||
<ul
|
||||
className="mb-4 space-y-2 list-disc list-inside text-gray-700"
|
||||
data-oid="8tm.vpa"
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
),
|
||||
|
||||
ol: ({ children }) => (
|
||||
<ol
|
||||
className="mb-4 space-y-2 list-decimal list-inside text-gray-700"
|
||||
data-oid="2_dmi-o"
|
||||
>
|
||||
{children}
|
||||
</ol>
|
||||
),
|
||||
|
||||
li: ({ children }) => (
|
||||
<li className="leading-relaxed" data-oid="p18xbtd">
|
||||
{children}
|
||||
</li>
|
||||
),
|
||||
|
||||
blockquote: ({ children }) => (
|
||||
<blockquote
|
||||
className="border-l-4 border-blue-500 pl-4 py-2 mb-4 bg-blue-50 text-gray-700 italic"
|
||||
data-oid="letfg8v"
|
||||
>
|
||||
{children}
|
||||
</blockquote>
|
||||
),
|
||||
|
||||
code: ({ children }) => (
|
||||
<code
|
||||
className="bg-gray-100 px-2 py-1 rounded text-sm font-mono text-gray-800"
|
||||
data-oid=":rcw03n"
|
||||
>
|
||||
{children}
|
||||
</code>
|
||||
),
|
||||
|
||||
pre: ({ children }) => (
|
||||
<pre
|
||||
className="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto mb-4"
|
||||
data-oid="kkqwbw_"
|
||||
>
|
||||
{children}
|
||||
</pre>
|
||||
),
|
||||
}}
|
||||
data-oid="gwxptyo"
|
||||
>
|
||||
{article.content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Article Footer */}
|
||||
<section className="py-8 px-4 sm:px-6 lg:px-8 bg-gray-50 border-t" data-oid="a4:0vxi">
|
||||
<div className="max-w-4xl mx-auto" data-oid="gs4ey_i">
|
||||
<div
|
||||
className="flex flex-col md:flex-row justify-between items-start md:items-center space-y-4 md:space-y-0"
|
||||
data-oid="utuumme"
|
||||
>
|
||||
<div data-oid="03ew7k3">
|
||||
<p className="text-gray-600 text-sm" data-oid="40k1zhp">
|
||||
{locale === 'en'
|
||||
? 'Published on'
|
||||
: locale === 'zh-TW'
|
||||
? '發布於'
|
||||
: '发布于'}{' '}
|
||||
{article.date}
|
||||
</p>
|
||||
<p className="text-gray-600 text-sm" data-oid="qar67n3">
|
||||
{locale === 'en' ? 'By' : locale === 'zh-TW' ? '作者:' : '作者:'}{' '}
|
||||
{article.author}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-4" data-oid="8yznw49">
|
||||
<button
|
||||
className="text-blue-600 hover:text-blue-800 text-sm flex items-center space-x-1"
|
||||
data-oid="gzw87qn"
|
||||
>
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="ldlorm8"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z"
|
||||
data-oid="l34b4tz"
|
||||
/>
|
||||
</svg>
|
||||
<span data-oid="ww8eb3z">
|
||||
{locale === 'en'
|
||||
? 'Share'
|
||||
: locale === 'zh-TW'
|
||||
? '分享'
|
||||
: '分享'}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
380
app/[locale]/news/page.tsx
Normal file
380
app/[locale]/news/page.tsx
Normal file
@ -0,0 +1,380 @@
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import Layout from '@/components/Layout';
|
||||
import Link from 'next/link';
|
||||
|
||||
interface NewsPageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
return locales.map((locale) => ({
|
||||
locale,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: NewsPageProps) {
|
||||
return generateSEOMetadata(params.locale, 'news');
|
||||
}
|
||||
|
||||
export default async function NewsPage({ params }: NewsPageProps) {
|
||||
const { locale } = params;
|
||||
const [common, news] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getTranslations(locale, 'news'),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
// Separate featured and regular articles
|
||||
const featuredArticles = news.articles.filter((article: any) => article.featured);
|
||||
const regularArticles = news.articles.filter((article: any) => !article.featured);
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid="0vnem-m">
|
||||
{/* Hero Section */}
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-blue-50 to-indigo-100"
|
||||
data-oid="_z.k3zw"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="_3g2-tz">
|
||||
<h1
|
||||
className="text-4xl md:text-6xl font-light leading-tight mb-8 text-gray-900"
|
||||
data-oid="hwhf6yk"
|
||||
>
|
||||
{news.title}
|
||||
</h1>
|
||||
<p
|
||||
className="text-xl md:text-2xl text-gray-600 mb-12 font-light max-w-3xl mx-auto"
|
||||
data-oid="475_6p4"
|
||||
>
|
||||
{news.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Categories Filter */}
|
||||
<section className="py-8 px-4 sm:px-6 lg:px-8 bg-white border-b" data-oid=".1agyst">
|
||||
<div className="max-w-6xl mx-auto" data-oid="8lpvlgm">
|
||||
<div className="flex flex-wrap justify-center gap-4" data-oid="x9w74q0">
|
||||
<button
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded-full text-sm font-medium"
|
||||
data-oid="m36b8uf"
|
||||
>
|
||||
{locale === 'en' ? 'All' : locale === 'zh-TW' ? '全部' : '全部'}
|
||||
</button>
|
||||
{news.categories.map((category: any) => (
|
||||
<button
|
||||
key={category.id}
|
||||
className="px-4 py-2 bg-gray-100 text-gray-700 hover:bg-gray-200 rounded-full text-sm font-medium transition-colors"
|
||||
data-oid="1mk88jz"
|
||||
>
|
||||
{category.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Featured Articles */}
|
||||
{featuredArticles.length > 0 && (
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-gray-50" data-oid="j5o7dgs">
|
||||
<div className="max-w-6xl mx-auto" data-oid="-67:-eb">
|
||||
<h2
|
||||
className="text-3xl font-light mb-12 text-gray-900 text-center"
|
||||
data-oid="f0:azse"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Featured Stories'
|
||||
: locale === 'zh-TW'
|
||||
? '精選報導'
|
||||
: '精选报道'}
|
||||
</h2>
|
||||
<div
|
||||
className="grid md:grid-cols-2 lg:grid-cols-3 gap-8"
|
||||
data-oid=":97aius"
|
||||
>
|
||||
{featuredArticles.map((article: any, index: number) => (
|
||||
<article
|
||||
key={article.id}
|
||||
className="bg-white rounded-lg shadow-sm hover:shadow-xl transition-all duration-300 overflow-hidden group hover:-translate-y-1"
|
||||
data-oid="f:en70o"
|
||||
>
|
||||
{/* Article Image */}
|
||||
<div
|
||||
className="h-48 bg-gradient-to-br from-blue-500 to-purple-600 relative overflow-hidden"
|
||||
data-oid="2t.wnic"
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 bg-black/20"
|
||||
data-oid="i4ukfzz"
|
||||
></div>
|
||||
<div className="absolute top-4 left-4" data-oid="k71eke4">
|
||||
<span
|
||||
className="px-3 py-1 bg-white/90 text-gray-800 text-xs rounded-full font-medium"
|
||||
data-oid=".sw53_f"
|
||||
>
|
||||
{article.category}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="absolute bottom-4 right-4"
|
||||
data-oid="-h749rl"
|
||||
>
|
||||
<span
|
||||
className="px-2 py-1 bg-red-500 text-white text-xs rounded-full font-medium"
|
||||
data-oid="hncsyw7"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Featured'
|
||||
: locale === 'zh-TW'
|
||||
? '精選'
|
||||
: '精选'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6" data-oid="ve46565">
|
||||
<div
|
||||
className="flex items-center gap-2 mb-3 text-sm text-gray-500"
|
||||
data-oid=":wckr.6"
|
||||
>
|
||||
<span data-oid="ry:qh2b">{article.date}</span>
|
||||
<span data-oid="f4btvsg">•</span>
|
||||
<span data-oid="v_wu-ue">{article.readTime}</span>
|
||||
</div>
|
||||
<Link
|
||||
href={`/${locale === 'zh-CN' ? '' : locale + '/'}news/${article.id}`}
|
||||
data-oid="f2dc6fr"
|
||||
>
|
||||
<h3
|
||||
className="text-xl font-light mb-3 text-gray-900 group-hover:text-blue-600 transition-colors line-clamp-2 cursor-pointer"
|
||||
data-oid="9m9sdpe"
|
||||
>
|
||||
{article.title}
|
||||
</h3>
|
||||
</Link>
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed mb-4 text-sm line-clamp-3"
|
||||
data-oid="apln_2n"
|
||||
>
|
||||
{article.excerpt}
|
||||
</p>
|
||||
<Link
|
||||
href={`/${locale}/news/${article.id}`}
|
||||
className="text-blue-600 hover:text-blue-800 font-light text-sm flex items-center gap-1"
|
||||
data-oid="v7lxwey"
|
||||
>
|
||||
{news.readMore}
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="ktuqoe-"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 5l7 7-7 7"
|
||||
data-oid="kvo-txc"
|
||||
/>
|
||||
</svg>
|
||||
</Link>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* Regular Articles */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8" data-oid="v4v_qyp">
|
||||
<div className="max-w-5xl mx-auto" data-oid="xw5.vf6">
|
||||
<h2
|
||||
className="text-3xl font-light mb-12 text-gray-900 text-center"
|
||||
data-oid="nqeg.nx"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Latest News'
|
||||
: locale === 'zh-TW'
|
||||
? '最新消息'
|
||||
: '最新消息'}
|
||||
</h2>
|
||||
<div className="space-y-8" data-oid="dvi3cq5">
|
||||
{regularArticles.map((article: any, index: number) => (
|
||||
<article
|
||||
key={article.id}
|
||||
className="bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow p-6 border border-gray-100"
|
||||
data-oid="u.554nu"
|
||||
>
|
||||
<div className="flex flex-col lg:flex-row gap-6" data-oid="ak2f2lg">
|
||||
<div className="lg:w-1/3" data-oid="8qjnsik">
|
||||
<div
|
||||
className="aspect-video bg-gradient-to-br from-gray-200 to-gray-300 rounded-lg"
|
||||
data-oid="a:bubtr"
|
||||
></div>
|
||||
</div>
|
||||
<div className="lg:w-2/3" data-oid="ov47-2.">
|
||||
<div
|
||||
className="flex items-center gap-4 mb-3"
|
||||
data-oid="5egq_qs"
|
||||
>
|
||||
<span
|
||||
className="px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full font-medium"
|
||||
data-oid="tbtpcc0"
|
||||
>
|
||||
{article.category}
|
||||
</span>
|
||||
<span
|
||||
className="text-gray-500 text-sm"
|
||||
data-oid="mu77._u"
|
||||
>
|
||||
{article.date}
|
||||
</span>
|
||||
<span
|
||||
className="text-gray-400 text-sm"
|
||||
data-oid="tm5xbdm"
|
||||
>
|
||||
{article.readTime}
|
||||
</span>
|
||||
</div>
|
||||
<Link
|
||||
href={`/${locale === 'zh-CN' ? '' : locale + '/'}news/${article.id}`}
|
||||
data-oid="-rjf7x3"
|
||||
>
|
||||
<h3
|
||||
className="text-2xl font-light mb-4 text-gray-900 hover:text-blue-600 transition-colors cursor-pointer"
|
||||
data-oid="d.pkpb7"
|
||||
>
|
||||
{article.title}
|
||||
</h3>
|
||||
</Link>
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed mb-4"
|
||||
data-oid="vo-q4e."
|
||||
>
|
||||
{article.excerpt}
|
||||
</p>
|
||||
<div
|
||||
className="flex items-center justify-between"
|
||||
data-oid="itrnko:"
|
||||
>
|
||||
<Link
|
||||
href={`/${locale}/news/${article.id}`}
|
||||
className="text-blue-600 hover:text-blue-800 font-light flex items-center gap-1"
|
||||
data-oid=":0h-66z"
|
||||
>
|
||||
{news.readMore}
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="ifbxhoc"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 5l7 7-7 7"
|
||||
data-oid="5s-5dkr"
|
||||
/>
|
||||
</svg>
|
||||
</Link>
|
||||
<span
|
||||
className="text-gray-400 text-sm"
|
||||
data-oid="lw6i.81"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'By'
|
||||
: locale === 'zh-TW'
|
||||
? '作者:'
|
||||
: '作者:'}{' '}
|
||||
{article.author}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Newsletter Subscription */}
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-900 text-white"
|
||||
data-oid="i4p0fxb"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="bcymkw3">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-6" data-oid="uk:qclr">
|
||||
{locale === 'en'
|
||||
? 'Stay Updated'
|
||||
: locale === 'zh-TW'
|
||||
? '保持更新'
|
||||
: '保持更新'}
|
||||
</h2>
|
||||
<p className="text-xl font-light mb-8 opacity-90" data-oid="jyr:dy3">
|
||||
{locale === 'en'
|
||||
? 'Subscribe to our newsletter for the latest industry insights and company updates.'
|
||||
: locale === 'zh-TW'
|
||||
? '訂閱我們的電子報,獲取最新的行業洞察和公司動態。'
|
||||
: '订阅我们的电子报,获取最新的行业洞察和公司动态。'}
|
||||
</p>
|
||||
<div
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center max-w-md mx-auto"
|
||||
data-oid="xi2e::m"
|
||||
>
|
||||
<input
|
||||
type="email"
|
||||
placeholder={
|
||||
locale === 'en'
|
||||
? 'Enter your email'
|
||||
: locale === 'zh-TW'
|
||||
? '輸入您的電子郵件'
|
||||
: '输入您的电子邮件'
|
||||
}
|
||||
className="flex-1 px-4 py-3 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
data-oid="04m.s6d"
|
||||
/>
|
||||
|
||||
<button
|
||||
className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors font-light"
|
||||
data-oid="li_uj-8"
|
||||
>
|
||||
{locale === 'en' ? 'Subscribe' : locale === 'zh-TW' ? '訂閱' : '订阅'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
65
app/[locale]/page.tsx
Normal file
65
app/[locale]/page.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import { getLatestNewsArticles } from '@/lib/markdown';
|
||||
import Layout from '@/components/Layout';
|
||||
import HomePageClient from '@/components/HomePageClient';
|
||||
import HomePageSEO from '@/components/HomePageSEO';
|
||||
|
||||
interface HomePageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
return locales.map((locale) => ({
|
||||
locale,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: HomePageProps) {
|
||||
return generateSEOMetadata(params.locale, 'home');
|
||||
}
|
||||
|
||||
export default async function HomePage({ params }: HomePageProps) {
|
||||
const { locale } = params;
|
||||
const [common, home, latestNews] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getTranslations(locale, 'home'),
|
||||
getLatestNewsArticles(locale, 3),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<HomePageSEO locale={locale} data-oid="ow9gpey" />
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid="kpluc9n">
|
||||
<HomePageClient locale={locale} home={home} common={common} latestNews={latestNews} data-oid="xqjcs:v" />
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
266
app/[locale]/products/page.tsx
Normal file
266
app/[locale]/products/page.tsx
Normal file
@ -0,0 +1,266 @@
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import Layout from '@/components/Layout';
|
||||
|
||||
interface ProductsPageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
return locales.map((locale) => ({
|
||||
locale,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: ProductsPageProps) {
|
||||
return generateSEOMetadata(params.locale, 'products');
|
||||
}
|
||||
|
||||
export default async function ProductsPage({ params }: ProductsPageProps) {
|
||||
const { locale } = params;
|
||||
const [common, products] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getTranslations(locale, 'products'),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid="gyz1ylb">
|
||||
{/* Hero Section */}
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-blue-50 to-indigo-100"
|
||||
data-oid="w78w6n1"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="qed-6ck">
|
||||
<h1
|
||||
className="text-4xl md:text-6xl font-light leading-tight mb-8 text-gray-900"
|
||||
data-oid="0qyfsz9"
|
||||
>
|
||||
{products.title}
|
||||
</h1>
|
||||
<p
|
||||
className="text-xl md:text-2xl text-gray-600 mb-12 font-light max-w-3xl mx-auto"
|
||||
data-oid="9fpzlrh"
|
||||
>
|
||||
{products.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Categories Section */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white" data-oid="1zebg6q">
|
||||
<div className="max-w-6xl mx-auto" data-oid="9umo9-6">
|
||||
<div className="text-center mb-12" data-oid="t1f7o-t">
|
||||
<h2 className="text-3xl font-light mb-4 text-gray-900" data-oid="64l9n6c">
|
||||
{locale === 'en'
|
||||
? 'Service Categories'
|
||||
: locale === 'zh-TW'
|
||||
? '服務類別'
|
||||
: '服务类别'}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6" data-oid=".gn5nfr">
|
||||
{products.categories.map((category: any, index: number) => (
|
||||
<div
|
||||
key={category.id}
|
||||
className="text-center p-6 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
|
||||
data-oid="iv_2ed8"
|
||||
>
|
||||
<div className="text-4xl mb-4" data-oid="tyq6p2w">
|
||||
{category.icon}
|
||||
</div>
|
||||
<h3
|
||||
className="text-lg font-light mb-2 text-gray-900"
|
||||
data-oid="q1z7z1_"
|
||||
>
|
||||
{category.name}
|
||||
</h3>
|
||||
<p className="text-gray-600 font-light text-sm" data-oid="xl3fv7e">
|
||||
{category.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Products Grid */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50" data-oid="qeuq_-:">
|
||||
<div className="max-w-6xl mx-auto" data-oid="oh:6vdi">
|
||||
<div className="text-center mb-16" data-oid=".vcnoeu">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-4 text-gray-900"
|
||||
data-oid="uadz:hj"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Our Solutions'
|
||||
: locale === 'zh-TW'
|
||||
? '我們的解決方案'
|
||||
: '我们的解决方案'}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8" data-oid="rxvkzz0">
|
||||
{products.items.map((product: any, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white rounded-lg shadow-sm hover:shadow-xl transition-all duration-300 overflow-hidden group hover:-translate-y-1"
|
||||
data-oid="pfuhhev"
|
||||
>
|
||||
{/* Product Icon/Image */}
|
||||
<div
|
||||
className="h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center"
|
||||
data-oid="tmootoi"
|
||||
>
|
||||
<span className="text-6xl" data-oid="bou76:j">
|
||||
{product.icon || '💼'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="p-6" data-oid="sevoy96">
|
||||
<h3
|
||||
className="text-xl font-light mb-3 text-gray-900 group-hover:text-blue-600 transition-colors"
|
||||
data-oid="0:6.pf7"
|
||||
>
|
||||
{product.title}
|
||||
</h3>
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed mb-4 text-sm"
|
||||
data-oid="zr62xye"
|
||||
>
|
||||
{product.description}
|
||||
</p>
|
||||
|
||||
{/* Features */}
|
||||
<div className="mb-6" data-oid="7f0q-g0">
|
||||
<h4
|
||||
className="text-sm font-medium text-gray-900 mb-2"
|
||||
data-oid="4rx:_c5"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Key Features:'
|
||||
: locale === 'zh-TW'
|
||||
? '主要功能:'
|
||||
: '主要功能:'}
|
||||
</h4>
|
||||
<div className="flex flex-wrap gap-2" data-oid="i5a_c6v">
|
||||
{product.features
|
||||
.slice(0, 4)
|
||||
.map((feature: string, featureIndex: number) => (
|
||||
<span
|
||||
key={featureIndex}
|
||||
className="px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full"
|
||||
data-oid="659zawc"
|
||||
>
|
||||
{feature}
|
||||
</span>
|
||||
))}
|
||||
{product.features.length > 4 && (
|
||||
<span
|
||||
className="px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded-full"
|
||||
data-oid="47o4wca"
|
||||
>
|
||||
+{product.features.length - 4}{' '}
|
||||
{locale === 'en'
|
||||
? 'more'
|
||||
: locale === 'zh-TW'
|
||||
? '更多'
|
||||
: '更多'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CTA Button */}
|
||||
<button
|
||||
className="w-full bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors font-light"
|
||||
data-oid="ig90.fv"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Learn More'
|
||||
: locale === 'zh-TW'
|
||||
? '了解更多'
|
||||
: '了解更多'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-900 text-white"
|
||||
data-oid="bp05uvo"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="skrviw7">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-6" data-oid="_dv23f0">
|
||||
{locale === 'en'
|
||||
? 'Ready to Transform Your Business?'
|
||||
: locale === 'zh-TW'
|
||||
? '準備好轉型您的業務了嗎?'
|
||||
: '准备好转型您的业务了吗?'}
|
||||
</h2>
|
||||
<p className="text-xl font-light mb-8 opacity-90" data-oid=":qjk4nd">
|
||||
{locale === 'en'
|
||||
? 'Contact our experts to discuss your specific needs and get a customized solution.'
|
||||
: locale === 'zh-TW'
|
||||
? '聯絡我們的專家討論您的具體需求,獲得客製化解決方案。'
|
||||
: '联系我们的专家讨论您的具体需求,获得定制化解决方案。'}
|
||||
</p>
|
||||
<div
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center"
|
||||
data-oid="_m7xjky"
|
||||
>
|
||||
<button
|
||||
className="bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 transition-colors font-light"
|
||||
data-oid="m1p0dgi"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Get Started'
|
||||
: locale === 'zh-TW'
|
||||
? '開始使用'
|
||||
: '开始使用'}
|
||||
</button>
|
||||
<button
|
||||
className="border border-white text-white px-8 py-3 rounded-lg hover:bg-white hover:text-gray-900 transition-colors font-light"
|
||||
data-oid=".31hjbd"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Schedule Consultation'
|
||||
: locale === 'zh-TW'
|
||||
? '預約諮詢'
|
||||
: '预约咨询'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
259
app/[locale]/support/page.tsx
Normal file
259
app/[locale]/support/page.tsx
Normal file
@ -0,0 +1,259 @@
|
||||
import { getTranslations, Locale, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import Layout from '@/components/Layout';
|
||||
|
||||
interface SupportPageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
return locales.map((locale) => ({
|
||||
locale,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: SupportPageProps) {
|
||||
return generateSEOMetadata(params.locale, 'support');
|
||||
}
|
||||
|
||||
export default async function SupportPage({ params }: SupportPageProps) {
|
||||
const { locale } = params;
|
||||
const [common, support] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getTranslations(locale, 'support'),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common} data-oid="lt:pgoh">
|
||||
{/* Hero Section */}
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-blue-50 to-indigo-100"
|
||||
data-oid="ixvdy14"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="70bosni">
|
||||
<h1
|
||||
className="text-4xl md:text-6xl font-light leading-tight mb-8 text-gray-900"
|
||||
data-oid="2w3nh03"
|
||||
>
|
||||
{support.title}
|
||||
</h1>
|
||||
<p
|
||||
className="text-xl md:text-2xl text-gray-600 mb-12 font-light max-w-3xl mx-auto"
|
||||
data-oid="p5hkz-y"
|
||||
>
|
||||
{support.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact Methods */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8" data-oid="7xr3drt">
|
||||
<div className="max-w-6xl mx-auto" data-oid="tu7tfi.">
|
||||
<div className="text-center mb-16" data-oid="qies69n">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-4 text-gray-900"
|
||||
data-oid="g9:2193"
|
||||
>
|
||||
{support.sections.contact.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600 font-light" data-oid="ke6h5h6">
|
||||
{support.sections.contact.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8" data-oid="s3moj-.">
|
||||
{support.sections.contact.methods.map((method: any, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white p-8 rounded-lg shadow-sm hover:shadow-md transition-shadow text-center"
|
||||
data-oid="kl17s4s"
|
||||
>
|
||||
<div className="text-4xl mb-4" data-oid="rzr20u.">
|
||||
{method.icon}
|
||||
</div>
|
||||
<h3
|
||||
className="text-xl font-light mb-3 text-gray-900"
|
||||
data-oid="67d-vb5"
|
||||
>
|
||||
{method.title}
|
||||
</h3>
|
||||
<p className="text-blue-600 font-medium mb-2" data-oid="ge86mew">
|
||||
{method.value}
|
||||
</p>
|
||||
<p className="text-gray-600 font-light text-sm" data-oid="kuk_bv7">
|
||||
{method.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Help Resources */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50" data-oid="7dgxwml">
|
||||
<div className="max-w-6xl mx-auto" data-oid="hha3y0c">
|
||||
<div className="text-center mb-16" data-oid="_loxumd">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-4 text-gray-900"
|
||||
data-oid="2mv_dyz"
|
||||
>
|
||||
{support.sections.resources.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600 font-light" data-oid="1u6h1y3">
|
||||
{support.sections.resources.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8" data-oid="2ux8bqc">
|
||||
{support.sections.resources.items.map((resource: any, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white p-6 rounded-lg shadow-sm hover:shadow-md transition-shadow text-center cursor-pointer group"
|
||||
data-oid="3yqt3ct"
|
||||
>
|
||||
<div
|
||||
className="text-4xl mb-4 group-hover:scale-110 transition-transform"
|
||||
data-oid="nokwcp0"
|
||||
>
|
||||
{resource.icon}
|
||||
</div>
|
||||
<h3
|
||||
className="text-lg font-light mb-3 text-gray-900 group-hover:text-blue-600 transition-colors"
|
||||
data-oid="c2:u7-s"
|
||||
>
|
||||
{resource.title}
|
||||
</h3>
|
||||
<p
|
||||
className="text-gray-600 font-light text-sm leading-relaxed"
|
||||
data-oid="c.eue5q"
|
||||
>
|
||||
{resource.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8" data-oid="ky447bf">
|
||||
<div className="max-w-4xl mx-auto" data-oid="tyktapc">
|
||||
<div className="text-center mb-16" data-oid="-egssn0">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-4 text-gray-900"
|
||||
data-oid="ddj969a"
|
||||
>
|
||||
{support.sections.faq.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600 font-light" data-oid="d8nfvq-">
|
||||
{support.sections.faq.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-6" data-oid="twq73md">
|
||||
{support.sections.faq.items.map((item: any, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white p-6 rounded-lg shadow-sm border border-gray-100"
|
||||
data-oid="vpw3zqy"
|
||||
>
|
||||
<h3
|
||||
className="text-lg font-light mb-3 text-gray-900 flex items-center"
|
||||
data-oid="-joy1m5"
|
||||
>
|
||||
<span
|
||||
className="w-6 h-6 bg-blue-100 text-blue-600 rounded-full flex items-center justify-center text-sm font-medium mr-3"
|
||||
data-oid="dh_hhfs"
|
||||
>
|
||||
Q
|
||||
</span>
|
||||
{item.question}
|
||||
</h3>
|
||||
<div className="ml-9" data-oid="x7nwh-6">
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed"
|
||||
data-oid="u_j--72"
|
||||
>
|
||||
{item.answer}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact CTA */}
|
||||
<section
|
||||
className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-900 text-white"
|
||||
data-oid="46znakk"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto text-center" data-oid="qc_rcu2">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-6" data-oid="_cfj:nm">
|
||||
{locale === 'en'
|
||||
? 'Still Need Help?'
|
||||
: locale === 'zh-TW'
|
||||
? '仍需要幫助?'
|
||||
: '仍需要帮助?'}
|
||||
</h2>
|
||||
<p className="text-xl font-light mb-8 opacity-90" data-oid="7qhi_:e">
|
||||
{locale === 'en'
|
||||
? 'Our support team is ready to assist you with any questions or issues.'
|
||||
: locale === 'zh-TW'
|
||||
? '我們的支援團隊隨時準備協助您解決任何問題。'
|
||||
: '我们的支持团队随时准备协助您解决任何问题。'}
|
||||
</p>
|
||||
<div
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center"
|
||||
data-oid="_feu0-2"
|
||||
>
|
||||
<button
|
||||
className="bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 transition-colors font-light"
|
||||
data-oid="cm4d1s6"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Contact Support'
|
||||
: locale === 'zh-TW'
|
||||
? '聯絡支援'
|
||||
: '联系支持'}
|
||||
</button>
|
||||
<button
|
||||
className="border border-white text-white px-8 py-3 rounded-lg hover:bg-white hover:text-gray-900 transition-colors font-light"
|
||||
data-oid="q6.5vlz"
|
||||
>
|
||||
{locale === 'en'
|
||||
? 'Schedule Call'
|
||||
: locale === 'zh-TW'
|
||||
? '預約通話'
|
||||
: '预约通话'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
34
app/[locale]/test-seo/page.tsx
Normal file
34
app/[locale]/test-seo/page.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Locale } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
|
||||
interface TestSEOPageProps {
|
||||
params: {
|
||||
locale: Locale;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const locales = ['zh-CN', 'zh-TW', 'en'];
|
||||
return locales.map((locale) => ({
|
||||
locale,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: TestSEOPageProps) {
|
||||
return generateSEOMetadata(params.locale, 'home');
|
||||
}
|
||||
|
||||
export default function TestSEOPage({ params }: TestSEOPageProps) {
|
||||
const { locale } = params;
|
||||
|
||||
return (
|
||||
<div className="p-8" data-oid="z5fb8n5">
|
||||
<h1 data-oid="tzdaaq:">SEO测试页面 - {locale}</h1>
|
||||
<p data-oid="p8ykx5x">检查页面的title、description和keywords是否正确显示</p>
|
||||
<div className="mt-4" data-oid="ua48xa6">
|
||||
<h2 data-oid="w5y4qgq">当前语言: {locale}</h2>
|
||||
<p data-oid="uq8d3e7">请查看浏览器标题栏和页面源代码中的meta标签</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
7
app/about/page.tsx
Normal file
7
app/about/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { defaultLocale } from '@/lib/i18n';
|
||||
|
||||
export default function AboutPage() {
|
||||
// Redirect to the localized version
|
||||
redirect(`/${defaultLocale}/about`);
|
||||
}
|
||||
BIN
app/favicon.ico
Normal file
BIN
app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
168
app/globals.css
Normal file
168
app/globals.css
Normal file
@ -0,0 +1,168 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--foreground-rgb: 0, 0, 0;
|
||||
--background-start-rgb: 214, 219, 220;
|
||||
--background-end-rgb: 255, 255, 255;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
/* Line clamp utilities for text truncation */
|
||||
.line-clamp-2 {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.line-clamp-3 {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 9%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
.dark {
|
||||
--background: 0 0% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
--accent: 0 0% 14.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 0% 83.1%;
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
--chart-4: 280 65% 60%;
|
||||
--chart-5: 340 75% 55%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
||||
/* 客服按钮样式优化 - 适配网页风格 */
|
||||
/* 使用更高优先级的选择器来覆盖第三方样式 */
|
||||
body [id*="hecong"] iframe,
|
||||
body [class*="hecong"] iframe,
|
||||
body iframe[src*="ahc.ink"],
|
||||
body div[style*="fixed"] iframe,
|
||||
body div[style*="bottom"] iframe,
|
||||
html [id*="hecong"] iframe,
|
||||
html [class*="hecong"] iframe,
|
||||
html iframe[src*="ahc.ink"] {
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 12px rgba(79, 156, 249, 0.15) !important;
|
||||
border: 1px solid rgba(79, 156, 249, 0.2) !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
background-color: #4F9CF9 !important;
|
||||
}
|
||||
|
||||
/* 悬停效果 - 增强选择器优先级 */
|
||||
body [id*="hecong"] iframe:hover,
|
||||
body [class*="hecong"] iframe:hover,
|
||||
body iframe[src*="ahc.ink"]:hover,
|
||||
body div[style*="fixed"] iframe:hover,
|
||||
body div[style*="bottom"] iframe:hover,
|
||||
html [id*="hecong"] iframe:hover,
|
||||
html [class*="hecong"] iframe:hover,
|
||||
html iframe[src*="ahc.ink"]:hover {
|
||||
transform: translateY(-2px) !important;
|
||||
box-shadow: 0 4px 20px rgba(79, 156, 249, 0.3) !important;
|
||||
border-color: rgba(79, 156, 249, 0.5) !important;
|
||||
background-color: #60A5FA !important;
|
||||
}
|
||||
|
||||
/* 确保客服组件在合适的层级 */
|
||||
body [id*="hecong"],
|
||||
body [class*="hecong"],
|
||||
html [id*="hecong"],
|
||||
html [class*="hecong"] {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
/* 客服聊天窗口样式优化 */
|
||||
body [id*="hecong-chat"],
|
||||
body [class*="hecong-chat"],
|
||||
body [id*="chat-window"],
|
||||
body [class*="chat-window"],
|
||||
html [id*="hecong-chat"],
|
||||
html [class*="hecong-chat"],
|
||||
html [id*="chat-window"],
|
||||
html [class*="chat-window"] {
|
||||
border-radius: 16px !important;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1) !important;
|
||||
border: 1px solid rgba(229, 231, 235, 0.8) !important;
|
||||
}
|
||||
|
||||
/* 针对可能的其他客服按钮选择器 */
|
||||
div[style*="position: fixed"][style*="bottom"][style*="right"] iframe,
|
||||
div[style*="position:fixed"][style*="bottom"][style*="right"] iframe,
|
||||
[style*="position: fixed"][style*="z-index"] iframe {
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 12px rgba(79, 156, 249, 0.15) !important;
|
||||
border: 1px solid rgba(79, 156, 249, 0.2) !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
background-color: #4F9CF9 !important;
|
||||
}
|
||||
198
app/layout.tsx
Normal file
198
app/layout.tsx
Normal file
@ -0,0 +1,198 @@
|
||||
import type { Metadata } from 'next';
|
||||
import Script from 'next/script';
|
||||
import './globals.css';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
template: '%s | HaoAWS',
|
||||
default: 'HaoAWS - 领先的AWS云服务与数字化转型解决方案提供商',
|
||||
},
|
||||
description:
|
||||
'HaoAWS专注AWS云服务与企业数字化转型,提供专业的云计算解决方案。服务800+成功案例,150+AWS专业团队,助力企业实现云端升级。',
|
||||
keywords: [
|
||||
'AWS云服务',
|
||||
'企业数字化转型',
|
||||
'云计算迁移服务',
|
||||
'云架构设计',
|
||||
'数据分析平台',
|
||||
],
|
||||
|
||||
authors: [{ name: 'HaoAWS', url: 'https://haoaws.com' }],
|
||||
creator: 'HaoAWS',
|
||||
publisher: 'HaoAWS',
|
||||
formatDetection: {
|
||||
email: false,
|
||||
address: false,
|
||||
telephone: false,
|
||||
},
|
||||
metadataBase: new URL('https://haoaws.com'),
|
||||
alternates: {
|
||||
canonical: '/',
|
||||
languages: {
|
||||
'zh-CN': '/',
|
||||
'zh-TW': '/zh-TW',
|
||||
en: '/en',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
type: 'website',
|
||||
locale: 'zh_CN',
|
||||
url: 'https://haoaws.com',
|
||||
siteName: 'HaoAWS',
|
||||
title: 'HaoAWS - 领先的AWS云服务与数字化转型解决方案提供商',
|
||||
description:
|
||||
'HaoAWS专注AWS云服务与企业数字化转型,提供专业的云计算解决方案。服务800+成功案例,150+AWS专业团队,助力企业实现云端升级。',
|
||||
images: [
|
||||
{
|
||||
url: '/og-image.jpg',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'HaoAWS - AWS云服务与数字化转型解决方案专家',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'HaoAWS - 领先的AWS云服务与数字化转型解决方案提供商',
|
||||
description: 'HaoAWS专注AWS云服务与企业数字化转型,提供专业的云计算解决方案。',
|
||||
images: ['/og-image.jpg'],
|
||||
creator: '@haoaws',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
googleBot: {
|
||||
index: true,
|
||||
follow: true,
|
||||
'max-video-preview': -1,
|
||||
'max-image-preview': 'large',
|
||||
'max-snippet': -1,
|
||||
},
|
||||
},
|
||||
verification: {
|
||||
google: 'your-google-verification-code',
|
||||
yandex: 'your-yandex-verification-code',
|
||||
yahoo: 'your-yahoo-verification-code',
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
|
||||
return (
|
||||
<html lang="zh-CN" data-oid="l6_rt4s">
|
||||
<head data-oid="qm2:6p3">
|
||||
<link rel="icon" href="/favicon.ico" data-oid="me:zhp-" />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/apple-touch-icon.png"
|
||||
data-oid="um.4go3"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="/favicon-32x32.png"
|
||||
data-oid="2kams1f"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="/favicon-16x16.png"
|
||||
data-oid="x1:e_kv"
|
||||
/>
|
||||
|
||||
<link rel="manifest" href="/site.webmanifest" data-oid="7.i_diy" />
|
||||
<meta name="theme-color" content="#ffffff" data-oid="pm_y3u3" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1"
|
||||
data-oid="y_ipvze"
|
||||
/>
|
||||
</head>
|
||||
<body className="" data-oid="exc9f3.">
|
||||
{children}
|
||||
|
||||
{/* Google Analytics */}
|
||||
<Script
|
||||
src="https://www.googletagmanager.com/gtag/js?id=G-E0ENRQGBZP"
|
||||
strategy="afterInteractive"
|
||||
/>
|
||||
<Script
|
||||
id="google-analytics"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-E0ENRQGBZP');
|
||||
`
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* AI客服系统 */}
|
||||
<Script
|
||||
id="ai-customer-service"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `(function(d,w,c){if(w[c])return;var s=d.createElement('script');w[c]=function(){(w[c].z=w[c].z||[]).push(arguments);};s.async=true;s.src='https://static.ahc.ink/hecong.js';if(d.head)d.head.appendChild(s);})(document,window,'_AIHECONG');_AIHECONG('ini',{channelId:'9BgJ9p'});`
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 客服按钮样式强制应用脚本 */}
|
||||
<Script
|
||||
id="customer-service-style"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
function applyCustomerServiceStyle() {
|
||||
const iframes = document.querySelectorAll('iframe[src*="ahc.ink"], div[style*="position: fixed"] iframe, div[style*="bottom"] iframe');
|
||||
iframes.forEach(iframe => {
|
||||
if (iframe && iframe.style) {
|
||||
iframe.style.borderRadius = '12px';
|
||||
iframe.style.boxShadow = '0 2px 12px rgba(79, 156, 249, 0.15)';
|
||||
iframe.style.border = '1px solid rgba(79, 156, 249, 0.2)';
|
||||
iframe.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
|
||||
iframe.style.backgroundColor = '#4F9CF9';
|
||||
|
||||
iframe.addEventListener('mouseenter', function() {
|
||||
this.style.transform = 'translateY(-2px)';
|
||||
this.style.boxShadow = '0 4px 20px rgba(79, 156, 249, 0.3)';
|
||||
this.style.borderColor = 'rgba(79, 156, 249, 0.5)';
|
||||
this.style.backgroundColor = '#60A5FA';
|
||||
});
|
||||
|
||||
iframe.addEventListener('mouseleave', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
this.style.boxShadow = '0 2px 12px rgba(79, 156, 249, 0.15)';
|
||||
this.style.borderColor = 'rgba(79, 156, 249, 0.2)';
|
||||
this.style.backgroundColor = '#4F9CF9';
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载后立即检查
|
||||
applyCustomerServiceStyle();
|
||||
|
||||
// 定期检查新加载的客服组件
|
||||
setInterval(applyCustomerServiceStyle, 1000);
|
||||
|
||||
// 监听DOM变化
|
||||
if (typeof MutationObserver !== 'undefined') {
|
||||
const observer = new MutationObserver(applyCustomerServiceStyle);
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
`
|
||||
}}
|
||||
/>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
297
app/news/[id]/page.tsx
Normal file
297
app/news/[id]/page.tsx
Normal file
@ -0,0 +1,297 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { getTranslations, Locale, getNavigationPaths, defaultLocale } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import { getNewsArticle, getAvailableLocalesForArticle, checkArticleExists } from '@/lib/markdown';
|
||||
import Layout from '@/components/Layout';
|
||||
import LanguageSwitcher from '@/components/LanguageSwitcher';
|
||||
import Link from 'next/link';
|
||||
|
||||
interface NewsDetailPageProps {
|
||||
params: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
// 默认语言的文章ID
|
||||
const articles = ['ai-transformation-2024', 'cloud-security-best-practices', 'company-expansion-2024'];
|
||||
return articles.map((id) => ({ id }));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: NewsDetailPageProps) {
|
||||
const { id } = params;
|
||||
const locale = defaultLocale; // 使用默认语言
|
||||
|
||||
// Check if article exists
|
||||
if (!checkArticleExists(id, locale)) {
|
||||
return {
|
||||
title: 'Article Not Found',
|
||||
description: 'The requested article could not be found.',
|
||||
};
|
||||
}
|
||||
|
||||
const article = await getNewsArticle(id, locale);
|
||||
if (!article) {
|
||||
return {
|
||||
title: 'Article Not Found',
|
||||
description: 'The requested article could not be found.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: article.title,
|
||||
description: article.excerpt,
|
||||
openGraph: {
|
||||
title: article.title,
|
||||
description: article.excerpt,
|
||||
type: 'article',
|
||||
publishedTime: article.date,
|
||||
authors: [article.author],
|
||||
tags: article.tags,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function NewsDetailPage({ params }: NewsDetailPageProps) {
|
||||
const { id } = params;
|
||||
const locale = defaultLocale; // 使用默认语言
|
||||
|
||||
// Check if article exists in the requested locale
|
||||
if (!checkArticleExists(id, locale)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const article = await getNewsArticle(id, locale);
|
||||
if (!article) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const [common, availableLocales] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getAvailableLocalesForArticle(id),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common}>
|
||||
{/* Breadcrumb */}
|
||||
<section className="py-4 px-4 sm:px-6 lg:px-8 bg-gray-50 border-b">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<nav className="flex items-center space-x-2 text-sm text-gray-600">
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'home')?.path || '/'}
|
||||
className="hover:text-blue-600 transition-colors"
|
||||
>
|
||||
{common.navigation.home}
|
||||
</Link>
|
||||
<span>/</span>
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'news')?.path || '/news'}
|
||||
className="hover:text-blue-600 transition-colors"
|
||||
>
|
||||
{common.navigation.news}
|
||||
</Link>
|
||||
<span>/</span>
|
||||
<span className="text-gray-900">{article.title}</span>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Language Switcher */}
|
||||
<section className="py-4 px-4 sm:px-6 lg:px-8 bg-white border-b">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm text-gray-600">可用语言:</span>
|
||||
<LanguageSwitcher
|
||||
currentLocale={locale}
|
||||
availableLocales={availableLocales}
|
||||
articleId={id}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Back to News */}
|
||||
<Link
|
||||
href={navigationPaths.find((p) => p.key === 'news')?.path || '/news'}
|
||||
className="text-sm text-blue-600 hover:text-blue-800 flex items-center space-x-1"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
<span>返回新闻</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Article Header */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center space-x-4 mb-6">
|
||||
<span className="px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full font-medium">
|
||||
{article.category}
|
||||
</span>
|
||||
{article.featured && (
|
||||
<span className="px-3 py-1 bg-red-100 text-red-800 text-sm rounded-full font-medium">
|
||||
精选
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl font-light leading-tight mb-6 text-gray-900">
|
||||
{article.title}
|
||||
</h1>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-6 text-gray-600 mb-6">
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span>{article.date}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
||||
</svg>
|
||||
<span>{article.author}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span>{article.readTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xl text-gray-600 font-light leading-relaxed">
|
||||
{article.excerpt}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
{article.tags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2 mb-8">
|
||||
{article.tags.map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full"
|
||||
>
|
||||
#{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Article Content */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="prose prose-lg prose-gray max-w-none">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
h1: ({ children }) => (
|
||||
<h1 className="text-3xl font-light mb-6 text-gray-900 border-b border-gray-200 pb-4">
|
||||
{children}
|
||||
</h1>
|
||||
),
|
||||
h2: ({ children }) => (
|
||||
<h2 className="text-2xl font-light mb-4 text-gray-900 mt-8">
|
||||
{children}
|
||||
</h2>
|
||||
),
|
||||
h3: ({ children }) => (
|
||||
<h3 className="text-xl font-light mb-3 text-gray-900 mt-6">
|
||||
{children}
|
||||
</h3>
|
||||
),
|
||||
p: ({ children }) => (
|
||||
<p className="mb-4 text-gray-700 leading-relaxed">
|
||||
{children}
|
||||
</p>
|
||||
),
|
||||
ul: ({ children }) => (
|
||||
<ul className="mb-4 pl-6 space-y-2">
|
||||
{children}
|
||||
</ul>
|
||||
),
|
||||
ol: ({ children }) => (
|
||||
<ol className="mb-4 pl-6 space-y-2 list-decimal">
|
||||
{children}
|
||||
</ol>
|
||||
),
|
||||
li: ({ children }) => (
|
||||
<li className="text-gray-700 leading-relaxed">
|
||||
{children}
|
||||
</li>
|
||||
),
|
||||
blockquote: ({ children }) => (
|
||||
<blockquote className="border-l-4 border-blue-600 pl-6 my-6 italic text-gray-600">
|
||||
{children}
|
||||
</blockquote>
|
||||
),
|
||||
code: ({ children }) => (
|
||||
<code className="bg-gray-100 px-2 py-1 rounded text-sm font-mono">
|
||||
{children}
|
||||
</code>
|
||||
),
|
||||
pre: ({ children }) => (
|
||||
<pre className="bg-gray-100 p-4 rounded-lg overflow-x-auto mb-4">
|
||||
{children}
|
||||
</pre>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{article.content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Related Articles */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-gray-50">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-2xl font-light mb-8 text-gray-900">相关文章</h2>
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{/* 这里可以添加相关文章的逻辑 */}
|
||||
<div className="bg-white rounded-lg p-6 shadow-sm">
|
||||
<h3 className="text-lg font-light mb-2 text-gray-900">更多新闻即将发布</h3>
|
||||
<p className="text-gray-600 text-sm">
|
||||
请持续关注我们的最新动态和行业见解。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
7
app/news/page.tsx
Normal file
7
app/news/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { defaultLocale } from '@/lib/i18n';
|
||||
|
||||
export default function NewsPage() {
|
||||
// Redirect to the localized version
|
||||
redirect(`/${defaultLocale}/news`);
|
||||
}
|
||||
48
app/page.tsx
Normal file
48
app/page.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { getTranslations, getNavigationPaths } from '@/lib/i18n';
|
||||
import { generateMetadata as generateSEOMetadata } from '@/lib/seo';
|
||||
import { getLatestNewsArticles } from '@/lib/markdown';
|
||||
import Layout from '@/components/Layout';
|
||||
import HomePageClient from '@/components/HomePageClient';
|
||||
|
||||
export async function generateMetadata() {
|
||||
return generateSEOMetadata('zh-CN', 'home');
|
||||
}
|
||||
|
||||
export default async function HomePage() {
|
||||
const locale = 'zh-CN'; // 根页面默认语言为简体中文
|
||||
const [common, home, latestNews] = await Promise.all([
|
||||
getTranslations(locale, 'common'),
|
||||
getTranslations(locale, 'home'),
|
||||
getLatestNewsArticles(locale, 3),
|
||||
]);
|
||||
|
||||
const navigationPaths = getNavigationPaths(locale);
|
||||
const navigation = [
|
||||
{
|
||||
name: common.navigation.home,
|
||||
href: navigationPaths.find((p) => p.key === 'home')?.path || '/',
|
||||
},
|
||||
{
|
||||
name: common.navigation.products,
|
||||
href: navigationPaths.find((p) => p.key === 'products')?.path || '/products',
|
||||
},
|
||||
{
|
||||
name: common.navigation.news,
|
||||
href: navigationPaths.find((p) => p.key === 'news')?.path || '/news',
|
||||
},
|
||||
{
|
||||
name: common.navigation.support,
|
||||
href: navigationPaths.find((p) => p.key === 'support')?.path || '/support',
|
||||
},
|
||||
{
|
||||
name: common.navigation.about,
|
||||
href: navigationPaths.find((p) => p.key === 'about')?.path || '/about',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout locale={locale} navigation={navigation} common={common}>
|
||||
<HomePageClient locale={locale} home={home} common={common} latestNews={latestNews} />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
7
app/products/page.tsx
Normal file
7
app/products/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { defaultLocale } from '@/lib/i18n';
|
||||
|
||||
export default function ProductsPage() {
|
||||
// Redirect to the localized version
|
||||
redirect(`/${defaultLocale}/products`);
|
||||
}
|
||||
12
app/robots.ts
Normal file
12
app/robots.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { MetadataRoute } from 'next';
|
||||
|
||||
export default function robots(): MetadataRoute.Robots {
|
||||
return {
|
||||
rules: {
|
||||
userAgent: '*',
|
||||
allow: '/',
|
||||
disallow: ['/api/', '/_next/', '/admin/'],
|
||||
},
|
||||
sitemap: 'https://haoaws.com/sitemap.xml',
|
||||
};
|
||||
}
|
||||
41
app/sitemap.ts
Normal file
41
app/sitemap.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { MetadataRoute } from 'next';
|
||||
import { locales, defaultLocale } from '@/lib/i18n';
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const baseUrl = 'https://haoaws.com';
|
||||
const pages = ['', 'about', 'products', 'news', 'support'];
|
||||
|
||||
const sitemap: MetadataRoute.Sitemap = [];
|
||||
|
||||
// Add pages for each locale
|
||||
locales.forEach((locale) => {
|
||||
pages.forEach((page) => {
|
||||
const url =
|
||||
locale === defaultLocale
|
||||
? `${baseUrl}${page ? `/${page}` : ''}`
|
||||
: `${baseUrl}/${locale}${page ? `/${page}` : ''}`;
|
||||
|
||||
sitemap.push({
|
||||
url,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: page === '' ? 'daily' : page === 'news' ? 'weekly' : 'monthly',
|
||||
priority: page === '' ? 1 : page === 'products' ? 0.9 : 0.8,
|
||||
alternates: {
|
||||
languages: locales.reduce(
|
||||
(acc, loc) => {
|
||||
const altUrl =
|
||||
loc === defaultLocale
|
||||
? `${baseUrl}${page ? `/${page}` : ''}`
|
||||
: `${baseUrl}/${loc}${page ? `/${page}` : ''}`;
|
||||
acc[loc] = altUrl;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
),
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return sitemap;
|
||||
}
|
||||
7
app/support/page.tsx
Normal file
7
app/support/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { defaultLocale } from '@/lib/i18n';
|
||||
|
||||
export default function SupportPage() {
|
||||
// Redirect to the localized version
|
||||
redirect(`/${defaultLocale}/support`);
|
||||
}
|
||||
98
build-static.js
Normal file
98
build-static.js
Normal file
@ -0,0 +1,98 @@
|
||||
const { spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 设置环境变量
|
||||
process.env.NEXT_DISABLE_TELEMETRY = '1';
|
||||
process.env.NODE_ENV = 'production';
|
||||
process.env.BUILD_MODE = 'static';
|
||||
|
||||
console.log('🚀 开始静态构建...');
|
||||
|
||||
// 清理函数
|
||||
function cleanup() {
|
||||
const dirs = ['.next', 'out'];
|
||||
dirs.forEach(dir => {
|
||||
try {
|
||||
if (fs.existsSync(dir)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
console.log(`✅ 清理了 ${dir} 目录`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`⚠️ 清理 ${dir} 时遇到问题,继续执行...`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 构建函数
|
||||
function build() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const buildProcess = spawn('npx', ['next', 'build'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
env: {
|
||||
...process.env,
|
||||
NEXT_DISABLE_TELEMETRY: '1',
|
||||
NODE_ENV: 'production',
|
||||
BUILD_MODE: 'static'
|
||||
}
|
||||
});
|
||||
|
||||
buildProcess.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
console.log('✅ 构建成功完成!');
|
||||
resolve();
|
||||
} else {
|
||||
console.log(`❌ 构建失败,退出码: ${code}`);
|
||||
reject(new Error(`Build failed with code ${code}`));
|
||||
}
|
||||
});
|
||||
|
||||
buildProcess.on('error', (error) => {
|
||||
console.error('❌ 构建过程出错:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 验证输出
|
||||
function verifyOutput() {
|
||||
const outDir = 'out';
|
||||
if (fs.existsSync(outDir)) {
|
||||
const files = fs.readdirSync(outDir);
|
||||
console.log(`✅ 输出目录包含 ${files.length} 个文件/文件夹`);
|
||||
|
||||
// 检查关键文件
|
||||
const keyFiles = ['index.html', 'zh-TW', 'en', '_next'];
|
||||
keyFiles.forEach(file => {
|
||||
if (files.includes(file)) {
|
||||
console.log(`✅ 找到: ${file}`);
|
||||
} else {
|
||||
console.log(`⚠️ 缺失: ${file}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('❌ 输出目录不存在');
|
||||
}
|
||||
}
|
||||
|
||||
// 主执行流程
|
||||
async function main() {
|
||||
try {
|
||||
console.log('🧹 清理旧文件...');
|
||||
cleanup();
|
||||
|
||||
console.log('🔨 开始构建...');
|
||||
await build();
|
||||
|
||||
console.log('🔍 验证输出...');
|
||||
verifyOutput();
|
||||
|
||||
console.log('🎉 静态构建完成! 使用 "npm run serve" 预览网站');
|
||||
} catch (error) {
|
||||
console.error('❌ 构建失败:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
20
components.json
Normal file
20
components.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "default",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "app/globals.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
}
|
||||
}
|
||||
153
components/Footer.tsx
Normal file
153
components/Footer.tsx
Normal file
@ -0,0 +1,153 @@
|
||||
import Link from 'next/link';
|
||||
import { Locale } from '@/lib/i18n';
|
||||
|
||||
interface FooterProps {
|
||||
locale: Locale;
|
||||
navigation: Array<{ name: string; href: string }>;
|
||||
common: {
|
||||
companyName: string;
|
||||
footer: {
|
||||
quickLinks: string;
|
||||
contactInfo: string;
|
||||
followUs: string;
|
||||
copyright: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default function Footer({ locale, navigation, common }: FooterProps) {
|
||||
const getCompanyDescription = () => {
|
||||
switch (locale) {
|
||||
case 'zh-CN':
|
||||
return '我们致力于为客户提供专业的AWS云服务解决方案,助力企业数字化转型';
|
||||
case 'zh-TW':
|
||||
return '我們致力於為客戶提供專業的AWS雲端服務解決方案,助力企業數位化轉型';
|
||||
case 'en':
|
||||
return 'We are committed to providing professional AWS cloud services solutions to help enterprises with digital transformation';
|
||||
default:
|
||||
return '我们致力于为客户提供专业的AWS云服务解决方案,助力企业数字化转型';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<footer className="py-12 px-4 sm:px-6 lg:px-8 border-t border-gray-100">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="grid md:grid-cols-4 gap-8 mb-8">
|
||||
{/* Company Info */}
|
||||
<div>
|
||||
<h3 className="font-light text-lg mb-4 text-gray-900">
|
||||
{common.companyName}
|
||||
</h3>
|
||||
<p className="text-gray-600 font-light text-sm leading-relaxed">
|
||||
{getCompanyDescription()}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
<div>
|
||||
<h4 className="font-light mb-4 text-gray-900">
|
||||
{common.footer.quickLinks}
|
||||
</h4>
|
||||
<ul className="space-y-2">
|
||||
{navigation.slice(1).map((item) => (
|
||||
<li key={item.name}>
|
||||
<Link
|
||||
href={item.href}
|
||||
className="text-gray-600 hover:text-gray-900 font-light text-sm transition-colors"
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Contact Info */}
|
||||
<div>
|
||||
<h4 className="font-light mb-4 text-gray-900">
|
||||
{common.footer.contactInfo}
|
||||
</h4>
|
||||
<div className="space-y-2 text-sm font-light text-gray-600">
|
||||
<p>
|
||||
<a href={`mailto:${common.footer.email}`} className="hover:text-gray-900 transition-colors">
|
||||
{common.footer.email}
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://wa.me/19174029875" target="_blank" rel="noopener noreferrer" className="hover:text-gray-900 transition-colors">
|
||||
WhatsApp: +1 917-402-9875
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Social Links */}
|
||||
<div>
|
||||
<h4 className="font-light mb-4 text-gray-900">
|
||||
{common.footer.followUs}
|
||||
</h4>
|
||||
<div className="flex space-x-4">
|
||||
{/* Telegram */}
|
||||
<a
|
||||
href="https://t.me/haoaws_official"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-600 hover:text-blue-500 transition-colors"
|
||||
title="Telegram"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.568 8.16l-1.642 7.702c-.123.559-.45.696-.913.433l-2.523-1.858-1.217 1.17c-.135.135-.249.249-.51.249l.182-2.576 4.71-4.253c.205-.182-.045-.283-.318-.1l-5.825 3.668-2.515-.785c-.547-.171-.558-.547.114-.81l9.826-3.784c.456-.171.856.1.706.81z"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{/* WhatsApp (as social link) */}
|
||||
<a
|
||||
href="https://wa.me/19174029875"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-600 hover:text-green-500 transition-colors"
|
||||
title="WhatsApp"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893A11.821 11.821 0 0020.885 3.488"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{/* Placeholder for future social icons */}
|
||||
<a
|
||||
href="#"
|
||||
className="text-gray-300 hover:text-green-500 transition-colors opacity-50 cursor-not-allowed"
|
||||
title="WeChat (Coming Soon)"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.152 4.203 2.943 5.539-.192.64-.576 1.627-.576 1.627s.96-.32 2.304-.8c.48.128.992.256 1.536.256 4.8 0 8.691-3.264 8.691-7.296 0-4.032-3.891-7.296-8.691-7.296z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Copyright */}
|
||||
<div className="pt-8 border-t border-gray-100">
|
||||
<p className="text-center text-gray-500 text-sm font-light">
|
||||
{common.footer.copyright}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
271
components/HomePageClient.tsx
Normal file
271
components/HomePageClient.tsx
Normal file
@ -0,0 +1,271 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { Locale, generateLocalizedPath } from '@/lib/i18n';
|
||||
import { NewsArticle } from '@/lib/markdown';
|
||||
|
||||
interface HomePageClientProps {
|
||||
locale: Locale;
|
||||
home: any;
|
||||
common: any;
|
||||
latestNews: NewsArticle[];
|
||||
}
|
||||
|
||||
export default function HomePageClient({ locale, home, common, latestNews }: HomePageClientProps) {
|
||||
const [currentSlide, setCurrentSlide] = useState(0);
|
||||
|
||||
// 生成新闻文章的链接
|
||||
const getNewsArticleUrl = (articleId: string) => {
|
||||
return generateLocalizedPath(`/news/${articleId}`, locale);
|
||||
};
|
||||
|
||||
// 生成新闻缩略图(使用Unsplash随机图片作为占位符)
|
||||
const getNewsImage = (index: number) => {
|
||||
const imageIds = [
|
||||
'photo-1560472354-b33ff0c44a43', // 科技主题
|
||||
'photo-1551434678-e076c223a692', // 云计算主题
|
||||
'photo-1581091226825-a6a2a5aee158' // AI主题
|
||||
];
|
||||
const imageId = imageIds[index % imageIds.length];
|
||||
return `https://images.unsplash.com/${imageId}?w=400&h=225&fit=crop`;
|
||||
};
|
||||
|
||||
// Banner carousel data
|
||||
const bannerSlides = [
|
||||
{
|
||||
id: 1,
|
||||
image: 'https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1200&h=600&fit=crop',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
image: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=1200&h=600&fit=crop',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
image: 'https://images.unsplash.com/photo-1557804506-669a67965ba0?w=1200&h=600&fit=crop',
|
||||
},
|
||||
];
|
||||
|
||||
// Auto-advance carousel
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setCurrentSlide((prev) => (prev + 1) % bannerSlides.length);
|
||||
}, 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
const nextSlide = () => {
|
||||
setCurrentSlide((prev) => (prev + 1) % bannerSlides.length);
|
||||
};
|
||||
|
||||
const prevSlide = () => {
|
||||
setCurrentSlide((prev) => (prev - 1 + bannerSlides.length) % bannerSlides.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Banner Carousel */}
|
||||
<section className="relative h-screen overflow-hidden">
|
||||
<div className="relative w-full h-full">
|
||||
{bannerSlides.map((slide, index) => (
|
||||
<div
|
||||
key={slide.id}
|
||||
className={`absolute inset-0 transition-opacity duration-1000 ${
|
||||
index === currentSlide ? 'opacity-100' : 'opacity-0'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-gray-900"
|
||||
style={{ backgroundImage: `url(${slide.image})` }}
|
||||
>
|
||||
<div className="absolute inset-0 bg-black/40"></div>
|
||||
<div className="relative z-10 flex items-center justify-center h-full">
|
||||
<div className="text-center text-white max-w-4xl px-4">
|
||||
<h2 className="text-4xl md:text-6xl font-light mb-6 leading-tight">
|
||||
{home.banner[index]?.title}
|
||||
</h2>
|
||||
<p className="text-xl md:text-2xl font-light opacity-90">
|
||||
{home.banner[index]?.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Carousel Controls */}
|
||||
<button
|
||||
onClick={prevSlide}
|
||||
className="absolute left-4 top-1/2 transform -translate-y-1/2 bg-white/20 hover:bg-white/30 text-white p-2 rounded-full transition-colors"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M15 19l-7-7 7-7"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
onClick={nextSlide}
|
||||
className="absolute right-4 top-1/2 transform -translate-y-1/2 bg-white/20 hover:bg-white/30 text-white p-2 rounded-full transition-colors"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{/* Carousel Indicators */}
|
||||
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2">
|
||||
{bannerSlides.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setCurrentSlide(index)}
|
||||
className={`w-3 h-3 rounded-full transition-colors ${
|
||||
index === currentSlide ? 'bg-white' : 'bg-white/50'
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<h1 className="text-4xl md:text-6xl font-light leading-tight mb-8 text-gray-900">
|
||||
{home.hero.title}
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-600 mb-12 font-light">
|
||||
{home.hero.subtitle}
|
||||
</p>
|
||||
<button className="bg-gray-900 text-white px-8 py-3 rounded-full hover:bg-gray-800 transition-colors font-light">
|
||||
{home.hero.button}
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-4 text-gray-900">
|
||||
{home.services.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600 font-light">{home.services.subtitle}</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{home.services.items.map((service: any, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white p-8 rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<h3 className="text-xl font-light mb-4 text-gray-900">
|
||||
{service.title}
|
||||
</h3>
|
||||
<p className="text-gray-600 font-light leading-relaxed">
|
||||
{service.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* News Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-4 text-gray-900">
|
||||
{home.news.title}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{latestNews.length > 0 ? latestNews.map((article, index) => (
|
||||
<Link key={article.id} href={getNewsArticleUrl(article.id)}>
|
||||
<article className="group cursor-pointer">
|
||||
<div className="aspect-video bg-gray-200 rounded-lg mb-4 overflow-hidden">
|
||||
<img
|
||||
src={getNewsImage(index)}
|
||||
alt={article.title}
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2 text-xs text-gray-500">
|
||||
<span className="bg-blue-100 text-blue-600 px-2 py-1 rounded">
|
||||
{article.category}
|
||||
</span>
|
||||
<span>{article.date}</span>
|
||||
<span>•</span>
|
||||
<span>{article.readTime}</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-light mb-2 text-gray-900 group-hover:text-gray-600 transition-colors line-clamp-2">
|
||||
{article.title}
|
||||
</h3>
|
||||
<p className="text-gray-600 font-light text-sm line-clamp-3">
|
||||
{article.excerpt}
|
||||
</p>
|
||||
{article.author && (
|
||||
<p className="text-xs text-gray-500 mt-2">
|
||||
{home.news.author}: {article.author}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
</Link>
|
||||
)) : (
|
||||
// 如果没有新闻数据,显示占位符
|
||||
[1, 2, 3].map((item) => (
|
||||
<article key={item} className="group cursor-pointer">
|
||||
<div className="aspect-video bg-gray-200 rounded-lg mb-4 overflow-hidden">
|
||||
<div className="w-full h-full bg-gradient-to-br from-gray-100 to-gray-200 group-hover:from-gray-200 group-hover:to-gray-300 transition-colors"></div>
|
||||
</div>
|
||||
<h3 className="text-lg font-light mb-2 text-gray-900 group-hover:text-gray-600 transition-colors">
|
||||
{home.news.sampleTitle} {item}
|
||||
</h3>
|
||||
<p className="text-gray-600 font-light text-sm">
|
||||
{home.news.sampleDate}
|
||||
</p>
|
||||
</article>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 查看更多新闻按钮 */}
|
||||
{latestNews.length > 0 && (
|
||||
<div className="text-center mt-12">
|
||||
<Link
|
||||
href={generateLocalizedPath('/news', locale)}
|
||||
className="inline-flex items-center px-6 py-3 border border-gray-300 text-gray-700 hover:text-gray-900 hover:border-gray-400 rounded-full transition-colors font-light"
|
||||
>
|
||||
{home.news.viewMore}
|
||||
<svg className="ml-2 w-4 h-4" 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>
|
||||
</section>
|
||||
|
||||
{/* Contact Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-900 text-white">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-4">{home.contact.title}</h2>
|
||||
<p className="text-xl font-light mb-8 opacity-90">{home.contact.description}</p>
|
||||
<button className="bg-white text-gray-900 px-8 py-3 rounded-full hover:bg-gray-100 transition-colors font-light">
|
||||
{common.common.contactNow}
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
314
components/HomePageSEO.tsx
Normal file
314
components/HomePageSEO.tsx
Normal file
@ -0,0 +1,314 @@
|
||||
'use client';
|
||||
|
||||
import { Locale, getTranslations } from '@/lib/i18n';
|
||||
import { getSEOData } from '@/lib/seo';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { SEOData } from '@/lib/seo';
|
||||
|
||||
interface HomePageSEOProps {
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
export default function HomePageSEO({ locale }: HomePageSEOProps) {
|
||||
const [seoData, setSeoData] = useState<SEOData | null>(null);
|
||||
const [homeData, setHomeData] = useState<any | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
const [seo, home] = await Promise.all([
|
||||
getSEOData(locale, 'home'),
|
||||
getTranslations(locale, 'home'),
|
||||
]);
|
||||
setSeoData(seo);
|
||||
setHomeData(home);
|
||||
} catch (error) {
|
||||
console.error('Failed to load SEO data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
loadData();
|
||||
}, [locale]);
|
||||
|
||||
const getLocalizedContent = () => {
|
||||
const content = {
|
||||
'zh-CN': {
|
||||
companyName: '创新科技',
|
||||
description: '专注企业数字化转型的科技公司',
|
||||
services: ['数字化转型咨询', 'ERP系统开发', 'AI数据分析', '云迁移服务', '网络安全'],
|
||||
address: '中国北京市朝阳区',
|
||||
phone: '+86-400-123-4567',
|
||||
email: 'contact@xintech',
|
||||
},
|
||||
'zh-TW': {
|
||||
companyName: '創新科技',
|
||||
description: '專注企業數位化轉型的科技公司',
|
||||
services: [
|
||||
'數位化轉型諮詢',
|
||||
'ERP系統開發',
|
||||
'AI數據分析',
|
||||
'雲端遷移服務',
|
||||
'網路安全',
|
||||
],
|
||||
|
||||
address: '中國北京市朝陽區',
|
||||
phone: '+86-400-123-4567',
|
||||
email: 'contact@xintech',
|
||||
},
|
||||
en: {
|
||||
companyName: 'Innovation Tech',
|
||||
description: 'Technology company focused on enterprise digital transformation',
|
||||
services: [
|
||||
'Digital Transformation Consulting',
|
||||
'ERP System Development',
|
||||
'AI Data Analytics',
|
||||
'Cloud Migration Services',
|
||||
'Cybersecurity',
|
||||
],
|
||||
|
||||
address: 'Chaoyang District, Beijing, China',
|
||||
phone: '+86-400-123-4567',
|
||||
email: 'contact@xintech',
|
||||
},
|
||||
};
|
||||
return content[locale] || content['zh-CN'];
|
||||
};
|
||||
|
||||
const content = getLocalizedContent();
|
||||
const baseUrl = 'https://xintech';
|
||||
const currentUrl = `${baseUrl}${locale === 'zh-CN' ? '' : `/${locale}`}`;
|
||||
|
||||
// Organization Schema
|
||||
const organizationSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
'@id': `${baseUrl}/#organization`,
|
||||
name: content.companyName,
|
||||
alternateName: 'Innovation Tech',
|
||||
description: content.description,
|
||||
url: currentUrl,
|
||||
logo: {
|
||||
'@type': 'ImageObject',
|
||||
url: `${baseUrl}/logo.png`,
|
||||
width: 300,
|
||||
height: 100,
|
||||
},
|
||||
image: `${baseUrl}/company-image.jpg`,
|
||||
telephone: content.phone,
|
||||
email: content.email,
|
||||
address: {
|
||||
'@type': 'PostalAddress',
|
||||
addressCountry: 'CN',
|
||||
addressLocality: 'Beijing',
|
||||
addressRegion: 'Beijing',
|
||||
streetAddress: content.address,
|
||||
},
|
||||
contactPoint: [
|
||||
{
|
||||
'@type': 'ContactPoint',
|
||||
telephone: content.phone,
|
||||
contactType: 'customer service',
|
||||
availableLanguage: ['Chinese', 'English'],
|
||||
areaServed: ['CN', 'US', 'GB', 'AU'],
|
||||
},
|
||||
{
|
||||
'@type': 'ContactPoint',
|
||||
email: content.email,
|
||||
contactType: 'sales',
|
||||
availableLanguage: ['Chinese', 'English'],
|
||||
},
|
||||
],
|
||||
|
||||
sameAs: [
|
||||
'https://www.linkedin.com/company/haoaws',
|
||||
'https://twitter.com/innovation_tech',
|
||||
'https://www.facebook.com/innovation.tech',
|
||||
'https://github.com/haoaws',
|
||||
],
|
||||
|
||||
foundingDate: '2010-01-01',
|
||||
numberOfEmployees: {
|
||||
'@type': 'QuantitativeValue',
|
||||
value: 150,
|
||||
},
|
||||
slogan:
|
||||
locale === 'en'
|
||||
? 'Leading Digital Transformation'
|
||||
: locale === 'zh-TW'
|
||||
? '引領數位化轉型'
|
||||
: '引领数字化转型',
|
||||
};
|
||||
|
||||
// Website Schema
|
||||
const websiteSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
'@id': `${baseUrl}/#website`,
|
||||
name: content.companyName,
|
||||
url: currentUrl,
|
||||
publisher: {
|
||||
'@id': `${baseUrl}/#organization`,
|
||||
},
|
||||
potentialAction: {
|
||||
'@type': 'SearchAction',
|
||||
target: {
|
||||
'@type': 'EntryPoint',
|
||||
urlTemplate: `${currentUrl}/search?q={search_term_string}`,
|
||||
},
|
||||
'query-input': 'required name=search_term_string',
|
||||
},
|
||||
inLanguage: locale === 'zh-CN' ? 'zh-CN' : locale === 'zh-TW' ? 'zh-TW' : 'en-US',
|
||||
};
|
||||
|
||||
// Service Schema
|
||||
const serviceSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Service',
|
||||
name:
|
||||
locale === 'en'
|
||||
? 'Digital Transformation Services'
|
||||
: locale === 'zh-TW'
|
||||
? '數位化轉型服務'
|
||||
: '数字化转型服务',
|
||||
description: content.description,
|
||||
provider: {
|
||||
'@id': `${baseUrl}/#organization`,
|
||||
},
|
||||
serviceType: content.services,
|
||||
areaServed: {
|
||||
'@type': 'Country',
|
||||
name: 'China',
|
||||
},
|
||||
hasOfferCatalog: {
|
||||
'@type': 'OfferCatalog',
|
||||
name:
|
||||
locale === 'en'
|
||||
? 'Digital Solutions'
|
||||
: locale === 'zh-TW'
|
||||
? '數位解決方案'
|
||||
: '数字解决方案',
|
||||
itemListElement: content.services.map((service, index) => ({
|
||||
'@type': 'Offer',
|
||||
itemOffered: {
|
||||
'@type': 'Service',
|
||||
name: service,
|
||||
},
|
||||
})),
|
||||
},
|
||||
};
|
||||
|
||||
// Local Business Schema
|
||||
const localBusinessSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'ProfessionalService',
|
||||
'@id': `${baseUrl}/#localbusiness`,
|
||||
name: content.companyName,
|
||||
description: content.description,
|
||||
url: currentUrl,
|
||||
telephone: content.phone,
|
||||
email: content.email,
|
||||
address: {
|
||||
'@type': 'PostalAddress',
|
||||
addressCountry: 'CN',
|
||||
addressLocality: 'Beijing',
|
||||
streetAddress: content.address,
|
||||
},
|
||||
geo: {
|
||||
'@type': 'GeoCoordinates',
|
||||
latitude: '39.9042',
|
||||
longitude: '116.4074',
|
||||
},
|
||||
openingHours: 'Mo-Fr 09:00-18:00',
|
||||
priceRange: '$',
|
||||
aggregateRating: {
|
||||
'@type': 'AggregateRating',
|
||||
ratingValue: '4.8',
|
||||
reviewCount: '150',
|
||||
bestRating: '5',
|
||||
worstRating: '1',
|
||||
},
|
||||
};
|
||||
|
||||
// FAQ Schema for common questions
|
||||
const faqSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: [
|
||||
{
|
||||
'@type': 'Question',
|
||||
name:
|
||||
locale === 'en'
|
||||
? 'What is digital transformation?'
|
||||
: locale === 'zh-TW'
|
||||
? '什麼是數位化轉型?'
|
||||
: '什么是数字化转型?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text:
|
||||
locale === 'en'
|
||||
? 'Digital transformation is the integration of digital technology into all areas of a business, fundamentally changing how you operate and deliver value to customers.'
|
||||
: locale === 'zh-TW'
|
||||
? '數位化轉型是將數位技術整合到企業的各個領域,從根本上改變企業的營運方式和為客戶提供價值的方式。'
|
||||
: '数字化转型是将数字技术整合到企业的各个领域,从根本上改变企业的运营方式和为客户提供价值的方式。',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name:
|
||||
locale === 'en'
|
||||
? 'How long does digital transformation take?'
|
||||
: locale === 'zh-TW'
|
||||
? '數位化轉型需要多長時間?'
|
||||
: '数字化转型需要多长时间?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text:
|
||||
locale === 'en'
|
||||
? 'Digital transformation timeline varies by company size and complexity, typically ranging from 6 months to 2 years for comprehensive transformation.'
|
||||
: locale === 'zh-TW'
|
||||
? '數位化轉型的時間因公司規模和複雜性而異,全面轉型通常需要6個月到2年的時間。'
|
||||
: '数字化转型的时间因公司规模和复杂性而异,全面转型通常需要6个月到2年的时间。',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(organizationSchema),
|
||||
}}
|
||||
/>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(websiteSchema),
|
||||
}}
|
||||
/>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(serviceSchema),
|
||||
}}
|
||||
/>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(localBusinessSchema),
|
||||
}}
|
||||
/>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(faqSchema),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
72
components/LanguageSwitcher.tsx
Normal file
72
components/LanguageSwitcher.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
'use client';
|
||||
|
||||
import { Locale, languages, generateLocalizedPath } from '@/lib/i18n';
|
||||
|
||||
interface LanguageSwitcherProps {
|
||||
currentLocale: Locale;
|
||||
availableLocales: Locale[];
|
||||
articleId: string;
|
||||
}
|
||||
|
||||
export default function LanguageSwitcher({
|
||||
currentLocale,
|
||||
availableLocales,
|
||||
articleId
|
||||
}: LanguageSwitcherProps) {
|
||||
const handleLanguageChange = (newLocale: Locale) => {
|
||||
// Set locale cookie
|
||||
document.cookie = `locale=${newLocale}; path=/; max-age=31536000`; // 1 year
|
||||
|
||||
// Navigate to the new path
|
||||
const newPath = generateLocalizedPath(`news/${articleId}`, newLocale);
|
||||
window.location.href = newPath;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex space-x-2">
|
||||
{languages.map((lang) => {
|
||||
const isAvailable = availableLocales.includes(lang.code);
|
||||
const isCurrent = lang.code === currentLocale;
|
||||
|
||||
if (!isAvailable) {
|
||||
return (
|
||||
<span
|
||||
key={lang.code}
|
||||
className="px-3 py-1 text-sm bg-gray-100 text-gray-400 rounded-full cursor-not-allowed"
|
||||
title={
|
||||
currentLocale === 'en'
|
||||
? 'Translation not available'
|
||||
: currentLocale === 'zh-TW'
|
||||
? '翻譯不可用'
|
||||
: '翻译不可用'
|
||||
}
|
||||
>
|
||||
{lang.flag} {lang.name}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (isCurrent) {
|
||||
return (
|
||||
<span
|
||||
key={lang.code}
|
||||
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-full"
|
||||
>
|
||||
{lang.flag} {lang.name}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
key={lang.code}
|
||||
onClick={() => handleLanguageChange(lang.code)}
|
||||
className="px-3 py-1 text-sm bg-gray-100 text-gray-700 hover:bg-gray-200 rounded-full transition-colors cursor-pointer"
|
||||
>
|
||||
{lang.flag} {lang.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
38
components/Layout.tsx
Normal file
38
components/Layout.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { Locale } from '@/lib/i18n';
|
||||
import Navigation from './Navigation';
|
||||
import Footer from './Footer';
|
||||
|
||||
interface LayoutProps {
|
||||
children: React.ReactNode;
|
||||
locale: Locale;
|
||||
navigation: Array<{ name: string; href: string }>;
|
||||
common: {
|
||||
companyName: string;
|
||||
footer: {
|
||||
quickLinks: string;
|
||||
contactInfo: string;
|
||||
followUs: string;
|
||||
copyright: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default function Layout({ children, locale, navigation, common }: LayoutProps) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white text-gray-900">
|
||||
<Navigation
|
||||
locale={locale}
|
||||
navigation={navigation}
|
||||
companyName={common.companyName}
|
||||
/>
|
||||
<main className="pt-16">{children}</main>
|
||||
<Footer
|
||||
locale={locale}
|
||||
navigation={navigation}
|
||||
common={common}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
212
components/Navigation.tsx
Normal file
212
components/Navigation.tsx
Normal file
@ -0,0 +1,212 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
Locale,
|
||||
languages,
|
||||
generateLocalizedPath,
|
||||
removeLocaleFromPath,
|
||||
} from '@/lib/i18n';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { useRouter, usePathname } from 'next/navigation';
|
||||
|
||||
interface NavigationProps {
|
||||
locale: Locale;
|
||||
navigation: Array<{ name: string; href: string }>;
|
||||
companyName: string;
|
||||
}
|
||||
|
||||
export default function Navigation({ locale, navigation, companyName }: NavigationProps) {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
|
||||
const handleLanguageChange = (newLocale: Locale) => {
|
||||
const currentPath = removeLocaleFromPath(pathname);
|
||||
const newPath = generateLocalizedPath(currentPath, newLocale);
|
||||
document.cookie = `locale=${newLocale}; path=/; max-age=31536000`;
|
||||
router.push(newPath);
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="fixed top-0 w-full bg-white/95 backdrop-blur-sm border-b border-gray-100 z-50">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
{/* Logo */}
|
||||
<div className="flex-shrink-0">
|
||||
<Link href={generateLocalizedPath('', locale)} className="flex items-center space-x-3">
|
||||
<Image
|
||||
src="/images/logo.png"
|
||||
alt={companyName ? `${companyName} Logo` : "HaoAWS Logo"}
|
||||
width={256}
|
||||
height={256}
|
||||
className="h-8 w-auto"
|
||||
priority
|
||||
/>
|
||||
<h1 className="text-xl font-light tracking-tight text-gray-900">
|
||||
{companyName}
|
||||
</h1>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:block">
|
||||
<div className="ml-10 flex items-baseline space-x-8">
|
||||
{navigation.map((item) => (
|
||||
<Link
|
||||
key={item.name}
|
||||
href={item.href}
|
||||
className="text-gray-600 hover:text-gray-900 px-3 py-2 text-sm font-light transition-colors"
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact Icons & Language Switcher */}
|
||||
<div className="flex items-center space-x-4">
|
||||
{/* Contact Icons */}
|
||||
<div className="hidden md:flex items-center space-x-3">
|
||||
{/* Telegram */}
|
||||
<a
|
||||
href="https://t.me/haoaws_official"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-600 hover:text-blue-500 transition-colors"
|
||||
title="Telegram"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.568 8.16l-1.642 7.702c-.123.559-.45.696-.913.433l-2.523-1.858-1.217 1.17c-.135.135-.249.249-.51.249l.182-2.576 4.71-4.253c.205-.182-.045-.283-.318-.1l-5.825 3.668-2.515-.785c-.547-.171-.558-.547.114-.81l9.826-3.784c.456-.171.856.1.706.81z"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{/* WhatsApp */}
|
||||
<a
|
||||
href="https://wa.me/19174029875"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-600 hover:text-green-500 transition-colors"
|
||||
title="WhatsApp"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893A11.821 11.821 0 0020.885 3.488"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{/* Placeholder for future social icons - currently disabled */}
|
||||
<a
|
||||
href="#"
|
||||
className="text-gray-300 hover:text-green-500 transition-colors opacity-50 cursor-not-allowed"
|
||||
title="WeChat (Coming Soon)"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.152 4.203 2.943 5.539-.192.64-.576 1.627-.576 1.627s.96-.32 2.304-.8c.48.128.992.256 1.536.256 4.8 0 8.691-3.264 8.691-7.296 0-4.032-3.891-7.296-8.691-7.296z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Language Switcher */}
|
||||
<div className="relative">
|
||||
<select
|
||||
value={locale}
|
||||
onChange={(e) => handleLanguageChange(e.target.value as Locale)}
|
||||
className="appearance-none bg-transparent border border-gray-200 rounded px-3 py-1 text-sm focus:outline-none focus:border-gray-400"
|
||||
>
|
||||
{languages.map((lang) => (
|
||||
<option key={lang.code} value={lang.code}>
|
||||
{lang.flag} {lang.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<button
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
className="md:hidden p-2"
|
||||
>
|
||||
<div className="w-6 h-6 flex flex-col justify-center items-center">
|
||||
<span
|
||||
className={`bg-gray-600 block transition-all duration-300 ease-out h-0.5 w-6 rounded-sm ${
|
||||
isMenuOpen
|
||||
? 'rotate-45 translate-y-1'
|
||||
: '-translate-y-0.5'
|
||||
}`}
|
||||
></span>
|
||||
<span
|
||||
className={`bg-gray-600 block transition-all duration-300 ease-out h-0.5 w-6 rounded-sm my-0.5 ${
|
||||
isMenuOpen ? 'opacity-0' : 'opacity-100'
|
||||
}`}
|
||||
></span>
|
||||
<span
|
||||
className={`bg-gray-600 block transition-all duration-300 ease-out h-0.5 w-6 rounded-sm ${
|
||||
isMenuOpen
|
||||
? '-rotate-45 -translate-y-1'
|
||||
: 'translate-y-0.5'
|
||||
}`}
|
||||
></span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation */}
|
||||
{isMenuOpen && (
|
||||
<div className="md:hidden">
|
||||
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t border-gray-100">
|
||||
{navigation.map((item) => (
|
||||
<Link
|
||||
key={item.name}
|
||||
href={item.href}
|
||||
className="text-gray-600 hover:text-gray-900 block px-3 py-2 text-base font-light"
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
|
||||
{/* Mobile Contact Icons */}
|
||||
<div className="flex items-center space-x-4 px-3 py-2">
|
||||
<a
|
||||
href="https://t.me/haoaws_official"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-600 hover:text-blue-500 transition-colors"
|
||||
title="Telegram"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.568 8.16l-1.642 7.702c-.123.559-.45.696-.913.433l-2.523-1.858-1.217 1.17c-.135.135-.249.249-.51.249l.182-2.576 4.71-4.253c.205-.182-.045-.283-.318-.1l-5.825 3.668-2.515-.785c-.547-.171-.558-.547.114-.81l9.826-3.784c.456-.171.856.1.706.81z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://wa.me/19174029875"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-600 hover:text-green-500 transition-colors"
|
||||
title="WhatsApp"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893A11.821 11.821 0 0020.885 3.488"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
95
components/SEOPreview.tsx
Normal file
95
components/SEOPreview.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
'use client';
|
||||
|
||||
import { Locale } from '@/lib/i18n';
|
||||
import { getSEOData, SEOData } from '@/lib/seo';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface SEOPreviewProps {
|
||||
locale: Locale;
|
||||
page: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function SEOPreview({ locale, page, className = '' }: SEOPreviewProps) {
|
||||
const [seoData, setSeoData] = useState<SEOData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const loadSEOData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getSEOData(locale, page);
|
||||
setSeoData(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to load SEO data:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadSEOData();
|
||||
}, [locale, page]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className={`animate-pulse ${className}`}>
|
||||
<div className="border rounded-lg p-4 bg-white shadow-sm">
|
||||
<div className="h-5 bg-gray-200 rounded mb-2"></div>
|
||||
<div className="h-4 bg-gray-200 rounded mb-1"></div>
|
||||
<div className="h-4 bg-gray-200 rounded w-2/3"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!seoData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const baseUrl = 'https://haoaws.com';
|
||||
const currentUrl = `${baseUrl}${locale === 'zh-CN' ? '' : `/${locale}`}${page === 'home' ? '' : `/${page}`}`;
|
||||
|
||||
return (
|
||||
<div className={`seo-preview ${className}`}>
|
||||
<h3 className="text-lg font-semibold mb-3">
|
||||
{locale === 'zh-CN'
|
||||
? '搜索引擎预览'
|
||||
: locale === 'zh-TW'
|
||||
? '搜尋引擎預覽'
|
||||
: 'Search Engine Preview'}
|
||||
</h3>
|
||||
|
||||
{/* Google Search Result Preview */}
|
||||
<div className="border rounded-lg p-4 bg-white shadow-sm mb-4">
|
||||
<div className="text-xs text-gray-600 mb-1">{currentUrl}</div>
|
||||
<h4 className="text-blue-600 text-lg hover:underline cursor-pointer mb-1">
|
||||
{seoData.title}
|
||||
</h4>
|
||||
<p className="text-sm text-gray-700 leading-relaxed">{seoData.description}</p>
|
||||
</div>
|
||||
|
||||
{/* Social Media Preview */}
|
||||
<div className="border rounded-lg p-4 bg-white shadow-sm">
|
||||
<h4 className="text-sm font-semibold mb-2">
|
||||
{locale === 'zh-CN'
|
||||
? '社交媒体预览'
|
||||
: locale === 'zh-TW'
|
||||
? '社群媒體預覽'
|
||||
: 'Social Media Preview'}
|
||||
</h4>
|
||||
<div className="border rounded bg-gray-50 p-3">
|
||||
<div className="w-full h-32 bg-gray-200 rounded mb-2 flex items-center justify-center text-gray-500 text-sm">
|
||||
{locale === 'zh-CN'
|
||||
? '预览图片'
|
||||
: locale === 'zh-TW'
|
||||
? '預覽圖片'
|
||||
: 'Preview Image'}
|
||||
</div>
|
||||
<h5 className="font-semibold text-sm mb-1">{seoData.title}</h5>
|
||||
<p className="text-xs text-gray-600 mb-1">{seoData.description}</p>
|
||||
<div className="text-xs text-gray-500">{currentUrl}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
146
components/StructuredData.tsx
Normal file
146
components/StructuredData.tsx
Normal file
@ -0,0 +1,146 @@
|
||||
import { Locale } from '@/lib/i18n';
|
||||
|
||||
interface StructuredDataProps {
|
||||
locale: Locale;
|
||||
page: string;
|
||||
}
|
||||
|
||||
export default function StructuredData({ locale, page }: StructuredDataProps) {
|
||||
const getOrganizationData = () => {
|
||||
const names = {
|
||||
'zh-CN': '创新科技',
|
||||
'zh-TW': '創新科技',
|
||||
en: 'Innovation Tech',
|
||||
};
|
||||
|
||||
const descriptions = {
|
||||
'zh-CN': '专注于企业数字化转型的科技公司',
|
||||
'zh-TW': '專注於企業數位化轉型的科技公司',
|
||||
en: 'Technology company focused on enterprise digital transformation',
|
||||
};
|
||||
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
name: names[locale],
|
||||
description: descriptions[locale],
|
||||
url: `https://haoaws.com${locale === 'zh-CN' ? '' : `/${locale}`}`,
|
||||
logo: 'https://haoaws.com/logo.png',
|
||||
contactPoint: {
|
||||
'@type': 'ContactPoint',
|
||||
telephone: '+86-400-123-4567',
|
||||
contactType: 'customer service',
|
||||
availableLanguage: ['Chinese', 'English'],
|
||||
},
|
||||
address: {
|
||||
'@type': 'PostalAddress',
|
||||
addressCountry: 'CN',
|
||||
addressLocality: 'Beijing',
|
||||
},
|
||||
sameAs: [
|
||||
'https://www.linkedin.com/company/haoaws',
|
||||
'https://twitter.com/innovation_tech',
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
const getWebsiteData = () => {
|
||||
const names = {
|
||||
'zh-CN': '创新科技官网',
|
||||
'zh-TW': '創新科技官網',
|
||||
en: 'Innovation Tech Official Website',
|
||||
};
|
||||
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
name: names[locale],
|
||||
url: `https://haoaws.com${locale === 'zh-CN' ? '' : `/${locale}`}`,
|
||||
potentialAction: {
|
||||
'@type': 'SearchAction',
|
||||
target: {
|
||||
'@type': 'EntryPoint',
|
||||
urlTemplate: `https://haoaws.com${locale === 'zh-CN' ? '' : `/${locale}`}/search?q={search_term_string}`,
|
||||
},
|
||||
'query-input': 'required name=search_term_string',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const getBreadcrumbData = () => {
|
||||
const pageNames = {
|
||||
'zh-CN': {
|
||||
home: '首页',
|
||||
about: '关于我们',
|
||||
products: '产品与服务',
|
||||
news: '新闻资讯',
|
||||
support: '客户支持',
|
||||
},
|
||||
'zh-TW': {
|
||||
home: '首頁',
|
||||
about: '關於我們',
|
||||
products: '產品與服務',
|
||||
news: '新聞資訊',
|
||||
support: '客戶支援',
|
||||
},
|
||||
en: {
|
||||
home: 'Home',
|
||||
about: 'About Us',
|
||||
products: 'Products & Services',
|
||||
news: 'News & Updates',
|
||||
support: 'Customer Support',
|
||||
},
|
||||
};
|
||||
|
||||
const baseUrl = `https://haoaws.com${locale === 'zh-CN' ? '' : `/${locale}`}`;
|
||||
|
||||
const breadcrumbList = [
|
||||
{
|
||||
'@type': 'ListItem',
|
||||
position: 1,
|
||||
name: pageNames[locale].home,
|
||||
item: baseUrl,
|
||||
},
|
||||
];
|
||||
|
||||
if (page !== 'home') {
|
||||
breadcrumbList.push({
|
||||
'@type': 'ListItem',
|
||||
position: 2,
|
||||
name: pageNames[locale][page as keyof (typeof pageNames)[typeof locale]],
|
||||
item: `${baseUrl}${page === 'home' ? '' : `/${page}`}`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: breadcrumbList,
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(getOrganizationData()),
|
||||
}}
|
||||
/>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(getWebsiteData()),
|
||||
}}
|
||||
/>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(getBreadcrumbData()),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
230
components/TDKConfigManager.tsx
Normal file
230
components/TDKConfigManager.tsx
Normal file
@ -0,0 +1,230 @@
|
||||
'use client';
|
||||
|
||||
import { Locale } from '@/lib/i18n';
|
||||
import { getSEOData, SEOData } from '@/lib/seo';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface TDKConfigManagerProps {
|
||||
locale: Locale;
|
||||
page: string;
|
||||
onSave?: (data: SEOData) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function TDKConfigManager({
|
||||
locale,
|
||||
page,
|
||||
onSave,
|
||||
className = '',
|
||||
}: TDKConfigManagerProps) {
|
||||
const [seoData, setSeoData] = useState<SEOData>({
|
||||
title: '',
|
||||
description: '',
|
||||
keywords: [],
|
||||
});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [newKeyword, setNewKeyword] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const loadSEOData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getSEOData(locale, page);
|
||||
setSeoData(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to load SEO data:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadSEOData();
|
||||
}, [locale, page]);
|
||||
|
||||
const handleSave = async () => {
|
||||
if (onSave) {
|
||||
setSaving(true);
|
||||
try {
|
||||
await onSave(seoData);
|
||||
alert(
|
||||
locale === 'zh-CN'
|
||||
? '保存成功!'
|
||||
: locale === 'zh-TW'
|
||||
? '儲存成功!'
|
||||
: 'Saved successfully!',
|
||||
);
|
||||
} catch (error) {
|
||||
alert(
|
||||
locale === 'zh-CN'
|
||||
? '保存失败!'
|
||||
: locale === 'zh-TW'
|
||||
? '儲存失敗!'
|
||||
: 'Save failed!',
|
||||
);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addKeyword = () => {
|
||||
if (newKeyword.trim() && !seoData.keywords.includes(newKeyword.trim())) {
|
||||
setSeoData({
|
||||
...seoData,
|
||||
keywords: [...seoData.keywords, newKeyword.trim()],
|
||||
});
|
||||
setNewKeyword('');
|
||||
}
|
||||
};
|
||||
|
||||
const removeKeyword = (index: number) => {
|
||||
setSeoData({
|
||||
...seoData,
|
||||
keywords: seoData.keywords.filter((_, i) => i !== index),
|
||||
});
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className={`animate-pulse ${className}`}>
|
||||
<div className="space-y-4">
|
||||
<div className="h-4 bg-gray-200 rounded"></div>
|
||||
<div className="h-20 bg-gray-200 rounded"></div>
|
||||
<div className="h-4 bg-gray-200 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`tdk-config-manager ${className}`}>
|
||||
<h3 className="text-lg font-semibold mb-4">
|
||||
{locale === 'zh-CN'
|
||||
? 'TDK配置管理'
|
||||
: locale === 'zh-TW'
|
||||
? 'TDK配置管理'
|
||||
: 'TDK Configuration'}
|
||||
</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Title */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
{locale === 'zh-CN' ? '标题' : locale === 'zh-TW' ? '標題' : 'Title'}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={seoData.title}
|
||||
onChange={(e) => setSeoData({ ...seoData, title: e.target.value })}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={
|
||||
locale === 'zh-CN'
|
||||
? '输入页面标题'
|
||||
: locale === 'zh-TW'
|
||||
? '輸入頁面標題'
|
||||
: 'Enter page title'
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="text-xs text-gray-500 mt-1">
|
||||
{seoData.title.length}/60{' '}
|
||||
{locale === 'zh-CN' ? '字符' : locale === 'zh-TW' ? '字元' : 'characters'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
{locale === 'zh-CN' ? '描述' : locale === 'zh-TW' ? '描述' : 'Description'}
|
||||
</label>
|
||||
<textarea
|
||||
value={seoData.description}
|
||||
onChange={(e) => setSeoData({ ...seoData, description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={
|
||||
locale === 'zh-CN'
|
||||
? '输入页面描述'
|
||||
: locale === 'zh-TW'
|
||||
? '輸入頁面描述'
|
||||
: 'Enter page description'
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="text-xs text-gray-500 mt-1">
|
||||
{seoData.description.length}/160{' '}
|
||||
{locale === 'zh-CN' ? '字符' : locale === 'zh-TW' ? '字元' : 'characters'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Keywords */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
{locale === 'zh-CN' ? '关键词' : locale === 'zh-TW' ? '關鍵詞' : 'Keywords'}
|
||||
</label>
|
||||
<div className="flex gap-2 mb-2">
|
||||
<input
|
||||
type="text"
|
||||
value={newKeyword}
|
||||
onChange={(e) => setNewKeyword(e.target.value)}
|
||||
onKeyPress={(e) => e.key === 'Enter' && addKeyword()}
|
||||
className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={
|
||||
locale === 'zh-CN'
|
||||
? '添加关键词'
|
||||
: locale === 'zh-TW'
|
||||
? '新增關鍵詞'
|
||||
: 'Add keyword'
|
||||
}
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={addKeyword}
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
{locale === 'zh-CN' ? '添加' : locale === 'zh-TW' ? '新增' : 'Add'}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{seoData.keywords.map((keyword, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="inline-flex items-center gap-1 bg-blue-100 text-blue-800 text-sm px-2 py-1 rounded"
|
||||
>
|
||||
{keyword}
|
||||
<button
|
||||
onClick={() => removeKeyword(index)}
|
||||
className="text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Save Button */}
|
||||
{onSave && (
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={saving}
|
||||
className="w-full px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 disabled:opacity-50"
|
||||
>
|
||||
{saving
|
||||
? locale === 'zh-CN'
|
||||
? '保存中...'
|
||||
: locale === 'zh-TW'
|
||||
? '儲存中...'
|
||||
: 'Saving...'
|
||||
: locale === 'zh-CN'
|
||||
? '保存配置'
|
||||
: locale === 'zh-TW'
|
||||
? '儲存配置'
|
||||
: 'Save Configuration'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
88
components/TDKManager.tsx
Normal file
88
components/TDKManager.tsx
Normal file
@ -0,0 +1,88 @@
|
||||
'use client';
|
||||
|
||||
import { Locale } from '@/lib/i18n';
|
||||
import { getSEOData, SEOData } from '@/lib/seo';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface TDKManagerProps {
|
||||
locale: Locale;
|
||||
page: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function TDKManager({ locale, page, className = '' }: TDKManagerProps) {
|
||||
const [seoData, setSeoData] = useState<SEOData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const loadSEOData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getSEOData(locale, page);
|
||||
setSeoData(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to load SEO data:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadSEOData();
|
||||
}, [locale, page]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className={`animate-pulse ${className}`}>
|
||||
<div className="h-4 bg-gray-200 rounded mb-2"></div>
|
||||
<div className="h-3 bg-gray-200 rounded mb-1"></div>
|
||||
<div className="h-3 bg-gray-200 rounded w-3/4"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!seoData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`tdk-info ${className}`}>
|
||||
<div className="mb-4">
|
||||
<h3 className="text-sm font-semibold text-gray-600 mb-1">
|
||||
{locale === 'zh-CN'
|
||||
? '页面标题'
|
||||
: locale === 'zh-TW'
|
||||
? '頁面標題'
|
||||
: 'Page Title'}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-800">{seoData.title}</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<h3 className="text-sm font-semibold text-gray-600 mb-1">
|
||||
{locale === 'zh-CN'
|
||||
? '页面描述'
|
||||
: locale === 'zh-TW'
|
||||
? '頁面描述'
|
||||
: 'Page Description'}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-800">{seoData.description}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-gray-600 mb-1">
|
||||
{locale === 'zh-CN' ? '关键词' : locale === 'zh-TW' ? '關鍵詞' : 'Keywords'}
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{seoData.keywords.map((keyword, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded"
|
||||
>
|
||||
{keyword}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
90
components/about/CertificationsSection.tsx
Normal file
90
components/about/CertificationsSection.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
interface CertificationsSectionProps {
|
||||
data: {
|
||||
title: string;
|
||||
items: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export default function CertificationsSection({ data }: CertificationsSectionProps) {
|
||||
return (
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50" data-oid="3cczmc2">
|
||||
<div className="max-w-5xl mx-auto" data-oid="yghb:oj">
|
||||
<div className="text-center mb-12" data-oid="_d8vhvs">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-4 text-gray-900"
|
||||
data-oid="21wse-i"
|
||||
>
|
||||
{data.title}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6" data-oid="jr6gmpg">
|
||||
{data.items.map((certification, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center p-6 bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
data-oid="nyq44rl"
|
||||
>
|
||||
<div
|
||||
className="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0"
|
||||
data-oid="djc0hl0"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6 text-green-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
data-oid="we9x9ea"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
data-oid="_dfri_o"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span
|
||||
className="text-gray-900 font-light leading-relaxed"
|
||||
data-oid="x4c2usp"
|
||||
>
|
||||
{certification}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Additional certification badges */}
|
||||
<div className="mt-12 text-center" data-oid="cssyfkc">
|
||||
<div className="flex flex-wrap justify-center gap-4" data-oid="h8e5xo:">
|
||||
<div
|
||||
className="bg-blue-100 text-blue-800 px-4 py-2 rounded-full text-sm font-medium"
|
||||
data-oid="klf4:.o"
|
||||
>
|
||||
🏆 Quality Certified
|
||||
</div>
|
||||
<div
|
||||
className="bg-green-100 text-green-800 px-4 py-2 rounded-full text-sm font-medium"
|
||||
data-oid="0cpr:jv"
|
||||
>
|
||||
🔒 Security Verified
|
||||
</div>
|
||||
<div
|
||||
className="bg-purple-100 text-purple-800 px-4 py-2 rounded-full text-sm font-medium"
|
||||
data-oid="tjnjk08"
|
||||
>
|
||||
🚀 Innovation Leader
|
||||
</div>
|
||||
<div
|
||||
className="bg-orange-100 text-orange-800 px-4 py-2 rounded-full text-sm font-medium"
|
||||
data-oid="nepx91x"
|
||||
>
|
||||
⭐ Excellence Award
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
95
components/about/CompanyMilestones.tsx
Normal file
95
components/about/CompanyMilestones.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
interface CompanyMilestonesProps {
|
||||
data: {
|
||||
title: string;
|
||||
items: Array<{
|
||||
year: string;
|
||||
title: string;
|
||||
description: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
export default function CompanyMilestones({ data }: CompanyMilestonesProps) {
|
||||
return (
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gray-50" data-oid="tm5on2x">
|
||||
<div className="max-w-6xl mx-auto" data-oid="a3fwh:i">
|
||||
<div className="text-center mb-16" data-oid="uszemd8">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-4 text-gray-900"
|
||||
data-oid="mlv_mj4"
|
||||
>
|
||||
{data.title}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="relative" data-oid="huer.yt">
|
||||
{/* Timeline line */}
|
||||
<div
|
||||
className="absolute left-1/2 transform -translate-x-1/2 w-0.5 h-full bg-gray-300 hidden md:block"
|
||||
data-oid="lg7p5-v"
|
||||
></div>
|
||||
|
||||
<div className="space-y-12" data-oid="qsjf7lk">
|
||||
{data.items.map((milestone, index) => (
|
||||
<div
|
||||
key={milestone.year}
|
||||
className={`flex flex-col md:flex-row items-center ${
|
||||
index % 2 === 0 ? 'md:flex-row' : 'md:flex-row-reverse'
|
||||
}`}
|
||||
data-oid="71-m4-e"
|
||||
>
|
||||
{/* Content */}
|
||||
<div
|
||||
className={`md:w-5/12 ${
|
||||
index % 2 === 0
|
||||
? 'md:text-right md:pr-8'
|
||||
: 'md:text-left md:pl-8'
|
||||
}`}
|
||||
data-oid="42s97ke"
|
||||
>
|
||||
<div
|
||||
className="bg-white p-6 rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
data-oid="r4f.q12"
|
||||
>
|
||||
<div
|
||||
className="inline-block bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm font-medium mb-3"
|
||||
data-oid="9kw-cq4"
|
||||
>
|
||||
{milestone.year}
|
||||
</div>
|
||||
<h3
|
||||
className="text-xl font-light mb-3 text-gray-900"
|
||||
data-oid="_0t-v-:"
|
||||
>
|
||||
{milestone.title}
|
||||
</h3>
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed"
|
||||
data-oid="r919o0s"
|
||||
>
|
||||
{milestone.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timeline dot */}
|
||||
<div
|
||||
className="md:w-2/12 flex justify-center my-6 md:my-0"
|
||||
data-oid="0f1ihf3"
|
||||
>
|
||||
<div
|
||||
className="w-6 h-6 bg-blue-600 rounded-full border-4 border-white shadow-lg relative z-10"
|
||||
data-oid=".he2ms6"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
{/* Spacer */}
|
||||
<div className="md:w-5/12" data-oid="6jk9dq3"></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
147
components/about/CompanyOverview.tsx
Normal file
147
components/about/CompanyOverview.tsx
Normal file
@ -0,0 +1,147 @@
|
||||
interface CompanyOverviewProps {
|
||||
data: {
|
||||
title: string;
|
||||
description: string;
|
||||
mission: {
|
||||
title: string;
|
||||
content: string;
|
||||
};
|
||||
vision: {
|
||||
title: string;
|
||||
content: string;
|
||||
};
|
||||
values: {
|
||||
title: string;
|
||||
items: Array<{
|
||||
name: string;
|
||||
description: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default function CompanyOverview({ data }: CompanyOverviewProps) {
|
||||
const getValueIcon = (index: number) => {
|
||||
const icons = ['💡', '🎯', '🤝', '🌟'];
|
||||
return icons[index] || '⭐';
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8" data-oid="778f74o">
|
||||
<div className="max-w-6xl mx-auto" data-oid="q-ohudw">
|
||||
<div className="text-center mb-16" data-oid="c1:a026">
|
||||
<h2
|
||||
className="text-3xl md:text-4xl font-light mb-6 text-gray-900"
|
||||
data-oid="2qfsl5_"
|
||||
>
|
||||
{data.title}
|
||||
</h2>
|
||||
<p
|
||||
className="text-lg text-gray-600 font-light leading-relaxed max-w-4xl mx-auto"
|
||||
data-oid="m88jlxe"
|
||||
>
|
||||
{data.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Mission & Vision */}
|
||||
<div className="grid md:grid-cols-2 gap-12 mb-20" data-oid="t.3l_2w">
|
||||
<div
|
||||
className="bg-white p-8 rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
data-oid="909qo8m"
|
||||
>
|
||||
<div className="text-center" data-oid="47d0qdo">
|
||||
<div
|
||||
className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-6"
|
||||
data-oid="hynyq5c"
|
||||
>
|
||||
<span className="text-2xl" data-oid="g9fipps">
|
||||
🎯
|
||||
</span>
|
||||
</div>
|
||||
<h3
|
||||
className="text-xl font-light mb-4 text-gray-900"
|
||||
data-oid=".ocipcn"
|
||||
>
|
||||
{data.mission.title}
|
||||
</h3>
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed"
|
||||
data-oid="nkfsl1s"
|
||||
>
|
||||
{data.mission.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="bg-white p-8 rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
data-oid="3fftkw6"
|
||||
>
|
||||
<div className="text-center" data-oid="4oqt-b9">
|
||||
<div
|
||||
className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-6"
|
||||
data-oid="zazpp6s"
|
||||
>
|
||||
<span className="text-2xl" data-oid="2uu_92e">
|
||||
🚀
|
||||
</span>
|
||||
</div>
|
||||
<h3
|
||||
className="text-xl font-light mb-4 text-gray-900"
|
||||
data-oid=":kmcck4"
|
||||
>
|
||||
{data.vision.title}
|
||||
</h3>
|
||||
<p
|
||||
className="text-gray-600 font-light leading-relaxed"
|
||||
data-oid="hyh_bth"
|
||||
>
|
||||
{data.vision.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Core Values */}
|
||||
<div className="text-center" data-oid="fpfopj4">
|
||||
<h3
|
||||
className="text-2xl md:text-3xl font-light mb-12 text-gray-900"
|
||||
data-oid="sdrp81y"
|
||||
>
|
||||
{data.values.title}
|
||||
</h3>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8" data-oid="7a:fm47">
|
||||
{data.values.items.map((value, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white p-6 rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
data-oid="c.t9z6:"
|
||||
>
|
||||
<div
|
||||
className="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4"
|
||||
data-oid="kxf2tqa"
|
||||
>
|
||||
<span className="text-2xl" data-oid="c.4uoyu">
|
||||
{getValueIcon(index)}
|
||||
</span>
|
||||
</div>
|
||||
<h4
|
||||
className="text-lg font-light mb-3 text-gray-900"
|
||||
data-oid="ij-6led"
|
||||
>
|
||||
{value.name}
|
||||
</h4>
|
||||
<p
|
||||
className="text-gray-600 font-light text-sm leading-relaxed"
|
||||
data-oid="qk9i:oi"
|
||||
>
|
||||
{value.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
64
components/about/TeamSection.tsx
Normal file
64
components/about/TeamSection.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
interface TeamSectionProps {
|
||||
data: {
|
||||
title: string;
|
||||
description: string;
|
||||
stats: Array<{
|
||||
number: string;
|
||||
label: string;
|
||||
}>;
|
||||
departments: Array<{
|
||||
name: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
export default function TeamSection({ data }: TeamSectionProps) {
|
||||
return (
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-light mb-4 text-gray-900">
|
||||
{data.title}
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600 font-light max-w-3xl mx-auto">
|
||||
{data.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Team Stats */}
|
||||
<div className="bg-white rounded-lg shadow-sm p-8 mb-16">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
|
||||
{data.stats.map((stat, index) => (
|
||||
<div key={index} className="text-center">
|
||||
<div className="text-4xl md:text-5xl font-light text-blue-600 mb-2">
|
||||
{stat.number}
|
||||
</div>
|
||||
<div className="text-gray-600 font-light">{stat.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Departments */}
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{data.departments.map((department, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="text-center p-6 bg-white rounded-lg shadow-sm hover:shadow-md transition-all duration-300 hover:-translate-y-1"
|
||||
>
|
||||
<div className="text-5xl mb-4">{department.icon}</div>
|
||||
<h3 className="text-lg font-light mb-3 text-gray-900">
|
||||
{department.name}
|
||||
</h3>
|
||||
<p className="text-gray-600 font-light text-sm leading-relaxed">
|
||||
{department.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
129
data/locales/en/about.json
Normal file
129
data/locales/en/about.json
Normal file
@ -0,0 +1,129 @@
|
||||
{
|
||||
"title": "About Us",
|
||||
"subtitle": "Discover our journey, values, and the passionate team driving innovation in digital transformation",
|
||||
"sections": {
|
||||
"company": {
|
||||
"title": "Company Overview",
|
||||
"description": "HaoAWS was founded in 2010 as a pioneering technology company dedicated to AWS cloud services and enterprise digital transformation. With over a decade of experience, we have evolved into a trusted partner for businesses seeking to leverage professional cloud computing solutions. Our commitment to excellence and innovation has helped hundreds of enterprises maintain competitive advantages in the rapidly evolving cloud landscape.",
|
||||
"mission": {
|
||||
"title": "Our Mission",
|
||||
"content": "To empower businesses through professional AWS cloud services solutions that drive cloud-based digital transformation, enhance operational efficiency, and unlock new opportunities for growth and value creation in the cloud economy."
|
||||
},
|
||||
"vision": {
|
||||
"title": "Our Vision",
|
||||
"content": "To become the world's most trusted partner in AWS cloud services, setting industry standards for cloud innovation, quality, and customer success while fostering a sustainable cloud future."
|
||||
},
|
||||
"values": {
|
||||
"title": "Core Values",
|
||||
"items": [
|
||||
{
|
||||
"name": "Innovation",
|
||||
"description": "Embracing creativity and pushing technological boundaries to deliver breakthrough solutions"
|
||||
},
|
||||
{
|
||||
"name": "Excellence",
|
||||
"description": "Maintaining the highest standards in everything we do, from code quality to customer service"
|
||||
},
|
||||
{
|
||||
"name": "Integrity",
|
||||
"description": "Building trust through transparency, honesty, and ethical business practices"
|
||||
},
|
||||
{
|
||||
"name": "Collaboration",
|
||||
"description": "Fostering partnerships that create mutual value and drive collective success"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"milestones": {
|
||||
"title": "Our Journey",
|
||||
"items": [
|
||||
{
|
||||
"year": "2010",
|
||||
"title": "Foundation & Vision",
|
||||
"description": "HaoAWS was established with a vision to revolutionize enterprise cloud services and digital solutions"
|
||||
},
|
||||
{
|
||||
"year": "2013",
|
||||
"title": "Strategic Expansion",
|
||||
"description": "Expanded our expertise into system integration and technical consulting, serving Fortune 500 companies"
|
||||
},
|
||||
{
|
||||
"year": "2016",
|
||||
"title": "AWS Cloud Revolution",
|
||||
"description": "Became official AWS partner, launched comprehensive cloud computing and advanced data analytics services, pioneering cloud-first solutions"
|
||||
},
|
||||
{
|
||||
"year": "2019",
|
||||
"title": "Global Reach",
|
||||
"description": "Established international presence, serving clients across North America, Europe, and Asia-Pacific regions"
|
||||
},
|
||||
{
|
||||
"year": "2022",
|
||||
"title": "Cloud-Native Innovation",
|
||||
"description": "Successfully integrated AWS cloud-native and machine learning technologies into our product ecosystem"
|
||||
},
|
||||
{
|
||||
"year": "2024",
|
||||
"title": "Future Forward",
|
||||
"description": "Leading the next wave of digital transformation with AWS emerging technologies and sustainable cloud solutions"
|
||||
}
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"title": "Our Team",
|
||||
"description": "Our diverse team of experts combines deep technical knowledge with industry experience to deliver exceptional results",
|
||||
"stats": [
|
||||
{
|
||||
"number": "150+",
|
||||
"label": "Expert Professionals"
|
||||
},
|
||||
{
|
||||
"number": "800+",
|
||||
"label": "Successful Projects"
|
||||
},
|
||||
{
|
||||
"number": "75+",
|
||||
"label": "Global Partners"
|
||||
},
|
||||
{
|
||||
"number": "14+",
|
||||
"label": "Years of Excellence"
|
||||
}
|
||||
],
|
||||
"departments": [
|
||||
{
|
||||
"name": "Research & Development",
|
||||
"description": "Driving innovation through cutting-edge research and product development",
|
||||
"icon": "💻"
|
||||
},
|
||||
{
|
||||
"name": "Business Development",
|
||||
"description": "Building strategic partnerships and expanding market presence globally",
|
||||
"icon": "📈"
|
||||
},
|
||||
{
|
||||
"name": "Customer Success",
|
||||
"description": "Ensuring client satisfaction through dedicated support and consultation",
|
||||
"icon": "🛠️"
|
||||
},
|
||||
{
|
||||
"name": "Project Excellence",
|
||||
"description": "Delivering projects on time and exceeding quality expectations",
|
||||
"icon": "📋"
|
||||
}
|
||||
]
|
||||
},
|
||||
"certifications": {
|
||||
"title": "Certifications & Recognition",
|
||||
"items": [
|
||||
"AWS Advanced Technology Partner Certification",
|
||||
"AWS Solutions Architect Professional Certification",
|
||||
"AWS Security Specialty Certification",
|
||||
"ISO 9001:2015 Quality Management System Certification",
|
||||
"ISO 27001:2013 Information Security Management Certification",
|
||||
"CMMI Level 5 Software Development Maturity Certification"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
24
data/locales/en/common.json
Normal file
24
data/locales/en/common.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"navigation": {
|
||||
"home": "Home",
|
||||
"products": "Products & Services",
|
||||
"news": "News",
|
||||
"support": "Customer Support",
|
||||
"about": "About Us"
|
||||
},
|
||||
"common": {
|
||||
"companyName": "HaoAWS",
|
||||
"learnMore": "Learn More",
|
||||
"contactNow": "Contact Now",
|
||||
"readMore": "Read More",
|
||||
"backToHome": "Back to Home"
|
||||
},
|
||||
"footer": {
|
||||
"quickLinks": "Quick Links",
|
||||
"contactInfo": "Contact Info",
|
||||
"followUs": "Follow Us",
|
||||
"copyright": "© 2024 HaoAWS. All rights reserved.",
|
||||
"email": "contact@haoaws.com",
|
||||
"phone": "+86 400-123-4567"
|
||||
}
|
||||
}
|
||||
63
data/locales/en/home.json
Normal file
63
data/locales/en/home.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"seo": {
|
||||
"title": "HaoAWS - Leading AWS Cloud Services & Digital Transformation Provider",
|
||||
"description": "HaoAWS specializes in AWS cloud services and enterprise digital transformation with 800+ successful cases. Offering comprehensive cloud architecture design, data analytics platforms, cloud migration, cybersecurity solutions. 150+ AWS expert team, 24/7 technical support, helping enterprises achieve cloud upgrades and boost operational efficiency by 300%. Contact now for free cloud assessment!",
|
||||
"keywords": [
|
||||
"AWS cloud services",
|
||||
"enterprise digital transformation",
|
||||
"cloud migration services",
|
||||
"cloud architecture design",
|
||||
"big data analytics platform",
|
||||
"enterprise system integration",
|
||||
"cloud consulting services"
|
||||
]
|
||||
},
|
||||
"hero": {
|
||||
"title": "Leading the Future of Cloud Technology Innovation",
|
||||
"subtitle": "We are committed to providing professional AWS cloud services solutions to help enterprises with digital transformation",
|
||||
"button": "Learn More"
|
||||
},
|
||||
"services": {
|
||||
"title": "Our Services",
|
||||
"subtitle": "Professional technical team providing comprehensive solutions",
|
||||
"items": [
|
||||
{
|
||||
"title": "Technical Consulting",
|
||||
"description": "Professional technical consulting services to help enterprises develop optimal technical solutions"
|
||||
},
|
||||
{
|
||||
"title": "Product Development",
|
||||
"description": "From concept to product, we provide complete development services"
|
||||
},
|
||||
{
|
||||
"title": "System Integration",
|
||||
"description": "Integrate various systems and platforms to improve enterprise operational efficiency"
|
||||
}
|
||||
]
|
||||
},
|
||||
"news": {
|
||||
"title": "Latest News",
|
||||
"sampleTitle": "News Title",
|
||||
"sampleDate": "January 2024",
|
||||
"viewMore": "View More News",
|
||||
"author": "Author"
|
||||
},
|
||||
"contact": {
|
||||
"title": "Contact Us",
|
||||
"description": "For any questions or requirements, feel free to contact our professional team anytime"
|
||||
},
|
||||
"banner": [
|
||||
{
|
||||
"title": "HaoAWS, Leading the Cloud Future",
|
||||
"subtitle": "Professional AWS Cloud Solutions, Excellent Service Experience"
|
||||
},
|
||||
{
|
||||
"title": "Quality Cloud Service, Trustworthy",
|
||||
"subtitle": "Years of AWS Practice Experience, Providing You with the Best Cloud Service"
|
||||
},
|
||||
{
|
||||
"title": "Global Cloud Deployment, Creating Brilliance Together",
|
||||
"subtitle": "Moving Forward with Partners Around the World in the Cloud"
|
||||
}
|
||||
]
|
||||
}
|
||||
97
data/locales/en/news.json
Normal file
97
data/locales/en/news.json
Normal file
@ -0,0 +1,97 @@
|
||||
{
|
||||
"title": "News & Updates",
|
||||
"subtitle": "Stay updated with the latest industry trends and company news",
|
||||
"readMore": "Read More",
|
||||
"categories": [
|
||||
{
|
||||
"id": "company",
|
||||
"name": "Company News"
|
||||
},
|
||||
{
|
||||
"id": "industry",
|
||||
"name": "Industry News"
|
||||
},
|
||||
{
|
||||
"id": "technology",
|
||||
"name": "Technology Updates"
|
||||
},
|
||||
{
|
||||
"id": "events",
|
||||
"name": "Events"
|
||||
}
|
||||
],
|
||||
"articles": [
|
||||
{
|
||||
"id": "ai-transformation-2024",
|
||||
"title": "2024 AI-Powered Enterprise Digital Transformation Trends",
|
||||
"category": "Technology",
|
||||
"date": "January 15, 2024",
|
||||
"excerpt": "Exploring how artificial intelligence technology drives enterprise digital transformation and future development trends. Discover the latest AI innovations reshaping business operations.",
|
||||
"content": "With the rapid development of artificial intelligence technology, more and more enterprises are beginning to integrate AI technology into their business processes...",
|
||||
"author": "Technical Team",
|
||||
"readTime": "5 min read",
|
||||
"tags": ["Artificial Intelligence", "Digital Transformation", "Enterprise Management"],
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"id": "cloud-security-best-practices",
|
||||
"title": "Cloud Security Best Practices: Protecting Your Data Assets",
|
||||
"category": "Technology",
|
||||
"date": "January 10, 2024",
|
||||
"excerpt": "Comprehensive guide to cloud security best practices that help enterprises build secure and reliable cloud infrastructure while maintaining operational efficiency.",
|
||||
"content": "In the era of cloud computing, data security is one of the most concerning issues for enterprises. This article will introduce cloud security best practices...",
|
||||
"author": "Security Expert",
|
||||
"readTime": "8 min read",
|
||||
"tags": ["Cloud Security", "Data Protection", "Best Practices"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "company-expansion-2024",
|
||||
"title": "Global Expansion: New Service Centers Across Three Continents",
|
||||
"category": "Company News",
|
||||
"date": "January 8, 2024",
|
||||
"excerpt": "To better serve our growing international client base, we have strategically opened new service centers in key markets across North America, Europe, and Asia.",
|
||||
"content": "With the rapid development of our business, we are pleased to announce the addition of new service centers in strategic locations...",
|
||||
"author": "Management Team",
|
||||
"readTime": "3 min read",
|
||||
"tags": ["Company News", "Business Expansion", "Service Centers"],
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"id": "industry-report-2024",
|
||||
"title": "2024 Software Industry Development Report: Key Insights",
|
||||
"category": "Industry",
|
||||
"date": "January 5, 2024",
|
||||
"excerpt": "In-depth analysis of software industry development trends, emerging technologies, and market opportunities that will shape the industry in 2024 and beyond.",
|
||||
"content": "According to the latest market research data, the software industry will continue to maintain strong growth momentum in 2024...",
|
||||
"author": "Market Research Department",
|
||||
"readTime": "12 min read",
|
||||
"tags": ["Industry Report", "Market Analysis", "Development Trends"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "tech-conference-2024",
|
||||
"title": "Join Us at the 2024 International Technology Summit",
|
||||
"category": "Events",
|
||||
"date": "January 3, 2024",
|
||||
"excerpt": "We're excited to participate in the upcoming International Technology Summit. Visit our booth to explore cutting-edge solutions and network with industry leaders.",
|
||||
"content": "We are honored to announce that we will participate in the International Technology Conference to be held in March 2024...",
|
||||
"author": "Marketing Department",
|
||||
"readTime": "2 min read",
|
||||
"tags": ["Technology Conference", "Exhibition", "Networking"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "new-partnership",
|
||||
"title": "Strategic Partnership Announcement: Driving Innovation Together",
|
||||
"category": "Company News",
|
||||
"date": "January 1, 2024",
|
||||
"excerpt": "We're proud to announce a strategic partnership with a leading technology innovator, combining our expertise to deliver next-generation solutions to our clients.",
|
||||
"content": "We are pleased to announce that we have established a strategic partnership with a well-known technology company in the industry...",
|
||||
"author": "Business Development Department",
|
||||
"readTime": "4 min read",
|
||||
"tags": ["Partnership", "Strategic Cooperation", "Innovation"],
|
||||
"featured": true
|
||||
}
|
||||
]
|
||||
}
|
||||
128
data/locales/en/products.json
Normal file
128
data/locales/en/products.json
Normal file
@ -0,0 +1,128 @@
|
||||
{
|
||||
"title": "Products & Services",
|
||||
"subtitle": "Comprehensive technology solutions designed to accelerate your digital transformation journey",
|
||||
"categories": [
|
||||
{
|
||||
"id": "software",
|
||||
"name": "Software Development",
|
||||
"description": "Custom software development services",
|
||||
"icon": "💻"
|
||||
},
|
||||
{
|
||||
"id": "consulting",
|
||||
"name": "Technical Consulting",
|
||||
"description": "Professional technical consulting and planning",
|
||||
"icon": "🔍"
|
||||
},
|
||||
{
|
||||
"id": "integration",
|
||||
"name": "System Integration",
|
||||
"description": "Enterprise-level system integration solutions",
|
||||
"icon": "🔗"
|
||||
},
|
||||
{
|
||||
"id": "cloud",
|
||||
"name": "Cloud Services",
|
||||
"description": "Cloud computing and data storage solutions",
|
||||
"icon": "☁️"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"id": "erp-system",
|
||||
"title": "Enterprise Resource Planning System",
|
||||
"category": "software",
|
||||
"description": "Comprehensive enterprise resource management solution designed to streamline business processes, enhance operational efficiency, and provide real-time insights across all departments.",
|
||||
"features": [
|
||||
"Financial Management",
|
||||
"Human Resources",
|
||||
"Supply Chain Management",
|
||||
"Customer Relationship Management",
|
||||
"Inventory Control",
|
||||
"Business Intelligence"
|
||||
],
|
||||
"price": "Contact us for pricing",
|
||||
"icon": "🏢"
|
||||
},
|
||||
{
|
||||
"id": "data-analytics",
|
||||
"title": "Advanced Data Analytics Platform",
|
||||
"category": "software",
|
||||
"description": "Powerful AI-driven data analysis and visualization platform that transforms raw data into actionable business insights with machine learning capabilities.",
|
||||
"features": [
|
||||
"Real-time Data Processing",
|
||||
"Interactive Dashboards",
|
||||
"Predictive Analytics",
|
||||
"Machine Learning Models",
|
||||
"Custom Reports",
|
||||
"Data Visualization"
|
||||
],
|
||||
"price": "Contact us for pricing",
|
||||
"icon": "📊"
|
||||
},
|
||||
{
|
||||
"id": "digital-transformation",
|
||||
"title": "Digital Transformation Consulting",
|
||||
"category": "consulting",
|
||||
"description": "Strategic consulting services that guide organizations through comprehensive digital transformation, from assessment to implementation and optimization.",
|
||||
"features": [
|
||||
"Digital Maturity Assessment",
|
||||
"Transformation Roadmap",
|
||||
"Technology Architecture",
|
||||
"Change Management",
|
||||
"Implementation Support",
|
||||
"Performance Monitoring"
|
||||
],
|
||||
"price": "Contact us for pricing",
|
||||
"icon": "🚀"
|
||||
},
|
||||
{
|
||||
"id": "cloud-migration",
|
||||
"title": "Cloud Migration & Optimization",
|
||||
"category": "cloud",
|
||||
"description": "End-to-end cloud migration services with zero-downtime deployment, security optimization, and ongoing performance management.",
|
||||
"features": [
|
||||
"Cloud Strategy Planning",
|
||||
"Migration Assessment",
|
||||
"Security Implementation",
|
||||
"Performance Optimization",
|
||||
"Cost Management",
|
||||
"24/7 Monitoring"
|
||||
],
|
||||
"price": "Contact us for pricing",
|
||||
"icon": "☁️"
|
||||
},
|
||||
{
|
||||
"id": "ai-solutions",
|
||||
"title": "AI & Machine Learning Solutions",
|
||||
"category": "software",
|
||||
"description": "Custom artificial intelligence and machine learning solutions that automate processes, enhance decision-making, and drive innovation.",
|
||||
"features": [
|
||||
"Natural Language Processing",
|
||||
"Computer Vision",
|
||||
"Predictive Modeling",
|
||||
"Process Automation",
|
||||
"Intelligent Chatbots",
|
||||
"Recommendation Systems"
|
||||
],
|
||||
"price": "Contact us for pricing",
|
||||
"icon": "🤖"
|
||||
},
|
||||
{
|
||||
"id": "cybersecurity",
|
||||
"title": "Cybersecurity Solutions",
|
||||
"category": "consulting",
|
||||
"description": "Comprehensive cybersecurity services to protect your digital assets, ensure compliance, and maintain business continuity.",
|
||||
"features": [
|
||||
"Security Assessment",
|
||||
"Threat Detection",
|
||||
"Incident Response",
|
||||
"Compliance Management",
|
||||
"Employee Training",
|
||||
"Continuous Monitoring"
|
||||
],
|
||||
"price": "Contact us for pricing",
|
||||
"icon": "🔒"
|
||||
}
|
||||
]
|
||||
}
|
||||
101
data/locales/en/support.json
Normal file
101
data/locales/en/support.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"title": "Customer Support",
|
||||
"subtitle": "We are committed to providing you with the highest quality customer service",
|
||||
"sections": {
|
||||
"faq": {
|
||||
"title": "Frequently Asked Questions",
|
||||
"subtitle": "Find answers to common questions",
|
||||
"items": [
|
||||
{
|
||||
"id": "pricing",
|
||||
"question": "How can I get product pricing?",
|
||||
"answer": "You can get product pricing through the following methods: 1. Fill out our online consultation form; 2. Call our sales hotline; 3. Send an email to sales@haoaws.com. Our sales team will contact you within 24 hours."
|
||||
},
|
||||
{
|
||||
"id": "implementation",
|
||||
"question": "How long does product implementation take?",
|
||||
"answer": "Implementation time depends on the complexity and scale of the project. Generally, small projects take 2-4 weeks, medium projects take 1-3 months, and large projects may take 3-6 months. We will provide detailed time planning before the project starts."
|
||||
},
|
||||
{
|
||||
"id": "support",
|
||||
"question": "What technical support services do you provide?",
|
||||
"answer": "We provide comprehensive technical support services, including: 7x24 online support, phone support, remote assistance, on-site service, training services, etc. Different service levels have different response time guarantees."
|
||||
},
|
||||
{
|
||||
"id": "training",
|
||||
"question": "Do you provide user training?",
|
||||
"answer": "Yes, we provide comprehensive user training services, including: online training, on-site training, and customized training courses. Training content covers product usage, best practices, troubleshooting, and more."
|
||||
},
|
||||
{
|
||||
"id": "customization",
|
||||
"question": "Do your products support customization?",
|
||||
"answer": "Our products are highly configurable and also support custom development. Our technical team can customize features and adjust interfaces according to your specific needs."
|
||||
}
|
||||
]
|
||||
},
|
||||
"contact": {
|
||||
"title": "Contact Us",
|
||||
"subtitle": "Multiple ways to reach our support team",
|
||||
"methods": [
|
||||
{
|
||||
"type": "phone",
|
||||
"title": "Phone Support",
|
||||
"value": "+86 400-123-4567",
|
||||
"description": "Weekdays 9:00-18:00",
|
||||
"icon": "📞"
|
||||
},
|
||||
{
|
||||
"type": "email",
|
||||
"title": "Email Support",
|
||||
"value": "support@haoaws.com",
|
||||
"description": "Reply within 24 hours",
|
||||
"icon": "📧"
|
||||
},
|
||||
{
|
||||
"type": "chat",
|
||||
"title": "Live Chat",
|
||||
"value": "Start conversation now",
|
||||
"description": "Weekdays 9:00-18:00",
|
||||
"icon": "💬"
|
||||
},
|
||||
{
|
||||
"type": "ticket",
|
||||
"title": "Ticket System",
|
||||
"value": "Submit technical ticket",
|
||||
"description": "Track issue resolution progress",
|
||||
"icon": "🎫"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": {
|
||||
"title": "Help Resources",
|
||||
"subtitle": "Rich documentation and resources to help you better use our products",
|
||||
"items": [
|
||||
{
|
||||
"type": "documentation",
|
||||
"title": "Product Documentation",
|
||||
"description": "Detailed product usage instructions and API documentation",
|
||||
"icon": "📚"
|
||||
},
|
||||
{
|
||||
"type": "tutorials",
|
||||
"title": "Video Tutorials",
|
||||
"description": "Step-by-step video tutorials and operation guides",
|
||||
"icon": "🎥"
|
||||
},
|
||||
{
|
||||
"type": "community",
|
||||
"title": "User Community",
|
||||
"description": "Exchange experiences and best practices with other users",
|
||||
"icon": "👥"
|
||||
},
|
||||
{
|
||||
"type": "downloads",
|
||||
"title": "Download Center",
|
||||
"description": "Software downloads, update packages and related tools",
|
||||
"icon": "⬇️"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
128
data/locales/zh-CN/about.json
Normal file
128
data/locales/zh-CN/about.json
Normal file
@ -0,0 +1,128 @@
|
||||
{
|
||||
"title": "关于我们",
|
||||
"subtitle": "了解我们的使命、愿景和团队",
|
||||
"sections": {
|
||||
"company": {
|
||||
"title": "公司简介",
|
||||
"description": "HaoAWS是一家专注于AWS云服务与企业数字化转型的科技公司。我们致力于为客户提供最专业的云计算解决方案,帮助企业在云时代保持竞争优势。",
|
||||
"mission": {
|
||||
"title": "我们的使命",
|
||||
"content": "通过专业的AWS云服务解决方案,帮助企业实现云端数字化转型,提升运营效率,创造更大价值。"
|
||||
},
|
||||
"vision": {
|
||||
"title": "我们的愿景",
|
||||
"content": "成为全球领先的AWS云服务提供商,推动云技术创新,引领企业云端转型。"
|
||||
},
|
||||
"values": {
|
||||
"title": "核心价值观",
|
||||
"items": [
|
||||
{
|
||||
"name": "创新",
|
||||
"description": "持续创新,追求技术突破"
|
||||
},
|
||||
{
|
||||
"name": "专业",
|
||||
"description": "专业的技术能力和服务水准"
|
||||
},
|
||||
{
|
||||
"name": "诚信",
|
||||
"description": "诚实守信,建立长期合作关系"
|
||||
},
|
||||
{
|
||||
"name": "共赢",
|
||||
"description": "与客户、合作伙伴共同成长"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"milestones": {
|
||||
"title": "发展历程",
|
||||
"items": [
|
||||
{
|
||||
"year": "2010",
|
||||
"title": "公司成立",
|
||||
"description": "HaoAWS正式成立,开始专注于企业云计算服务"
|
||||
},
|
||||
{
|
||||
"year": "2013",
|
||||
"title": "业务拓展",
|
||||
"description": "扩展到系统集成和技术咨询领域"
|
||||
},
|
||||
{
|
||||
"year": "2016",
|
||||
"title": "AWS服务启动",
|
||||
"description": "正式成为AWS合作伙伴,推出专业云计算和数据分析服务"
|
||||
},
|
||||
{
|
||||
"year": "2019",
|
||||
"title": "国际化发展",
|
||||
"description": "开始为海外客户提供服务"
|
||||
},
|
||||
{
|
||||
"year": "2022",
|
||||
"title": "云原生技术整合",
|
||||
"description": "将AWS云原生和AI服务整合到产品和服务中"
|
||||
},
|
||||
{
|
||||
"year": "2024",
|
||||
"title": "持续创新",
|
||||
"description": "继续在AWS云服务领域深耕,助力更多企业云端转型"
|
||||
}
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"title": "我们的团队",
|
||||
"description": "我们拥有一支经验丰富、充满活力的专业团队",
|
||||
"stats": [
|
||||
{
|
||||
"number": "100+",
|
||||
"label": "专业员工"
|
||||
},
|
||||
{
|
||||
"number": "500+",
|
||||
"label": "成功项目"
|
||||
},
|
||||
{
|
||||
"number": "50+",
|
||||
"label": "合作伙伴"
|
||||
},
|
||||
{
|
||||
"number": "10+",
|
||||
"label": "服务年限"
|
||||
}
|
||||
],
|
||||
"departments": [
|
||||
{
|
||||
"name": "研发部门",
|
||||
"description": "负责产品研发和技术创新",
|
||||
"icon": "💻"
|
||||
},
|
||||
{
|
||||
"name": "销售部门",
|
||||
"description": "负责市场开拓和客户服务",
|
||||
"icon": "📈"
|
||||
},
|
||||
{
|
||||
"name": "技术支持",
|
||||
"description": "提供专业的技术支持服务",
|
||||
"icon": "🛠️"
|
||||
},
|
||||
{
|
||||
"name": "项目管理",
|
||||
"description": "确保项目按时高质量交付",
|
||||
"icon": "📋"
|
||||
}
|
||||
]
|
||||
},
|
||||
"certifications": {
|
||||
"title": "资质认证",
|
||||
"items": [
|
||||
"AWS 高级技术合作伙伴认证",
|
||||
"ISO 9001质量管理体系认证",
|
||||
"ISO 27001信息安全管理体系认证",
|
||||
"CMMI 3级软件能力成熟度认证",
|
||||
"高新技术企业认证"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
24
data/locales/zh-CN/common.json
Normal file
24
data/locales/zh-CN/common.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"navigation": {
|
||||
"home": "首页",
|
||||
"products": "产品与服务",
|
||||
"news": "新闻资讯",
|
||||
"support": "客户支持",
|
||||
"about": "关于我们"
|
||||
},
|
||||
"common": {
|
||||
"companyName": "HaoAWS",
|
||||
"learnMore": "了解更多",
|
||||
"contactNow": "立即联系",
|
||||
"readMore": "阅读更多",
|
||||
"backToHome": "返回首页"
|
||||
},
|
||||
"footer": {
|
||||
"quickLinks": "快速链接",
|
||||
"contactInfo": "联系方式",
|
||||
"followUs": "关注我们",
|
||||
"copyright": "© 2024 HaoAWS. 保留所有权利.",
|
||||
"email": "contact@haoaws.com",
|
||||
"phone": "+86 400-123-4567"
|
||||
}
|
||||
}
|
||||
63
data/locales/zh-CN/home.json
Normal file
63
data/locales/zh-CN/home.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"seo": {
|
||||
"title": "HaoAWS - 企业云计算与数字化转型解决方案专家",
|
||||
"description": "HaoAWS专注于为企业提供AWS云服务和数字化转型解决方案,包括云架构设计、数据分析平台、云迁移服务等。助力企业提升运营效率,实现可持续发展。",
|
||||
"keywords": [
|
||||
"AWS云服务",
|
||||
"数字化转型",
|
||||
"云计算服务",
|
||||
"云架构设计",
|
||||
"云迁移服务",
|
||||
"数据分析",
|
||||
"系统集成"
|
||||
]
|
||||
},
|
||||
"hero": {
|
||||
"title": "引领云端技术创新",
|
||||
"subtitle": "我们致力于为客户提供专业的AWS云服务解决方案,助力企业数字化转型",
|
||||
"button": "了解更多"
|
||||
},
|
||||
"services": {
|
||||
"title": "我们的服务",
|
||||
"subtitle": "专业的技术团队,为您提供全方位的解决方案",
|
||||
"items": [
|
||||
{
|
||||
"title": "技术咨询",
|
||||
"description": "专业的技术咨询服务,帮助企业制定最优的技术方案"
|
||||
},
|
||||
{
|
||||
"title": "产品开发",
|
||||
"description": "从概念到产品,我们提供完整的开发服务"
|
||||
},
|
||||
{
|
||||
"title": "系统集成",
|
||||
"description": "整合各种系统和平台,提高企业运营效率"
|
||||
}
|
||||
]
|
||||
},
|
||||
"news": {
|
||||
"title": "最新资讯",
|
||||
"sampleTitle": "新闻标题",
|
||||
"sampleDate": "2024年1月",
|
||||
"viewMore": "查看更多新闻",
|
||||
"author": "作者"
|
||||
},
|
||||
"contact": {
|
||||
"title": "联系我们",
|
||||
"description": "有任何问题或需求,欢迎随时联系我们的专业团队"
|
||||
},
|
||||
"banner": [
|
||||
{
|
||||
"title": "HaoAWS,引领云端未来",
|
||||
"subtitle": "专业的AWS云服务解决方案,卓越的服务体验"
|
||||
},
|
||||
{
|
||||
"title": "品质云服务,值得信赖",
|
||||
"subtitle": "多年AWS实践经验,为您提供最优质的云服务"
|
||||
},
|
||||
{
|
||||
"title": "全球云部署,共创辉煌",
|
||||
"subtitle": "与世界各地的合作伙伴在云端携手前行"
|
||||
}
|
||||
]
|
||||
}
|
||||
97
data/locales/zh-CN/news.json
Normal file
97
data/locales/zh-CN/news.json
Normal file
@ -0,0 +1,97 @@
|
||||
{
|
||||
"title": "新闻资讯",
|
||||
"subtitle": "掌握最新的行业动态和公司发展资讯",
|
||||
"readMore": "阅读更多",
|
||||
"categories": [
|
||||
{
|
||||
"id": "company",
|
||||
"name": "公司新闻"
|
||||
},
|
||||
{
|
||||
"id": "industry",
|
||||
"name": "行业资讯"
|
||||
},
|
||||
{
|
||||
"id": "technology",
|
||||
"name": "技术动态"
|
||||
},
|
||||
{
|
||||
"id": "events",
|
||||
"name": "活动公告"
|
||||
}
|
||||
],
|
||||
"articles": [
|
||||
{
|
||||
"id": "ai-transformation-2024",
|
||||
"title": "2024年人工智能助力企业数字化转型新趋势",
|
||||
"category": "技术动态",
|
||||
"date": "2024年1月15日",
|
||||
"excerpt": "深入探讨人工智能技术如何推动企业数字化转型,以及塑造未来商业运营的创新趋势。发现重新定义企业运营的最新AI创新技术。",
|
||||
"content": "随着人工智能技术的快速发展,越来越多的企业开始将AI技术融入到业务流程中...",
|
||||
"author": "技术团队",
|
||||
"readTime": "5分钟阅读",
|
||||
"tags": ["人工智能", "数字化转型", "企业管理"],
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"id": "cloud-security-best-practices",
|
||||
"title": "云安全最佳实践:保护您的数据资产",
|
||||
"category": "技术动态",
|
||||
"date": "2024年1月10日",
|
||||
"excerpt": "全面的云安全最佳实践指南,帮助企业构建安全可靠的云基础设施,同时保持运营效率。",
|
||||
"content": "在云计算时代,数据安全是企业最关心的问题之一。本文将介绍云安全的最佳实践...",
|
||||
"author": "安全专家",
|
||||
"readTime": "8分钟阅读",
|
||||
"tags": ["云安全", "数据保护", "最佳实践"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "company-expansion-2024",
|
||||
"title": "全球扩展:跨三大洲新设服务中心",
|
||||
"category": "公司新闻",
|
||||
"date": "2024年1月8日",
|
||||
"excerpt": "为了更好地服务不断增长的国际客户群,我们战略性地在北美、欧洲和亚洲的关键市场开设了新的服务中心。",
|
||||
"content": "随着业务的快速发展,我们很高兴地宣布在战略性地点新增了服务中心...",
|
||||
"author": "管理团队",
|
||||
"readTime": "3分钟阅读",
|
||||
"tags": ["公司新闻", "业务拓展", "服务中心"],
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"id": "industry-report-2024",
|
||||
"title": "2024年软件行业发展报告:关键洞察",
|
||||
"category": "行业资讯",
|
||||
"date": "2024年1月5日",
|
||||
"excerpt": "深度分析软件行业发展趋势、新兴技术,以及将在2024年及未来塑造行业的市场机遇。",
|
||||
"content": "根据最新的市场调研数据,2024年软件行业将继续保持强劲的增长势头...",
|
||||
"author": "市场研究部",
|
||||
"readTime": "12分钟阅读",
|
||||
"tags": ["行业报告", "市场分析", "发展趋势"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "tech-conference-2024",
|
||||
"title": "加入我们参与2024年国际技术峰会",
|
||||
"category": "活动公告",
|
||||
"date": "2024年1月3日",
|
||||
"excerpt": "我们很兴奋能参与即将举行的国际技术峰会。欢迎莅临我们的展台,探索尖端解决方案并与行业领袖交流。",
|
||||
"content": "我们很荣幸地宣布,将参加2024年3月举行的国际技术大会...",
|
||||
"author": "市场部",
|
||||
"readTime": "2分钟阅读",
|
||||
"tags": ["技术大会", "展览", "交流"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "new-partnership",
|
||||
"title": "战略合作伙伴关系公告:携手推动创新",
|
||||
"category": "公司新闻",
|
||||
"date": "2024年1月1日",
|
||||
"excerpt": "我们很自豪地宣布与领先的技术创新者建立战略合作伙伴关系,结合我们的专业知识为客户提供下一代解决方案。",
|
||||
"content": "我们很高兴地宣布,与业界知名的科技公司建立了战略合作伙伴关系...",
|
||||
"author": "商务发展部",
|
||||
"readTime": "4分钟阅读",
|
||||
"tags": ["合作伙伴", "战略合作", "创新"],
|
||||
"featured": true
|
||||
}
|
||||
]
|
||||
}
|
||||
114
data/locales/zh-CN/products.json
Normal file
114
data/locales/zh-CN/products.json
Normal file
@ -0,0 +1,114 @@
|
||||
{
|
||||
"title": "产品与服务",
|
||||
"subtitle": "专为加速您的云端数字化转型之旅而设计的全方位AWS云服务解决方案",
|
||||
"categories": [
|
||||
{
|
||||
"id": "software",
|
||||
"name": "云应用开发",
|
||||
"description": "基于AWS的云原生应用开发服务",
|
||||
"icon": "💻"
|
||||
},
|
||||
{
|
||||
"id": "consulting",
|
||||
"name": "云架构咨询",
|
||||
"description": "专业的AWS云架构咨询与规划",
|
||||
"icon": "🔍"
|
||||
},
|
||||
{
|
||||
"id": "integration",
|
||||
"name": "系统集成",
|
||||
"description": "企业级系统整合方案",
|
||||
"icon": "🔗"
|
||||
},
|
||||
{
|
||||
"id": "cloud",
|
||||
"name": "AWS云服务",
|
||||
"description": "专业的AWS云计算与数据存储解决方案",
|
||||
"icon": "☁️"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"id": "erp-system",
|
||||
"title": "云端企业资源规划系统",
|
||||
"category": "software",
|
||||
"description": "基于AWS的全面企业资源管理解决方案,旨在简化业务流程、提升运营效率,并为所有部门提供实时洞察。",
|
||||
"features": [
|
||||
"财务管理",
|
||||
"人力资源",
|
||||
"供应链管理",
|
||||
"客户关系管理",
|
||||
"库存控制",
|
||||
"商业智能"
|
||||
],
|
||||
"price": "联系我们获取报价",
|
||||
"icon": "🏢"
|
||||
},
|
||||
{
|
||||
"id": "data-analytics",
|
||||
"title": "高级数据分析平台",
|
||||
"category": "software",
|
||||
"description": "强大的AI驱动数据分析和可视化平台,将原始数据转化为可行的商业洞察,具备机器学习功能。",
|
||||
"features": [
|
||||
"实时数据处理",
|
||||
"交互式仪表板",
|
||||
"预测分析",
|
||||
"机器学习模型",
|
||||
"自定义报表",
|
||||
"数据可视化"
|
||||
],
|
||||
"price": "联系我们获取报价",
|
||||
"icon": "📊"
|
||||
},
|
||||
{
|
||||
"id": "digital-transformation",
|
||||
"title": "数字化转型咨询",
|
||||
"category": "consulting",
|
||||
"description": "战略咨询服务,引导组织进行全面的数字化转型,从评估到实施和优化。",
|
||||
"features": [
|
||||
"数字成熟度评估",
|
||||
"转型路线图",
|
||||
"技术架构",
|
||||
"变革管理",
|
||||
"实施支持",
|
||||
"绩效监控"
|
||||
],
|
||||
"price": "联系我们获取报价",
|
||||
"icon": "🚀"
|
||||
},
|
||||
{
|
||||
"id": "cloud-migration",
|
||||
"title": "云迁移与优化",
|
||||
"category": "cloud",
|
||||
"description": "端到端云迁移服务,具备零停机部署、安全优化和持续性能管理。",
|
||||
"features": ["云战略规划", "迁移评估", "安全实施", "性能优化", "成本管理", "24/7监控"],
|
||||
"price": "联系我们获取报价",
|
||||
"icon": "☁️"
|
||||
},
|
||||
{
|
||||
"id": "ai-solutions",
|
||||
"title": "AWS AI与机器学习解决方案",
|
||||
"category": "software",
|
||||
"description": "基于AWS AI服务的定制人工智能和机器学习解决方案,自动化流程、增强决策制定并推动创新。",
|
||||
"features": [
|
||||
"自然语言处理",
|
||||
"计算机视觉",
|
||||
"预测建模",
|
||||
"流程自动化",
|
||||
"智能聊天机器人",
|
||||
"推荐系统"
|
||||
],
|
||||
"price": "联系我们获取报价",
|
||||
"icon": "🤖"
|
||||
},
|
||||
{
|
||||
"id": "cybersecurity",
|
||||
"title": "网络安全解决方案",
|
||||
"category": "consulting",
|
||||
"description": "全面的网络安全服务,保护您的数字资产、确保合规性并维持业务连续性。",
|
||||
"features": ["安全评估", "威胁检测", "事件响应", "合规管理", "员工培训", "持续监控"],
|
||||
"price": "联系我们获取报价",
|
||||
"icon": "🔒"
|
||||
}
|
||||
]
|
||||
}
|
||||
101
data/locales/zh-CN/support.json
Normal file
101
data/locales/zh-CN/support.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"title": "客户支持",
|
||||
"subtitle": "我们致力于为您提供最优质的客户服务",
|
||||
"sections": {
|
||||
"faq": {
|
||||
"title": "常见问题",
|
||||
"subtitle": "查找常见问题的答案",
|
||||
"items": [
|
||||
{
|
||||
"id": "pricing",
|
||||
"question": "如何获取产品报价?",
|
||||
"answer": "您可以通过以下方式获取产品报价:1. 填写在线咨询表单;2. 致电我们的销售热线;3. 发送邮件至sales@haoaws.com。我们的销售团队会在24小时内与您联系。"
|
||||
},
|
||||
{
|
||||
"id": "implementation",
|
||||
"question": "产品实施需要多长时间?",
|
||||
"answer": "实施时间取决于项目的复杂程度和规模。一般来说,小型项目需要2-4周,中型项目需要1-3个月,大型项目可能需要3-6个月。我们会在项目开始前提供详细的时间规划。"
|
||||
},
|
||||
{
|
||||
"id": "support",
|
||||
"question": "提供哪些技术支持服务?",
|
||||
"answer": "我们提供全方位的技术支持服务,包括:7x24小时在线支持、电话支持、远程协助、现场服务、培训服务等。不同的服务级别有不同的响应时间保证。"
|
||||
},
|
||||
{
|
||||
"id": "training",
|
||||
"question": "是否提供用户培训?",
|
||||
"answer": "是的,我们提供全面的用户培训服务,包括:在线培训、现场培训、定制化培训课程。培训内容涵盖产品使用、最佳实践、故障排除等方面。"
|
||||
},
|
||||
{
|
||||
"id": "customization",
|
||||
"question": "产品是否支持定制化?",
|
||||
"answer": "我们的产品具有高度的可配置性,同时也支持定制化开发。我们的技术团队可以根据您的具体需求进行功能定制和界面调整。"
|
||||
}
|
||||
]
|
||||
},
|
||||
"contact": {
|
||||
"title": "联系我们",
|
||||
"subtitle": "多种方式联系我们的支持团队",
|
||||
"methods": [
|
||||
{
|
||||
"type": "phone",
|
||||
"title": "电话支持",
|
||||
"value": "+86 400-123-4567",
|
||||
"description": "工作日 9:00-18:00",
|
||||
"icon": "📞"
|
||||
},
|
||||
{
|
||||
"type": "email",
|
||||
"title": "邮件支持",
|
||||
"value": "support@haoaws.com",
|
||||
"description": "24小时内回复",
|
||||
"icon": "📧"
|
||||
},
|
||||
{
|
||||
"type": "chat",
|
||||
"title": "在线客服",
|
||||
"value": "立即开始对话",
|
||||
"description": "工作日 9:00-18:00",
|
||||
"icon": "💬"
|
||||
},
|
||||
{
|
||||
"type": "ticket",
|
||||
"title": "工单系统",
|
||||
"value": "提交技术工单",
|
||||
"description": "跟踪问题处理进度",
|
||||
"icon": "🎫"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": {
|
||||
"title": "帮助资源",
|
||||
"subtitle": "丰富的文档和资源帮助您更好地使用我们的产品",
|
||||
"items": [
|
||||
{
|
||||
"type": "documentation",
|
||||
"title": "产品文档",
|
||||
"description": "详细的产品使用说明和API文档",
|
||||
"icon": "📚"
|
||||
},
|
||||
{
|
||||
"type": "tutorials",
|
||||
"title": "视频教程",
|
||||
"description": "步骤详细的视频教程和操作指南",
|
||||
"icon": "🎥"
|
||||
},
|
||||
{
|
||||
"type": "community",
|
||||
"title": "用户社区",
|
||||
"description": "与其他用户交流经验和最佳实践",
|
||||
"icon": "👥"
|
||||
},
|
||||
{
|
||||
"type": "downloads",
|
||||
"title": "下载中心",
|
||||
"description": "软件下载、更新包和相关工具",
|
||||
"icon": "⬇️"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
129
data/locales/zh-TW/about.json
Normal file
129
data/locales/zh-TW/about.json
Normal file
@ -0,0 +1,129 @@
|
||||
{
|
||||
"title": "關於我們",
|
||||
"subtitle": "探索我們的發展歷程、核心價值,以及推動數位化轉型創新的專業團隊",
|
||||
"sections": {
|
||||
"company": {
|
||||
"title": "公司簡介",
|
||||
"description": "HaoAWS是一家專注於AWS雲端服務與企業數位化轉型的先驅科技公司。憑藉超過十年的豐富經驗,我們已發展成為企業尋求運用專業雲端技術解決方案的可信賴夥伴。我們對卓越和創新的承諾,已幫助數百家企業在快速發展的雲端環境中保持競爭優勢。",
|
||||
"mission": {
|
||||
"title": "我們的使命",
|
||||
"content": "透過專業的AWS雲端服務解決方案賦能企業,推動雲端數位化轉型,提升營運效率,並在雲端經濟中開創成長與價值創造的新機遇。"
|
||||
},
|
||||
"vision": {
|
||||
"title": "我們的願景",
|
||||
"content": "成為全球最值得信賴的AWS雲端服務夥伴,在雲端創新、品質和客戶成功方面設立行業標準,同時促進可持續的雲端未來。"
|
||||
},
|
||||
"values": {
|
||||
"title": "核心價值觀",
|
||||
"items": [
|
||||
{
|
||||
"name": "創新",
|
||||
"description": "擁抱創意並突破技術界限,提供突破性的解決方案"
|
||||
},
|
||||
{
|
||||
"name": "卓越",
|
||||
"description": "在我們所做的一切中保持最高標準,從程式碼品質到客戶服務"
|
||||
},
|
||||
{
|
||||
"name": "誠信",
|
||||
"description": "透過透明、誠實和道德的商業實踐建立信任"
|
||||
},
|
||||
{
|
||||
"name": "協作",
|
||||
"description": "培養創造互惠價值並推動集體成功的夥伴關係"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"milestones": {
|
||||
"title": "發展歷程",
|
||||
"items": [
|
||||
{
|
||||
"year": "2010",
|
||||
"title": "創立與願景",
|
||||
"description": "HaoAWS成立,致力於革新企業雲端服務和數位解決方案"
|
||||
},
|
||||
{
|
||||
"year": "2013",
|
||||
"title": "策略擴展",
|
||||
"description": "將專業領域擴展至系統整合和技術諮詢,服務財富500強企業"
|
||||
},
|
||||
{
|
||||
"year": "2016",
|
||||
"title": "AWS雲端革命",
|
||||
"description": "正式成為AWS合作夥伴,推出全面的雲端運算和先進數據分析服務,開創雲端優先解決方案"
|
||||
},
|
||||
{
|
||||
"year": "2019",
|
||||
"title": "全球佈局",
|
||||
"description": "建立國際業務,服務遍及北美、歐洲和亞太地區的客戶"
|
||||
},
|
||||
{
|
||||
"year": "2022",
|
||||
"title": "雲原生創新",
|
||||
"description": "成功將AWS雲原生和機器學習技術整合到我們的產品生態系統中"
|
||||
},
|
||||
{
|
||||
"year": "2024",
|
||||
"title": "面向未來",
|
||||
"description": "以AWS新興技術和可持續雲端解決方案引領下一波數位化轉型浪潮"
|
||||
}
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"title": "我們的團隊",
|
||||
"description": "我們多元化的專家團隊結合深厚的技術知識與行業經驗,提供卓越的成果",
|
||||
"stats": [
|
||||
{
|
||||
"number": "150+",
|
||||
"label": "專業人才"
|
||||
},
|
||||
{
|
||||
"number": "800+",
|
||||
"label": "成功專案"
|
||||
},
|
||||
{
|
||||
"number": "75+",
|
||||
"label": "全球夥伴"
|
||||
},
|
||||
{
|
||||
"number": "14+",
|
||||
"label": "卓越年份"
|
||||
}
|
||||
],
|
||||
"departments": [
|
||||
{
|
||||
"name": "研發創新",
|
||||
"description": "透過尖端研究和產品開發推動創新",
|
||||
"icon": "💻"
|
||||
},
|
||||
{
|
||||
"name": "業務發展",
|
||||
"description": "建立策略夥伴關係並在全球擴展市場影響力",
|
||||
"icon": "📈"
|
||||
},
|
||||
{
|
||||
"name": "客戶成功",
|
||||
"description": "透過專業支援和諮詢確保客戶滿意度",
|
||||
"icon": "🛠️"
|
||||
},
|
||||
{
|
||||
"name": "專案卓越",
|
||||
"description": "按時交付專案並超越品質期望",
|
||||
"icon": "📋"
|
||||
}
|
||||
]
|
||||
},
|
||||
"certifications": {
|
||||
"title": "認證與榮譽",
|
||||
"items": [
|
||||
"AWS 進階技術合作夥伴認證",
|
||||
"ISO 9001:2015 品質管理系統認證",
|
||||
"ISO 27001:2013 資訊安全管理認證",
|
||||
"CMMI Level 5 軟體開發成熟度認證",
|
||||
"AWS 解決方案架構專業認證",
|
||||
"AWS 雲端安全專業認證"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
24
data/locales/zh-TW/common.json
Normal file
24
data/locales/zh-TW/common.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"navigation": {
|
||||
"home": "首頁",
|
||||
"products": "產品與服務",
|
||||
"news": "新聞資訊",
|
||||
"support": "客戶支持",
|
||||
"about": "關於我們"
|
||||
},
|
||||
"common": {
|
||||
"companyName": "HaoAWS",
|
||||
"learnMore": "了解更多",
|
||||
"contactNow": "立即聯絡",
|
||||
"readMore": "閱讀更多",
|
||||
"backToHome": "返回首頁"
|
||||
},
|
||||
"footer": {
|
||||
"quickLinks": "快速連結",
|
||||
"contactInfo": "聯絡方式",
|
||||
"followUs": "關注我們",
|
||||
"copyright": "© 2024 HaoAWS. 保留所有權利.",
|
||||
"email": "contact@haoaws.com",
|
||||
"phone": "+86 400-123-4567"
|
||||
}
|
||||
}
|
||||
63
data/locales/zh-TW/home.json
Normal file
63
data/locales/zh-TW/home.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"seo": {
|
||||
"title": "HaoAWS - 領先的AWS雲端服務與數位化轉型解決方案提供商",
|
||||
"description": "HaoAWS專注於AWS雲端服務與企業數位化轉型,服務800+成功案例。提供雲端架構設計、數據分析平台、雲端遷移、網路安全等一站式解決方案。150+AWS專業團隊,7x24小時技術支援,助力企業實現雲端化升級,提升營運效率300%。立即諮詢獲取免費雲端評估!",
|
||||
"keywords": [
|
||||
"AWS雲端服務",
|
||||
"企業數位化轉型",
|
||||
"雲端運算遷移服務",
|
||||
"雲端架構設計",
|
||||
"大數據分析平台",
|
||||
"企業系統整合",
|
||||
"雲端諮詢服務"
|
||||
]
|
||||
},
|
||||
"hero": {
|
||||
"title": "引領雲端技術創新",
|
||||
"subtitle": "我們致力於為客戶提供專業的AWS雲端服務解決方案,助力企業數位化轉型",
|
||||
"button": "了解更多"
|
||||
},
|
||||
"services": {
|
||||
"title": "我們的服務",
|
||||
"subtitle": "專業的技術團隊,為您提供全方位的解決方案",
|
||||
"items": [
|
||||
{
|
||||
"title": "技術諮詢",
|
||||
"description": "專業的技術諮詢服務,幫助企業制定最優的技術方案"
|
||||
},
|
||||
{
|
||||
"title": "產品開發",
|
||||
"description": "從概念到產品,我們提供完整的開發服務"
|
||||
},
|
||||
{
|
||||
"title": "系統整合",
|
||||
"description": "整合各種系統和平台,提高企業營運效率"
|
||||
}
|
||||
]
|
||||
},
|
||||
"news": {
|
||||
"title": "最新資訊",
|
||||
"sampleTitle": "新聞標題",
|
||||
"sampleDate": "2024年1月",
|
||||
"viewMore": "查看更多新聞",
|
||||
"author": "作者"
|
||||
},
|
||||
"contact": {
|
||||
"title": "聯絡我們",
|
||||
"description": "有任何問題或需求,歡迎隨時聯絡我們的專業團隊"
|
||||
},
|
||||
"banner": [
|
||||
{
|
||||
"title": "HaoAWS,引領雲端未來",
|
||||
"subtitle": "專業的AWS雲端服務解決方案,卓越的服務體驗"
|
||||
},
|
||||
{
|
||||
"title": "品質雲端服務,值得信賴",
|
||||
"subtitle": "多年AWS實踐經驗,為您提供最優質的雲端服務"
|
||||
},
|
||||
{
|
||||
"title": "全球雲端部署,共創輝煌",
|
||||
"subtitle": "與世界各地的合作夥伴在雲端攜手前行"
|
||||
}
|
||||
]
|
||||
}
|
||||
97
data/locales/zh-TW/news.json
Normal file
97
data/locales/zh-TW/news.json
Normal file
@ -0,0 +1,97 @@
|
||||
{
|
||||
"title": "新聞資訊",
|
||||
"subtitle": "掌握最新的行業動態和公司發展資訊",
|
||||
"readMore": "閱讀更多",
|
||||
"categories": [
|
||||
{
|
||||
"id": "company",
|
||||
"name": "公司新聞"
|
||||
},
|
||||
{
|
||||
"id": "industry",
|
||||
"name": "行業資訊"
|
||||
},
|
||||
{
|
||||
"id": "technology",
|
||||
"name": "技術動態"
|
||||
},
|
||||
{
|
||||
"id": "events",
|
||||
"name": "活動公告"
|
||||
}
|
||||
],
|
||||
"articles": [
|
||||
{
|
||||
"id": "ai-transformation-2024",
|
||||
"title": "2024年人工智慧助力企業數位化轉型新趨勢",
|
||||
"category": "技術動態",
|
||||
"date": "2024年1月15日",
|
||||
"excerpt": "深入探討人工智慧技術如何推動企業數位化轉型,以及塑造未來商業營運的創新趨勢。發現重新定義企業營運的最新AI創新技術。",
|
||||
"content": "隨著人工智慧技術的快速發展,越來越多的企業開始將AI技術融入到業務流程中...",
|
||||
"author": "技術團隊",
|
||||
"readTime": "5分鐘閱讀",
|
||||
"tags": ["人工智慧", "數位化轉型", "企業管理"],
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"id": "cloud-security-best-practices",
|
||||
"title": "雲端安全最佳實踐:保護您的數據資產",
|
||||
"category": "技術動態",
|
||||
"date": "2024年1月10日",
|
||||
"excerpt": "全面的雲端安全最佳實踐指南,幫助企業建構安全可靠的雲端基礎設施,同時維持營運效率。",
|
||||
"content": "在雲端運算時代,數據安全是企業最關心的問題之一。本文將介紹雲端安全的最佳實踐...",
|
||||
"author": "安全專家",
|
||||
"readTime": "8分鐘閱讀",
|
||||
"tags": ["雲端安全", "數據保護", "最佳實踐"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "company-expansion-2024",
|
||||
"title": "全球擴展:跨三大洲新設服務中心",
|
||||
"category": "公司新聞",
|
||||
"date": "2024年1月8日",
|
||||
"excerpt": "為了更好地服務不斷增長的國際客戶群,我們策略性地在北美、歐洲和亞洲的關鍵市場開設了新的服務中心。",
|
||||
"content": "隨著業務的快速發展,我們很高興地宣布在策略性地點新增了服務中心...",
|
||||
"author": "管理團隊",
|
||||
"readTime": "3分鐘閱讀",
|
||||
"tags": ["公司新聞", "業務拓展", "服務中心"],
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"id": "industry-report-2024",
|
||||
"title": "2024年軟體行業發展報告:關鍵洞察",
|
||||
"category": "行業資訊",
|
||||
"date": "2024年1月5日",
|
||||
"excerpt": "深度分析軟體行業發展趨勢、新興技術,以及將在2024年及未來塑造行業的市場機遇。",
|
||||
"content": "根據最新的市場調研數據,2024年軟體行業將繼續保持強勁的增長勢頭...",
|
||||
"author": "市場研究部",
|
||||
"readTime": "12分鐘閱讀",
|
||||
"tags": ["行業報告", "市場分析", "發展趨勢"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "tech-conference-2024",
|
||||
"title": "加入我們參與2024年國際技術高峰會",
|
||||
"category": "活動公告",
|
||||
"date": "2024年1月3日",
|
||||
"excerpt": "我們很興奮能參與即將舉行的國際技術高峰會。歡迎蒞臨我們的展台,探索尖端解決方案並與行業領袖交流。",
|
||||
"content": "我們很榮幸地宣布,將參加2024年3月舉行的國際技術大會...",
|
||||
"author": "市場部",
|
||||
"readTime": "2分鐘閱讀",
|
||||
"tags": ["技術大會", "展覽", "交流"],
|
||||
"featured": false
|
||||
},
|
||||
{
|
||||
"id": "new-partnership",
|
||||
"title": "策略合作夥伴關係公告:攜手推動創新",
|
||||
"category": "公司新聞",
|
||||
"date": "2024年1月1日",
|
||||
"excerpt": "我們很自豪地宣布與領先的技術創新者建立策略合作夥伴關係,結合我們的專業知識為客戶提供下一代解決方案。",
|
||||
"content": "我們很高興地宣布,與業界知名的科技公司建立了策略合作夥伴關係...",
|
||||
"author": "商務發展部",
|
||||
"readTime": "4分鐘閱讀",
|
||||
"tags": ["合作夥伴", "策略合作", "創新"],
|
||||
"featured": true
|
||||
}
|
||||
]
|
||||
}
|
||||
121
data/locales/zh-TW/products.json
Normal file
121
data/locales/zh-TW/products.json
Normal file
@ -0,0 +1,121 @@
|
||||
{
|
||||
"title": "產品與服務",
|
||||
"subtitle": "專為加速您的數位化轉型之旅而設計的全方位技術解決方案",
|
||||
"categories": [
|
||||
{
|
||||
"id": "software",
|
||||
"name": "軟體開發",
|
||||
"description": "定制化軟體開發服務",
|
||||
"icon": "💻"
|
||||
},
|
||||
{
|
||||
"id": "consulting",
|
||||
"name": "技術諮詢",
|
||||
"description": "專業的技術諮詢與規劃",
|
||||
"icon": "🔍"
|
||||
},
|
||||
{
|
||||
"id": "integration",
|
||||
"name": "系統整合",
|
||||
"description": "企業級系統整合方案",
|
||||
"icon": "🔗"
|
||||
},
|
||||
{
|
||||
"id": "cloud",
|
||||
"name": "雲服務",
|
||||
"description": "雲計算與數據存儲解決方案",
|
||||
"icon": "☁️"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"id": "erp-system",
|
||||
"title": "企業資源規劃系統",
|
||||
"category": "software",
|
||||
"description": "全面的企業資源管理解決方案,旨在簡化業務流程、提升營運效率,並為所有部門提供即時洞察。",
|
||||
"features": [
|
||||
"財務管理",
|
||||
"人力資源",
|
||||
"供應鏈管理",
|
||||
"客戶關係管理",
|
||||
"庫存控制",
|
||||
"商業智慧"
|
||||
],
|
||||
"price": "聯絡我們獲取報價",
|
||||
"icon": "🏢"
|
||||
},
|
||||
{
|
||||
"id": "data-analytics",
|
||||
"title": "進階數據分析平台",
|
||||
"category": "software",
|
||||
"description": "強大的AI驅動數據分析和可視化平台,將原始數據轉化為可行的商業洞察,具備機器學習功能。",
|
||||
"features": [
|
||||
"即時數據處理",
|
||||
"互動式儀表板",
|
||||
"預測分析",
|
||||
"機器學習模型",
|
||||
"自定義報表",
|
||||
"數據可視化"
|
||||
],
|
||||
"price": "聯絡我們獲取報價",
|
||||
"icon": "📊"
|
||||
},
|
||||
{
|
||||
"id": "digital-transformation",
|
||||
"title": "數位化轉型諮詢",
|
||||
"category": "consulting",
|
||||
"description": "策略諮詢服務,引導組織進行全面的數位化轉型,從評估到實施和優化。",
|
||||
"features": [
|
||||
"數位成熟度評估",
|
||||
"轉型路線圖",
|
||||
"技術架構",
|
||||
"變革管理",
|
||||
"實施支援",
|
||||
"績效監控"
|
||||
],
|
||||
"price": "聯絡我們獲取報價",
|
||||
"icon": "🚀"
|
||||
},
|
||||
{
|
||||
"id": "cloud-migration",
|
||||
"title": "雲端遷移與優化",
|
||||
"category": "cloud",
|
||||
"description": "端到端雲端遷移服務,具備零停機部署、安全優化和持續性能管理。",
|
||||
"features": [
|
||||
"雲端策略規劃",
|
||||
"遷移評估",
|
||||
"安全實施",
|
||||
"性能優化",
|
||||
"成本管理",
|
||||
"24/7監控"
|
||||
],
|
||||
"price": "聯絡我們獲取報價",
|
||||
"icon": "☁️"
|
||||
},
|
||||
{
|
||||
"id": "ai-solutions",
|
||||
"title": "AI與機器學習解決方案",
|
||||
"category": "software",
|
||||
"description": "定制的人工智慧和機器學習解決方案,自動化流程、增強決策制定並推動創新。",
|
||||
"features": [
|
||||
"自然語言處理",
|
||||
"電腦視覺",
|
||||
"預測建模",
|
||||
"流程自動化",
|
||||
"智能聊天機器人",
|
||||
"推薦系統"
|
||||
],
|
||||
"price": "聯絡我們獲取報價",
|
||||
"icon": "🤖"
|
||||
},
|
||||
{
|
||||
"id": "cybersecurity",
|
||||
"title": "網路安全解決方案",
|
||||
"category": "consulting",
|
||||
"description": "全面的網路安全服務,保護您的數位資產、確保合規性並維持業務連續性。",
|
||||
"features": ["安全評估", "威脅檢測", "事件回應", "合規管理", "員工培訓", "持續監控"],
|
||||
"price": "聯絡我們獲取報價",
|
||||
"icon": "🔒"
|
||||
}
|
||||
]
|
||||
}
|
||||
101
data/locales/zh-TW/support.json
Normal file
101
data/locales/zh-TW/support.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"title": "客戶支持",
|
||||
"subtitle": "我們致力於為您提供最優質的客戶服務",
|
||||
"sections": {
|
||||
"faq": {
|
||||
"title": "常見問題",
|
||||
"subtitle": "查找常見問題的答案",
|
||||
"items": [
|
||||
{
|
||||
"id": "pricing",
|
||||
"question": "如何獲取產品報價?",
|
||||
"answer": "您可以通過以下方式獲取產品報價:1. 填寫線上諮詢表單;2. 致電我們的銷售熱線;3. 發送郵件至sales@haoaws.com。我們的銷售團隊會在24小時內與您聯絡。"
|
||||
},
|
||||
{
|
||||
"id": "implementation",
|
||||
"question": "產品實施需要多長時間?",
|
||||
"answer": "實施時間取決於項目的複雜程度和規模。一般來說,小型項目需要2-4週,中型項目需要1-3個月,大型項目可能需要3-6個月。我們會在項目開始前提供詳細的時間規劃。"
|
||||
},
|
||||
{
|
||||
"id": "support",
|
||||
"question": "提供哪些技術支持服務?",
|
||||
"answer": "我們提供全方位的技術支持服務,包括:7x24小時線上支持、電話支持、遠程協助、現場服務、培訓服務等。不同的服務級別有不同的響應時間保證。"
|
||||
},
|
||||
{
|
||||
"id": "training",
|
||||
"question": "是否提供用戶培訓?",
|
||||
"answer": "是的,我們提供全面的用戶培訓服務,包括:線上培訓、現場培訓、定制化培訓課程。培訓內容涵蓋產品使用、最佳實踐、故障排除等方面。"
|
||||
},
|
||||
{
|
||||
"id": "customization",
|
||||
"question": "產品是否支持定制化?",
|
||||
"answer": "我們的產品具有高度的可配置性,同時也支持定制化開發。我們的技術團隊可以根據您的具體需求進行功能定制和界面調整。"
|
||||
}
|
||||
]
|
||||
},
|
||||
"contact": {
|
||||
"title": "聯絡我們",
|
||||
"subtitle": "多種方式聯絡我們的支持團隊",
|
||||
"methods": [
|
||||
{
|
||||
"type": "phone",
|
||||
"title": "電話支持",
|
||||
"value": "+86 400-123-4567",
|
||||
"description": "工作日 9:00-18:00",
|
||||
"icon": "📞"
|
||||
},
|
||||
{
|
||||
"type": "email",
|
||||
"title": "郵件支持",
|
||||
"value": "support@haoaws.com",
|
||||
"description": "24小時內回復",
|
||||
"icon": "📧"
|
||||
},
|
||||
{
|
||||
"type": "chat",
|
||||
"title": "線上客服",
|
||||
"value": "立即開始對話",
|
||||
"description": "工作日 9:00-18:00",
|
||||
"icon": "💬"
|
||||
},
|
||||
{
|
||||
"type": "ticket",
|
||||
"title": "工單系統",
|
||||
"value": "提交技術工單",
|
||||
"description": "跟蹤問題處理進度",
|
||||
"icon": "🎫"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": {
|
||||
"title": "幫助資源",
|
||||
"subtitle": "豐富的文檔和資源幫助您更好地使用我們的產品",
|
||||
"items": [
|
||||
{
|
||||
"type": "documentation",
|
||||
"title": "產品文檔",
|
||||
"description": "詳細的產品使用說明和API文檔",
|
||||
"icon": "📚"
|
||||
},
|
||||
{
|
||||
"type": "tutorials",
|
||||
"title": "視頻教程",
|
||||
"description": "步驟詳細的視頻教程和操作指南",
|
||||
"icon": "🎥"
|
||||
},
|
||||
{
|
||||
"type": "community",
|
||||
"title": "用戶社群",
|
||||
"description": "與其他用戶交流經驗和最佳實踐",
|
||||
"icon": "👥"
|
||||
},
|
||||
{
|
||||
"type": "downloads",
|
||||
"title": "下載中心",
|
||||
"description": "軟體下載、更新包和相關工具",
|
||||
"icon": "⬇️"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
64
docs/news/en/ai-transformation-2024.md
Normal file
64
docs/news/en/ai-transformation-2024.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: '2024 AI-Powered Enterprise Digital Transformation Trends'
|
||||
category: 'Technology'
|
||||
date: 'January 15, 2024'
|
||||
excerpt: 'Exploring how artificial intelligence technology drives enterprise digital transformation and future development trends. Discover the latest AI innovations reshaping business operations.'
|
||||
author: 'Technical Team'
|
||||
readTime: '5 min read'
|
||||
tags: ['Artificial Intelligence', 'Digital Transformation', 'Enterprise Management']
|
||||
featured: true
|
||||
---
|
||||
|
||||
# 2024 AI-Powered Enterprise Digital Transformation Trends
|
||||
|
||||
With the rapid development of artificial intelligence technology, more and more enterprises are beginning to integrate AI technology into their business processes. This transformation not only improves operational efficiency but also creates new business opportunities for companies.
|
||||
|
||||
## AI Applications in Enterprise
|
||||
|
||||
### 1. Process Automation Optimization
|
||||
|
||||
Artificial intelligence technology can automate many repetitive tasks, thereby freeing up employees' time to focus on more valuable work. For example:
|
||||
|
||||
- **Document Processing Automation**: Using OCR and NLP technologies to automatically process and classify documents
|
||||
- **Customer Service Automation**: Intelligent chatbots providing 24/7 customer support
|
||||
- **Data Analysis Automation**: Automatically generating reports and insights
|
||||
|
||||
### 2. Predictive Analytics
|
||||
|
||||
AI-driven predictive analytics help enterprises:
|
||||
|
||||
- Predict market trends
|
||||
- Optimize inventory management
|
||||
- Identify potential issues in advance
|
||||
|
||||
## Key Elements of Digital Transformation
|
||||
|
||||
### Data-Driven Decision Making
|
||||
|
||||
Modern enterprises need to establish robust data infrastructure to ensure data quality and accessibility. This includes:
|
||||
|
||||
1. **Data Collection**: Establishing comprehensive data collection mechanisms
|
||||
2. **Data Cleaning**: Ensuring data accuracy and consistency
|
||||
3. **Data Analysis**: Using AI tools for in-depth analysis
|
||||
|
||||
### Employee Skill Enhancement
|
||||
|
||||
The key to successful digital transformation lies in employee skill enhancement:
|
||||
|
||||
- Providing training on AI and digital tools
|
||||
- Building a culture of continuous learning
|
||||
- Encouraging innovation and experimentation
|
||||
|
||||
## Future Outlook
|
||||
|
||||
In 2024, we expect to see the following trends:
|
||||
|
||||
1. **Smarter Automation**: AI will be able to handle more complex tasks
|
||||
2. **Personalized Experiences**: AI-based personalized services will become standard
|
||||
3. **Sustainable Development**: AI will help enterprises achieve sustainable development goals
|
||||
|
||||
## Conclusion
|
||||
|
||||
AI-driven digital transformation is no longer a choice but a necessity for enterprise survival and development. Those companies that can successfully integrate AI technology will gain a competitive advantage.
|
||||
|
||||
Enterprises need to develop clear digital transformation strategies, invest in the right technologies and talent, and build a culture that supports innovation. Only in this way can they maintain competitiveness in a rapidly changing business environment.
|
||||
88
docs/news/en/cloud-security-best-practices.md
Normal file
88
docs/news/en/cloud-security-best-practices.md
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
title: 'Cloud Security Best Practices: Protecting Your Data Assets'
|
||||
category: 'Technology'
|
||||
date: 'January 10, 2024'
|
||||
excerpt: 'Comprehensive guide to cloud security best practices that help enterprises build secure and reliable cloud infrastructure while maintaining operational efficiency.'
|
||||
author: 'Security Expert'
|
||||
readTime: '8 min read'
|
||||
tags: ['Cloud Security', 'Data Protection', 'Best Practices']
|
||||
featured: false
|
||||
---
|
||||
|
||||
# Cloud Security Best Practices: Protecting Your Data Assets
|
||||
|
||||
In the era of cloud computing, data security is one of the most concerning issues for enterprises. This article will introduce cloud security best practices to help you build a secure and reliable cloud environment.
|
||||
|
||||
## Identity and Access Management
|
||||
|
||||
### Multi-Factor Authentication
|
||||
|
||||
- Enable MFA for all user accounts
|
||||
- Use strong password policies
|
||||
- Regularly review user permissions
|
||||
|
||||
### Principle of Least Privilege
|
||||
|
||||
- Grant only necessary access permissions
|
||||
- Regularly review and update permissions
|
||||
- Use role-based access control
|
||||
|
||||
## Data Encryption
|
||||
|
||||
### Encryption in Transit
|
||||
|
||||
- Use TLS/SSL protocols
|
||||
- Implement end-to-end encryption
|
||||
- Verify certificate validity
|
||||
|
||||
### Encryption at Rest
|
||||
|
||||
- Encrypt stored sensitive data
|
||||
- Use strong encryption algorithms
|
||||
- Securely manage encryption keys
|
||||
|
||||
## Network Security
|
||||
|
||||
### Firewall Configuration
|
||||
|
||||
- Configure network firewall rules
|
||||
- Restrict unnecessary network access
|
||||
- Monitor network traffic
|
||||
|
||||
### VPN and Dedicated Connections
|
||||
|
||||
- Use VPN for remote access
|
||||
- Consider dedicated network connections
|
||||
- Implement network segmentation
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Security Monitoring
|
||||
|
||||
- Implement real-time security monitoring
|
||||
- Set up security alerts
|
||||
- Conduct regular security audits
|
||||
|
||||
### Log Management
|
||||
|
||||
- Collect and analyze security logs
|
||||
- Maintain appropriate log retention
|
||||
- Implement log integrity protection
|
||||
|
||||
## Backup and Disaster Recovery
|
||||
|
||||
### Data Backup
|
||||
|
||||
- Regularly backup critical data
|
||||
- Test backup recovery processes
|
||||
- Implement multi-location backup strategies
|
||||
|
||||
### Disaster Recovery Planning
|
||||
|
||||
- Develop detailed recovery plans
|
||||
- Regularly test recovery procedures
|
||||
- Establish business continuity strategies
|
||||
|
||||
## Conclusion
|
||||
|
||||
Cloud security requires a comprehensive approach and continuous effort. By implementing these best practices, enterprises can significantly improve the security of their cloud environments.
|
||||
64
docs/news/en/company-expansion-2024.md
Normal file
64
docs/news/en/company-expansion-2024.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: 'Global Expansion: New Service Centers Across Three Continents'
|
||||
category: 'Company News'
|
||||
date: 'January 8, 2024'
|
||||
excerpt: 'To better serve our growing international client base, we have strategically opened new service centers in key markets across North America, Europe, and Asia.'
|
||||
author: 'Management Team'
|
||||
readTime: '3 min read'
|
||||
tags: ['Company News', 'Business Expansion', 'Service Centers']
|
||||
featured: true
|
||||
---
|
||||
|
||||
# Global Expansion: New Service Centers Across Three Continents
|
||||
|
||||
With the rapid development of our business, we are pleased to announce the addition of new service centers in strategic locations to better serve our global customers.
|
||||
|
||||
## Expansion Strategy
|
||||
|
||||
### North America
|
||||
|
||||
We have established new service centers in Toronto and Chicago, which will enable us to:
|
||||
|
||||
- Provide localized customer support
|
||||
- Reduce response times
|
||||
- Better understand local market needs
|
||||
|
||||
### Europe
|
||||
|
||||
New offices in Berlin and Amsterdam will help us:
|
||||
|
||||
- Expand European market share
|
||||
- Provide multilingual support
|
||||
- Comply with local regulatory requirements
|
||||
|
||||
### Asia-Pacific
|
||||
|
||||
Service centers in Singapore and Sydney will:
|
||||
|
||||
- Cover Asia-Pacific time zones
|
||||
- Provide 24/7 round-the-clock service
|
||||
- Support the rapidly growing Asian market
|
||||
|
||||
## Service Capability Enhancement
|
||||
|
||||
### Technical Support
|
||||
|
||||
- Local technical expert teams
|
||||
- Rapid problem resolution
|
||||
- Customized solutions
|
||||
|
||||
### Customer Service
|
||||
|
||||
- Multilingual customer support
|
||||
- Localized service experience
|
||||
- Culturally sensitive communication
|
||||
|
||||
## Future Plans
|
||||
|
||||
We plan to complete by the end of 2024:
|
||||
|
||||
1. Full operation of all new service centers
|
||||
2. Recruitment of 200 new employees
|
||||
3. Establishment of regional partner networks
|
||||
|
||||
This expansion marks an important milestone in our company's development, and we are committed to providing excellent service experiences for our global customers.
|
||||
64
docs/news/zh-CN/ai-transformation-2024.md
Normal file
64
docs/news/zh-CN/ai-transformation-2024.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: '2024年AI驱动的企业数字化转型趋势'
|
||||
category: '技术'
|
||||
date: '2024年1月15日'
|
||||
excerpt: '探索人工智能技术如何推动企业数字化转型以及未来发展趋势。了解重塑商业运营的最新AI创新。'
|
||||
author: '技术团队'
|
||||
readTime: '5分钟阅读'
|
||||
tags: ['人工智能', '数字化转型', '企业管理']
|
||||
featured: true
|
||||
---
|
||||
|
||||
# 2024年AI驱动的企业数字化转型趋势
|
||||
|
||||
随着人工智能技术的快速发展,越来越多的企业开始将AI技术融入到他们的业务流程中。这种转变不仅提高了运营效率,还为企业创造了新的商业机会。
|
||||
|
||||
## AI技术在企业中的应用
|
||||
|
||||
### 1. 自动化流程优化
|
||||
|
||||
人工智能技术能够自动化许多重复性任务,从而释放员工的时间来专注于更有价值的工作。例如:
|
||||
|
||||
- **文档处理自动化**:使用OCR和NLP技术自动处理和分类文档
|
||||
- **客户服务自动化**:智能聊天机器人提供24/7客户支持
|
||||
- **数据分析自动化**:自动生成报告和洞察
|
||||
|
||||
### 2. 预测性分析
|
||||
|
||||
AI驱动的预测性分析帮助企业:
|
||||
|
||||
- 预测市场趋势
|
||||
- 优化库存管理
|
||||
- 提前识别潜在问题
|
||||
|
||||
## 数字化转型的关键要素
|
||||
|
||||
### 数据驱动决策
|
||||
|
||||
现代企业需要建立强大的数据基础设施,确保数据的质量和可访问性。这包括:
|
||||
|
||||
1. **数据收集**:建立全面的数据收集机制
|
||||
2. **数据清洗**:确保数据的准确性和一致性
|
||||
3. **数据分析**:使用AI工具进行深度分析
|
||||
|
||||
### 员工技能提升
|
||||
|
||||
数字化转型成功的关键在于员工的技能提升:
|
||||
|
||||
- 提供AI和数字化工具的培训
|
||||
- 建立持续学习的文化
|
||||
- 鼓励创新和实验
|
||||
|
||||
## 未来展望
|
||||
|
||||
2024年,我们预计将看到以下趋势:
|
||||
|
||||
1. **更智能的自动化**:AI将能够处理更复杂的任务
|
||||
2. **个性化体验**:基于AI的个性化服务将成为标准
|
||||
3. **可持续发展**:AI将帮助企业实现可持续发展目标
|
||||
|
||||
## 结论
|
||||
|
||||
AI驱动的数字化转型不再是选择,而是企业生存和发展的必需品。那些能够成功整合AI技术的企业将在竞争中占据优势地位。
|
||||
|
||||
企业需要制定清晰的数字化转型战略,投资于正确的技术和人才,并建立支持创新的文化。只有这样,才能在快速变化的商业环境中保持竞争力。
|
||||
88
docs/news/zh-CN/cloud-security-best-practices.md
Normal file
88
docs/news/zh-CN/cloud-security-best-practices.md
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
title: '云安全最佳实践:保护您的数据资产'
|
||||
category: '技术'
|
||||
date: '2024年1月10日'
|
||||
excerpt: '全面的云安全最佳实践指南,帮助企业构建安全可靠的云基础设施,同时保持运营效率。'
|
||||
author: '安全专家'
|
||||
readTime: '8分钟阅读'
|
||||
tags: ['云安全', '数据保护', '最佳实践']
|
||||
featured: false
|
||||
---
|
||||
|
||||
# 云安全最佳实践:保护您的数据资产
|
||||
|
||||
在云计算时代,数据安全是企业最关心的问题之一。本文将介绍云安全最佳实践,帮助您构建安全可靠的云环境。
|
||||
|
||||
## 身份和访问管理
|
||||
|
||||
### 多因素认证
|
||||
|
||||
- 为所有用户账户启用MFA
|
||||
- 使用强密码策略
|
||||
- 定期审查用户权限
|
||||
|
||||
### 最小权限原则
|
||||
|
||||
- 仅授予必要的访问权限
|
||||
- 定期审查和更新权限
|
||||
- 使用基于角色的访问控制
|
||||
|
||||
## 数据加密
|
||||
|
||||
### 传输中加密
|
||||
|
||||
- 使用TLS/SSL协议
|
||||
- 实施端到端加密
|
||||
- 验证证书有效性
|
||||
|
||||
### 静态数据加密
|
||||
|
||||
- 加密存储的敏感数据
|
||||
- 使用强加密算法
|
||||
- 安全管理加密密钥
|
||||
|
||||
## 网络安全
|
||||
|
||||
### 防火墙配置
|
||||
|
||||
- 配置网络防火墙规则
|
||||
- 限制不必要的网络访问
|
||||
- 监控网络流量
|
||||
|
||||
### VPN和专用连接
|
||||
|
||||
- 使用VPN进行远程访问
|
||||
- 考虑专用网络连接
|
||||
- 实施网络分段
|
||||
|
||||
## 监控和日志记录
|
||||
|
||||
### 安全监控
|
||||
|
||||
- 实施实时安全监控
|
||||
- 设置安全警报
|
||||
- 定期安全审计
|
||||
|
||||
### 日志管理
|
||||
|
||||
- 收集和分析安全日志
|
||||
- 保留适当的日志记录
|
||||
- 实施日志完整性保护
|
||||
|
||||
## 备份和灾难恢复
|
||||
|
||||
### 数据备份
|
||||
|
||||
- 定期备份关键数据
|
||||
- 测试备份恢复过程
|
||||
- 实施多地备份策略
|
||||
|
||||
### 灾难恢复计划
|
||||
|
||||
- 制定详细的恢复计划
|
||||
- 定期测试恢复程序
|
||||
- 建立业务连续性策略
|
||||
|
||||
## 结论
|
||||
|
||||
云安全需要全面的方法和持续的努力。通过实施这些最佳实践,企业可以显著提高其云环境的安全性。
|
||||
64
docs/news/zh-CN/company-expansion-2024.md
Normal file
64
docs/news/zh-CN/company-expansion-2024.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: '全球扩张:三大洲新增服务中心'
|
||||
category: '公司新闻'
|
||||
date: '2024年1月8日'
|
||||
excerpt: '为了更好地服务我们不断增长的国际客户群,我们在北美、欧洲和亚洲的关键市场战略性地开设了新的服务中心。'
|
||||
author: '管理团队'
|
||||
readTime: '3分钟阅读'
|
||||
tags: ['公司新闻', '业务扩张', '服务中心']
|
||||
featured: true
|
||||
---
|
||||
|
||||
# 全球扩张:三大洲新增服务中心
|
||||
|
||||
随着我们业务的快速发展,我们很高兴地宣布在战略位置新增服务中心,以更好地服务我们的全球客户。
|
||||
|
||||
## 扩张战略
|
||||
|
||||
### 北美地区
|
||||
|
||||
我们在多伦多和芝加哥新设立了服务中心,这将使我们能够:
|
||||
|
||||
- 提供本地化的客户支持
|
||||
- 缩短响应时间
|
||||
- 更好地理解当地市场需求
|
||||
|
||||
### 欧洲地区
|
||||
|
||||
在柏林和阿姆斯特丹的新办事处将帮助我们:
|
||||
|
||||
- 扩大欧洲市场份额
|
||||
- 提供多语言支持
|
||||
- 符合当地法规要求
|
||||
|
||||
### 亚太地区
|
||||
|
||||
新加坡和悉尼的服务中心将:
|
||||
|
||||
- 覆盖亚太时区
|
||||
- 提供24/7全天候服务
|
||||
- 支持快速增长的亚洲市场
|
||||
|
||||
## 服务能力提升
|
||||
|
||||
### 技术支持
|
||||
|
||||
- 本地技术专家团队
|
||||
- 快速问题解决
|
||||
- 定制化解决方案
|
||||
|
||||
### 客户服务
|
||||
|
||||
- 多语言客户支持
|
||||
- 本地化服务体验
|
||||
- 文化敏感的沟通方式
|
||||
|
||||
## 未来计划
|
||||
|
||||
我们计划在2024年底前:
|
||||
|
||||
1. 完成所有新服务中心的全面运营
|
||||
2. 招聘200名新员工
|
||||
3. 建立区域合作伙伴网络
|
||||
|
||||
这次扩张标志着我们公司发展的重要里程碑,我们致力于为全球客户提供卓越的服务体验。
|
||||
64
docs/news/zh-TW/ai-transformation-2024.md
Normal file
64
docs/news/zh-TW/ai-transformation-2024.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: '2024年AI驅動的企業數位化轉型趨勢'
|
||||
category: '技術'
|
||||
date: '2024年1月15日'
|
||||
excerpt: '探索人工智慧技術如何推動企業數位化轉型以及未來發展趨勢。了解重塑商業營運的最新AI創新。'
|
||||
author: '技術團隊'
|
||||
readTime: '5分鐘閱讀'
|
||||
tags: ['人工智慧', '數位化轉型', '企業管理']
|
||||
featured: true
|
||||
---
|
||||
|
||||
# 2024年AI驅動的企業數位化轉型趨勢
|
||||
|
||||
隨著人工智慧技術的快速發展,越來越多的企業開始將AI技術融入到他們的業務流程中。這種轉變不僅提高了營運效率,還為企業創造了新的商業機會。
|
||||
|
||||
## AI技術在企業中的應用
|
||||
|
||||
### 1. 自動化流程優化
|
||||
|
||||
人工智慧技術能夠自動化許多重複性任務,從而釋放員工的時間來專注於更有價值的工作。例如:
|
||||
|
||||
- **文件處理自動化**:使用OCR和NLP技術自動處理和分類文件
|
||||
- **客戶服務自動化**:智慧聊天機器人提供24/7客戶支援
|
||||
- **資料分析自動化**:自動生成報告和洞察
|
||||
|
||||
### 2. 預測性分析
|
||||
|
||||
AI驅動的預測性分析幫助企業:
|
||||
|
||||
- 預測市場趨勢
|
||||
- 優化庫存管理
|
||||
- 提前識別潛在問題
|
||||
|
||||
## 數位化轉型的關鍵要素
|
||||
|
||||
### 資料驅動決策
|
||||
|
||||
現代企業需要建立強大的資料基礎設施,確保資料的品質和可存取性。這包括:
|
||||
|
||||
1. **資料收集**:建立全面的資料收集機制
|
||||
2. **資料清洗**:確保資料的準確性和一致性
|
||||
3. **資料分析**:使用AI工具進行深度分析
|
||||
|
||||
### 員工技能提升
|
||||
|
||||
數位化轉型成功的關鍵在於員工的技能提升:
|
||||
|
||||
- 提供AI和數位化工具的培訓
|
||||
- 建立持續學習的文化
|
||||
- 鼓勵創新和實驗
|
||||
|
||||
## 未來展望
|
||||
|
||||
2024年,我們預計將看到以下趨勢:
|
||||
|
||||
1. **更智慧的自動化**:AI將能夠處理更複雜的任務
|
||||
2. **個人化體驗**:基於AI的個人化服務將成為標準
|
||||
3. **可持續發展**:AI將幫助企業實現可持續發展目標
|
||||
|
||||
## 結論
|
||||
|
||||
AI驅動的數位化轉型不再是選擇,而是企業生存和發展的必需品。那些能夠成功整合AI技術的企業將在競爭中佔據優勢地位。
|
||||
|
||||
企業需要制定清晰的數位化轉型策略,投資於正確的技術和人才,並建立支持創新的文化。只有這樣,才能在快速變化的商業環境中保持競爭力。
|
||||
88
docs/news/zh-TW/cloud-security-best-practices.md
Normal file
88
docs/news/zh-TW/cloud-security-best-practices.md
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
title: '雲端安全最佳實務:保護您的資料資產'
|
||||
category: '技術'
|
||||
date: '2024年1月10日'
|
||||
excerpt: '全面的雲端安全最佳實務指南,幫助企業構建安全可靠的雲端基礎設施,同時保持營運效率。'
|
||||
author: '安全專家'
|
||||
readTime: '8分鐘閱讀'
|
||||
tags: ['雲端安全', '資料保護', '最佳實務']
|
||||
featured: false
|
||||
---
|
||||
|
||||
# 雲端安全最佳實務:保護您的資料資產
|
||||
|
||||
在雲端運算時代,資料安全是企業最關心的問題之一。本文將介紹雲端安全最佳實務,幫助您構建安全可靠的雲端環境。
|
||||
|
||||
## 身分和存取管理
|
||||
|
||||
### 多因素驗證
|
||||
|
||||
- 為所有使用者帳戶啟用MFA
|
||||
- 使用強密碼策略
|
||||
- 定期審查使用者權限
|
||||
|
||||
### 最小權限原則
|
||||
|
||||
- 僅授予必要的存取權限
|
||||
- 定期審查和更新權限
|
||||
- 使用基於角色的存取控制
|
||||
|
||||
## 資料加密
|
||||
|
||||
### 傳輸中加密
|
||||
|
||||
- 使用TLS/SSL協定
|
||||
- 實施端到端加密
|
||||
- 驗證憑證有效性
|
||||
|
||||
### 靜態資料加密
|
||||
|
||||
- 加密儲存的敏感資料
|
||||
- 使用強加密演算法
|
||||
- 安全管理加密金鑰
|
||||
|
||||
## 網路安全
|
||||
|
||||
### 防火牆設定
|
||||
|
||||
- 設定網路防火牆規則
|
||||
- 限制不必要的網路存取
|
||||
- 監控網路流量
|
||||
|
||||
### VPN和專用連線
|
||||
|
||||
- 使用VPN進行遠端存取
|
||||
- 考慮專用網路連線
|
||||
- 實施網路分段
|
||||
|
||||
## 監控和日誌記錄
|
||||
|
||||
### 安全監控
|
||||
|
||||
- 實施即時安全監控
|
||||
- 設定安全警報
|
||||
- 定期安全稽核
|
||||
|
||||
### 日誌管理
|
||||
|
||||
- 收集和分析安全日誌
|
||||
- 保留適當的日誌記錄
|
||||
- 實施日誌完整性保護
|
||||
|
||||
## 備份和災難復原
|
||||
|
||||
### 資料備份
|
||||
|
||||
- 定期備份關鍵資料
|
||||
- 測試備份復原過程
|
||||
- 實施多地備份策略
|
||||
|
||||
### 災難復原計畫
|
||||
|
||||
- 制定詳細的復原計畫
|
||||
- 定期測試復原程序
|
||||
- 建立業務持續性策略
|
||||
|
||||
## 結論
|
||||
|
||||
雲端安全需要全面的方法和持續的努力。透過實施這些最佳實務,企業可以顯著提高其雲端環境的安全性。
|
||||
64
docs/news/zh-TW/company-expansion-2024.md
Normal file
64
docs/news/zh-TW/company-expansion-2024.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: '全球擴張:三大洲新增服務中心'
|
||||
category: '公司新聞'
|
||||
date: '2024年1月8日'
|
||||
excerpt: '為了更好地服務我們不斷增長的國際客戶群,我們在北美、歐洲和亞洲的關鍵市場戰略性地開設了新的服務中心。'
|
||||
author: '管理團隊'
|
||||
readTime: '3分鐘閱讀'
|
||||
tags: ['公司新聞', '業務擴張', '服務中心']
|
||||
featured: true
|
||||
---
|
||||
|
||||
# 全球擴張:三大洲新增服務中心
|
||||
|
||||
隨著我們業務的快速發展,我們很高興地宣布在戰略位置新增服務中心,以更好地服務我們的全球客戶。
|
||||
|
||||
## 擴張策略
|
||||
|
||||
### 北美地區
|
||||
|
||||
我們在多倫多和芝加哥新設立了服務中心,這將使我們能夠:
|
||||
|
||||
- 提供本地化的客戶支援
|
||||
- 縮短回應時間
|
||||
- 更好地理解當地市場需求
|
||||
|
||||
### 歐洲地區
|
||||
|
||||
在柏林和阿姆斯特丹的新辦事處將幫助我們:
|
||||
|
||||
- 擴大歐洲市場份額
|
||||
- 提供多語言支援
|
||||
- 符合當地法規要求
|
||||
|
||||
### 亞太地區
|
||||
|
||||
新加坡和雪梨的服務中心將:
|
||||
|
||||
- 覆蓋亞太時區
|
||||
- 提供24/7全天候服務
|
||||
- 支援快速增長的亞洲市場
|
||||
|
||||
## 服務能力提升
|
||||
|
||||
### 技術支援
|
||||
|
||||
- 本地技術專家團隊
|
||||
- 快速問題解決
|
||||
- 客製化解決方案
|
||||
|
||||
### 客戶服務
|
||||
|
||||
- 多語言客戶支援
|
||||
- 本地化服務體驗
|
||||
- 文化敏感的溝通方式
|
||||
|
||||
## 未來計畫
|
||||
|
||||
我們計畫在2024年底前:
|
||||
|
||||
1. 完成所有新服務中心的全面營運
|
||||
2. 招聘200名新員工
|
||||
3. 建立區域合作夥伴網路
|
||||
|
||||
這次擴張標誌著我們公司發展的重要里程碑,我們致力於為全球客戶提供卓越的服務體驗。
|
||||
99
lib/i18n.ts
Normal file
99
lib/i18n.ts
Normal file
@ -0,0 +1,99 @@
|
||||
export type Locale = 'zh-CN' | 'zh-TW' | 'en';
|
||||
|
||||
export const locales: Locale[] = ['zh-CN', 'zh-TW', 'en'];
|
||||
|
||||
export const defaultLocale: Locale = 'zh-CN';
|
||||
|
||||
export const languages = [
|
||||
{ code: 'zh-CN' as Locale, name: '简体中文', flag: '🇨🇳' },
|
||||
{ code: 'zh-TW' as Locale, name: '繁體中文', flag: '🇹🇼' },
|
||||
{ code: 'en' as Locale, name: 'English', flag: '🇺🇸' },
|
||||
];
|
||||
|
||||
export async function getTranslations(locale: Locale, namespace: string) {
|
||||
// Validate inputs
|
||||
if (!locales.includes(locale) || !namespace || namespace.includes('.')) {
|
||||
console.warn(`Invalid locale or namespace: ${locale}/${namespace}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
try {
|
||||
const translations = await import(`../data/locales/${locale}/${namespace}.json`);
|
||||
return translations.default;
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load translations for ${locale}/${namespace}:`, error);
|
||||
// Fallback to default locale
|
||||
if (locale !== defaultLocale) {
|
||||
try {
|
||||
const fallbackTranslations = await import(
|
||||
`../data/locales/${defaultLocale}/${namespace}.json`
|
||||
);
|
||||
return fallbackTranslations.default;
|
||||
} catch (fallbackError) {
|
||||
console.error(
|
||||
`Failed to load fallback translations for ${defaultLocale}/${namespace}:`,
|
||||
fallbackError,
|
||||
);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export function getLocaleFromPath(pathname: string): Locale {
|
||||
const segments = pathname.split('/').filter(Boolean);
|
||||
const firstSegment = segments[0];
|
||||
|
||||
if (locales.includes(firstSegment as Locale)) {
|
||||
return firstSegment as Locale;
|
||||
}
|
||||
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
export function removeLocaleFromPath(pathname: string): string {
|
||||
const segments = pathname.split('/').filter(Boolean);
|
||||
const firstSegment = segments[0];
|
||||
|
||||
if (locales.includes(firstSegment as Locale)) {
|
||||
return '/' + segments.slice(1).join('/');
|
||||
}
|
||||
|
||||
return pathname;
|
||||
}
|
||||
|
||||
export function addLocaleToPath(pathname: string, locale: Locale): string {
|
||||
if (locale === defaultLocale) {
|
||||
return pathname;
|
||||
}
|
||||
|
||||
const cleanPath = removeLocaleFromPath(pathname);
|
||||
return `/${locale}${cleanPath === '/' ? '' : cleanPath}`;
|
||||
}
|
||||
|
||||
export function generateLocalizedPath(path: string, locale: Locale): string {
|
||||
// Remove leading slash if present
|
||||
const cleanPath = path.startsWith('/') ? path.slice(1) : path;
|
||||
|
||||
if (locale === defaultLocale) {
|
||||
return `/${cleanPath}`;
|
||||
}
|
||||
|
||||
return `/${locale}/${cleanPath}`;
|
||||
}
|
||||
|
||||
export function getNavigationPaths(locale: Locale) {
|
||||
const basePaths = [
|
||||
{ key: 'home', path: '' },
|
||||
{ key: 'products', path: 'products' },
|
||||
{ key: 'news', path: 'news' },
|
||||
{ key: 'support', path: 'support' },
|
||||
{ key: 'about', path: 'about' },
|
||||
];
|
||||
|
||||
return basePaths.map((item) => ({
|
||||
key: item.key,
|
||||
path: generateLocalizedPath(item.path, locale),
|
||||
}));
|
||||
}
|
||||
125
lib/markdown.ts
Normal file
125
lib/markdown.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import matter from 'gray-matter';
|
||||
import { Locale } from './i18n';
|
||||
|
||||
export interface NewsArticle {
|
||||
id: string;
|
||||
title: string;
|
||||
category: string;
|
||||
date: string;
|
||||
excerpt: string;
|
||||
author: string;
|
||||
readTime: string;
|
||||
tags: string[];
|
||||
featured: boolean;
|
||||
content: string;
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
const DOCS_PATH = path.join(process.cwd(), 'docs', 'news');
|
||||
|
||||
export async function getNewsArticle(id: string, locale: Locale): Promise<NewsArticle | null> {
|
||||
try {
|
||||
const filePath = path.join(DOCS_PATH, locale, `${id}.md`);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileContents = fs.readFileSync(filePath, 'utf8');
|
||||
const { data, content } = matter(fileContents);
|
||||
|
||||
return {
|
||||
id,
|
||||
title: data.title,
|
||||
category: data.category,
|
||||
date: data.date,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
readTime: data.readTime,
|
||||
tags: data.tags || [],
|
||||
featured: data.featured || false,
|
||||
content,
|
||||
locale,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error reading article ${id} for locale ${locale}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAllNewsArticles(locale: Locale): Promise<NewsArticle[]> {
|
||||
try {
|
||||
const articlesDir = path.join(DOCS_PATH, locale);
|
||||
|
||||
if (!fs.existsSync(articlesDir)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const filenames = fs.readdirSync(articlesDir);
|
||||
const articles: NewsArticle[] = [];
|
||||
|
||||
for (const filename of filenames) {
|
||||
if (filename.endsWith('.md')) {
|
||||
const id = filename.replace(/\.md$/, '');
|
||||
const article = await getNewsArticle(id, locale);
|
||||
if (article) {
|
||||
articles.push(article);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by date (newest first)
|
||||
// Handle Chinese date format (e.g., "2024年1月15日")
|
||||
const parseChineseDate = (dateStr: string): Date => {
|
||||
// Try to parse Chinese date format first
|
||||
const chineseDateMatch = dateStr.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);
|
||||
if (chineseDateMatch) {
|
||||
const [, year, month, day] = chineseDateMatch;
|
||||
return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
|
||||
}
|
||||
// Fallback to regular Date parsing
|
||||
return new Date(dateStr);
|
||||
};
|
||||
|
||||
return articles.sort((a, b) => {
|
||||
const dateA = parseChineseDate(a.date);
|
||||
const dateB = parseChineseDate(b.date);
|
||||
return dateB.getTime() - dateA.getTime();
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error reading articles for locale ${locale}:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAvailableLocalesForArticle(id: string): Promise<Locale[]> {
|
||||
const availableLocales: Locale[] = [];
|
||||
const locales: Locale[] = ['zh-CN', 'zh-TW', 'en'];
|
||||
|
||||
for (const locale of locales) {
|
||||
const filePath = path.join(DOCS_PATH, locale, `${id}.md`);
|
||||
if (fs.existsSync(filePath)) {
|
||||
availableLocales.push(locale);
|
||||
}
|
||||
}
|
||||
|
||||
return availableLocales;
|
||||
}
|
||||
|
||||
export function checkArticleExists(id: string, locale: Locale): boolean {
|
||||
const filePath = path.join(DOCS_PATH, locale, `${id}.md`);
|
||||
return fs.existsSync(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新的新闻文章(用于首页显示)
|
||||
* @param locale 语言
|
||||
* @param limit 限制文章数量,默认为3
|
||||
* @returns 最新的新闻文章数组
|
||||
*/
|
||||
export async function getLatestNewsArticles(locale: Locale, limit: number = 3): Promise<NewsArticle[]> {
|
||||
const allArticles = await getAllNewsArticles(locale);
|
||||
return allArticles.slice(0, limit);
|
||||
}
|
||||
358
lib/seo.ts
Normal file
358
lib/seo.ts
Normal file
@ -0,0 +1,358 @@
|
||||
import { Locale, getTranslations } from './i18n';
|
||||
|
||||
export interface SEOData {
|
||||
title: string;
|
||||
description: string;
|
||||
keywords: string[];
|
||||
}
|
||||
|
||||
export interface PageSEO {
|
||||
[key: string]: SEOData;
|
||||
}
|
||||
|
||||
// 保留原有的静态配置作为后备方案
|
||||
export const seoConfig: Record<Locale, PageSEO> = {
|
||||
'zh-CN': {
|
||||
about: {
|
||||
title: '关于我们 - HaoAWS企业云计算与数字化转型专家',
|
||||
description:
|
||||
'HaoAWS是一家专注于AWS云服务与企业数字化转型的科技公司。拥有150+AWS专业团队,服务800+成功项目,致力于通过专业的云计算解决方案帮助企业实现数字化转型。',
|
||||
keywords: [
|
||||
'AWS云服务',
|
||||
'企业数字化',
|
||||
'云计算咨询',
|
||||
'云架构设计',
|
||||
'HaoAWS公司',
|
||||
'数字化专家',
|
||||
'云技术服务',
|
||||
'企业转型',
|
||||
],
|
||||
},
|
||||
products: {
|
||||
title: '产品与服务 - 全方位AWS云计算解决方案',
|
||||
description:
|
||||
'提供AWS云架构设计、数据分析平台、云迁移服务、网络安全解决方案等全方位云技术服务。专业团队为您量身定制云计算转型方案。',
|
||||
keywords: [
|
||||
'AWS云架构',
|
||||
'数据分析平台',
|
||||
'云迁移服务',
|
||||
'云计算解决方案',
|
||||
'网络安全',
|
||||
'系统集成',
|
||||
'云技术咨询',
|
||||
],
|
||||
},
|
||||
news: {
|
||||
title: '新闻资讯 - 云计算行业动态与技术趋势',
|
||||
description:
|
||||
'获取最新的云计算行业动态、数字化转型趋势、AWS技术发展、云计算资讯等。了解HaoAWS公司最新动态和技术洞察。',
|
||||
keywords: [
|
||||
'云计算新闻',
|
||||
'数字化趋势',
|
||||
'AWS技术',
|
||||
'云计算资讯',
|
||||
'行业动态',
|
||||
'技术洞察',
|
||||
'HaoAWS',
|
||||
],
|
||||
},
|
||||
support: {
|
||||
title: '客户支持 - 专业技术支持服务',
|
||||
description:
|
||||
'提供7x24小时专业技术支持服务,包括在线咨询、技术文档、培训服务等。我们的专家团队随时为您解决技术问题。',
|
||||
keywords: [
|
||||
'技术支持',
|
||||
'客户服务',
|
||||
'在线咨询',
|
||||
'技术培训',
|
||||
'问题解决',
|
||||
'专家团队',
|
||||
'售后服务',
|
||||
],
|
||||
},
|
||||
},
|
||||
'zh-TW': {
|
||||
about: {
|
||||
title: '關於我們 - HaoAWS企業雲端運算與數位化轉型專家',
|
||||
description:
|
||||
'HaoAWS是一家專注於AWS雲端服務與企業數位化轉型的科技公司。擁有150+AWS專業團隊,服務800+成功專案,致力於透過專業的雲端運算解決方案幫助企業實現數位化轉型。',
|
||||
keywords: [
|
||||
'AWS雲端服務',
|
||||
'企業數位化',
|
||||
'雲端運算諮詢',
|
||||
'雲端架構設計',
|
||||
'HaoAWS公司',
|
||||
'數位化專家',
|
||||
'雲端技術服務',
|
||||
'企業轉型',
|
||||
],
|
||||
},
|
||||
products: {
|
||||
title: '產品與服務 - 全方位AWS雲端運算解決方案',
|
||||
description:
|
||||
'提供AWS雲端架構設計、數據分析平台、雲端遷移服務、網路安全解決方案等全方位雲端技術服務。專業團隊為您量身定制雲端運算轉型方案。',
|
||||
keywords: [
|
||||
'AWS雲端架構',
|
||||
'數據分析平台',
|
||||
'雲端遷移服務',
|
||||
'雲端運算解決方案',
|
||||
'網路安全',
|
||||
'系統整合',
|
||||
'雲端技術諮詢',
|
||||
],
|
||||
},
|
||||
news: {
|
||||
title: '新聞資訊 - 雲端運算行業動態與技術趨勢',
|
||||
description:
|
||||
'獲取最新的雲端運算行業動態、數位化轉型趨勢、AWS技術發展、雲端運算資訊等。了解HaoAWS公司最新動態和技術洞察。',
|
||||
keywords: [
|
||||
'雲端運算新聞',
|
||||
'數位化趨勢',
|
||||
'AWS技術',
|
||||
'雲端運算資訊',
|
||||
'行業動態',
|
||||
'技術洞察',
|
||||
'HaoAWS',
|
||||
],
|
||||
},
|
||||
support: {
|
||||
title: '客戶支援 - 專業技術支援服務',
|
||||
description:
|
||||
'提供7x24小時專業技術支援服務,包括線上諮詢、技術文件、培訓服務等。我們的專家團隊隨時為您解決技術問題。',
|
||||
keywords: [
|
||||
'技術支援',
|
||||
'客戶服務',
|
||||
'線上諮詢',
|
||||
'技術培訓',
|
||||
'問題解決',
|
||||
'專家團隊',
|
||||
'售後服務',
|
||||
],
|
||||
},
|
||||
},
|
||||
en: {
|
||||
about: {
|
||||
title: 'About Us - HaoAWS Enterprise Cloud Computing & Digital Transformation Experts',
|
||||
description:
|
||||
'HaoAWS is a technology company focused on AWS cloud services and enterprise digital transformation. With 150+ AWS professional team members and 800+ successful projects, we help enterprises achieve digital transformation through professional cloud computing solutions.',
|
||||
keywords: [
|
||||
'AWS cloud services',
|
||||
'enterprise digitalization',
|
||||
'cloud computing consulting',
|
||||
'cloud architecture design',
|
||||
'HaoAWS company',
|
||||
'digital experts',
|
||||
'cloud tech services',
|
||||
'business transformation',
|
||||
],
|
||||
},
|
||||
products: {
|
||||
title: 'Products & Services - Comprehensive AWS Cloud Computing Solutions',
|
||||
description:
|
||||
'Offering AWS cloud architecture design, data analytics platforms, cloud migration services, cybersecurity solutions and comprehensive cloud technical services. Professional team provides customized cloud computing transformation solutions.',
|
||||
keywords: [
|
||||
'AWS cloud architecture',
|
||||
'data analytics platform',
|
||||
'cloud migration',
|
||||
'cloud computing solutions',
|
||||
'cybersecurity',
|
||||
'system integration',
|
||||
'cloud technology consulting',
|
||||
],
|
||||
},
|
||||
news: {
|
||||
title: 'News & Updates - Cloud Computing Industry Trends & Technology Insights',
|
||||
description:
|
||||
'Get the latest cloud computing industry news, digital transformation trends, AWS technology developments, cloud computing insights. Stay updated with HaoAWS company news and technical insights.',
|
||||
keywords: [
|
||||
'cloud computing news',
|
||||
'digital trends',
|
||||
'AWS technology',
|
||||
'cloud computing',
|
||||
'industry insights',
|
||||
'technology updates',
|
||||
'HaoAWS',
|
||||
],
|
||||
},
|
||||
support: {
|
||||
title: 'Customer Support - Professional Technical Support Services',
|
||||
description:
|
||||
'Providing 24/7 professional technical support services including online consultation, technical documentation, training services. Our expert team is ready to solve your technical challenges.',
|
||||
keywords: [
|
||||
'technical support',
|
||||
'customer service',
|
||||
'online consultation',
|
||||
'technical training',
|
||||
'problem solving',
|
||||
'expert team',
|
||||
'after-sales service',
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// 从locale文件获取SEO数据的新函数
|
||||
export async function getSEODataFromLocale(locale: Locale, page: string): Promise<SEOData | null> {
|
||||
try {
|
||||
const translations = await getTranslations(locale, page);
|
||||
if (translations?.seo) {
|
||||
return {
|
||||
title: translations.seo.title,
|
||||
description: translations.seo.description,
|
||||
keywords: translations.seo.keywords || [],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load SEO data from locale file for ${locale}/${page}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSEOData(locale: Locale, page: string): Promise<SEOData> {
|
||||
// 首先尝试从locale文件获取SEO数据
|
||||
const localeData = await getSEODataFromLocale(locale, page);
|
||||
if (localeData) {
|
||||
return localeData;
|
||||
}
|
||||
|
||||
// 如果locale文件中没有SEO数据,则使用静态配置
|
||||
return (
|
||||
seoConfig[locale]?.[page] ||
|
||||
seoConfig[locale]?.home ||
|
||||
seoConfig['zh-CN'].home || {
|
||||
title: '创新科技',
|
||||
description: '专注企业数字化转型的科技公司',
|
||||
keywords: ['数字化转型', '企业软件开发', 'AI解决方案'],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateMetadata(locale: Locale, page: string) {
|
||||
const seoData = await getSEOData(locale, page);
|
||||
const baseUrl = 'https://haoaws.com';
|
||||
const currentUrl = `${baseUrl}${locale === 'zh-CN' ? '' : `/${locale}`}${page === 'home' ? '' : `/${page}`}`;
|
||||
|
||||
const companyNames = {
|
||||
'zh-CN': '创新科技',
|
||||
'zh-TW': '創新科技',
|
||||
en: 'Innovation Tech',
|
||||
};
|
||||
|
||||
return {
|
||||
title: seoData.title,
|
||||
description: seoData.description,
|
||||
keywords: seoData.keywords.join(', '),
|
||||
authors: [{ name: companyNames[locale], url: baseUrl }],
|
||||
creator: companyNames[locale],
|
||||
publisher: companyNames[locale],
|
||||
formatDetection: {
|
||||
email: false,
|
||||
address: false,
|
||||
telephone: false,
|
||||
},
|
||||
metadataBase: new URL(baseUrl),
|
||||
openGraph: {
|
||||
title: seoData.title,
|
||||
description: seoData.description,
|
||||
url: currentUrl,
|
||||
siteName: companyNames[locale],
|
||||
type: 'website',
|
||||
locale: locale === 'zh-CN' ? 'zh_CN' : locale === 'zh-TW' ? 'zh_TW' : 'en_US',
|
||||
images: [
|
||||
{
|
||||
url: '/og-image-home.jpg',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: seoData.title,
|
||||
type: 'image/jpeg',
|
||||
},
|
||||
{
|
||||
url: '/og-image-square.jpg',
|
||||
width: 800,
|
||||
height: 800,
|
||||
alt: seoData.title,
|
||||
type: 'image/jpeg',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: seoData.title,
|
||||
description: seoData.description,
|
||||
images: ['/twitter-image.jpg'],
|
||||
creator: '@innovation_tech',
|
||||
site: '@innovation_tech',
|
||||
},
|
||||
alternates: {
|
||||
canonical: currentUrl,
|
||||
languages: {
|
||||
'zh-CN': `${baseUrl}${page === 'home' ? '' : `/${page}`}`,
|
||||
'zh-TW': `${baseUrl}/zh-TW${page === 'home' ? '' : `/${page}`}`,
|
||||
en: `${baseUrl}/en${page === 'home' ? '' : `/${page}`}`,
|
||||
'x-default': `${baseUrl}${page === 'home' ? '' : `/${page}`}`,
|
||||
},
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
nocache: false,
|
||||
googleBot: {
|
||||
index: true,
|
||||
follow: true,
|
||||
noimageindex: false,
|
||||
'max-video-preview': -1,
|
||||
'max-image-preview': 'large',
|
||||
'max-snippet': -1,
|
||||
},
|
||||
},
|
||||
verification: {
|
||||
google: 'your-google-site-verification',
|
||||
yandex: 'your-yandex-verification',
|
||||
yahoo: 'your-yahoo-verification',
|
||||
other: {
|
||||
'baidu-site-verification': 'your-baidu-verification',
|
||||
sogou_site_verification: 'your-sogou-verification',
|
||||
},
|
||||
},
|
||||
category: page === 'home' ? 'technology' : page,
|
||||
classification: 'Business',
|
||||
referrer: 'origin-when-cross-origin',
|
||||
colorScheme: 'light',
|
||||
themeColor: [
|
||||
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
|
||||
{ media: '(prefers-color-scheme: dark)', color: '#000000' },
|
||||
],
|
||||
viewport: {
|
||||
width: 'device-width',
|
||||
initialScale: 1,
|
||||
maximumScale: 5,
|
||||
},
|
||||
manifest: '/site.webmanifest',
|
||||
icons: {
|
||||
icon: [
|
||||
{ url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' },
|
||||
{ url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
|
||||
],
|
||||
apple: [{ url: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' }],
|
||||
other: [
|
||||
{
|
||||
rel: 'mask-icon',
|
||||
url: '/safari-pinned-tab.svg',
|
||||
color: '#000000',
|
||||
},
|
||||
],
|
||||
},
|
||||
appleWebApp: {
|
||||
capable: true,
|
||||
title: companyNames[locale],
|
||||
statusBarStyle: 'default',
|
||||
},
|
||||
applicationName: companyNames[locale],
|
||||
generator: 'Next.js',
|
||||
abstract: seoData.description,
|
||||
archives: [`${baseUrl}/news`],
|
||||
assets: [`${baseUrl}/assets`],
|
||||
bookmarks: [`${baseUrl}/products`],
|
||||
};
|
||||
}
|
||||
6
lib/utils.ts
Normal file
6
lib/utils.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
69
middleware.ts
Normal file
69
middleware.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { locales, defaultLocale } from './lib/i18n';
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
// 在静态导出模式下,中间件不会执行
|
||||
// 这个文件保留用于开发和服务器模式
|
||||
|
||||
// 在静态导出模式下跳过中间件逻辑
|
||||
if (process.env.NODE_ENV === 'production' && process.env.NEXT_OUTPUT_MODE === 'export') {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
const pathname = request.nextUrl.pathname;
|
||||
|
||||
// Check if there is any supported locale in the pathname
|
||||
const pathnameIsMissingLocale = locales.every(
|
||||
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`,
|
||||
);
|
||||
|
||||
// Redirect if there is no locale
|
||||
if (pathnameIsMissingLocale) {
|
||||
// Get locale from Accept-Language header or use default
|
||||
const locale = getLocaleFromRequest(request) || defaultLocale;
|
||||
|
||||
// Don't redirect for default locale on root path
|
||||
if (locale === defaultLocale && pathname === '/') {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
// Redirect to locale-prefixed path for non-default locales
|
||||
if (locale !== defaultLocale) {
|
||||
return NextResponse.redirect(
|
||||
new URL(`/${locale}${pathname === '/' ? '' : pathname}`, request.url),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
function getLocaleFromRequest(request: NextRequest): string | undefined {
|
||||
// Get locale from cookie first
|
||||
const localeCookie = request.cookies.get('locale')?.value;
|
||||
if (localeCookie && locales.includes(localeCookie as any)) {
|
||||
return localeCookie;
|
||||
}
|
||||
|
||||
// Get locale from Accept-Language header
|
||||
const acceptLanguage = request.headers.get('accept-language');
|
||||
if (acceptLanguage) {
|
||||
const preferredLocale = acceptLanguage
|
||||
.split(',')
|
||||
.map((lang) => lang.split(';')[0].trim())
|
||||
.find((lang) => locales.includes(lang as any));
|
||||
|
||||
if (preferredLocale) {
|
||||
return preferredLocale;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
// Skip all internal paths (_next), static files, and manifest files
|
||||
'/((?!_next|api|favicon.ico|site.webmanifest|.*\\..*).*)',
|
||||
],
|
||||
};
|
||||
28
next.config.mjs
Normal file
28
next.config.mjs
Normal file
@ -0,0 +1,28 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// 仅在构建静态版本时启用导出 (npm run build:static)
|
||||
output: process.env.BUILD_MODE === 'static' ? 'export' : undefined,
|
||||
|
||||
// 静态资源优化
|
||||
images: {
|
||||
unoptimized: process.env.BUILD_MODE === 'static', // 仅在静态导出时禁用优化
|
||||
},
|
||||
|
||||
// 确保静态导出正常工作
|
||||
trailingSlash: true,
|
||||
|
||||
// 禁用服务器端功能(静态导出不支持)
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true, // 临时禁用以避免构建问题
|
||||
},
|
||||
|
||||
// 禁用构建追踪以避免权限问题
|
||||
experimental: {
|
||||
outputFileTracingRoot: undefined,
|
||||
},
|
||||
|
||||
// 基础路径配置(如果需要部署到子路径)
|
||||
// basePath: '/your-subdirectory',
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
7865
package-lock.json
generated
Normal file
7865
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
package.json
Normal file
42
package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "@onlook/next-template",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"build:static": "node build-static.js",
|
||||
"build:simple": "set NEXT_DISABLE_TELEMETRY=1 && next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"format": "prettier --write .",
|
||||
"serve": "npx serve out",
|
||||
"preview": "npm run build:static && npm run serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"gray-matter": "^4.0.3",
|
||||
"lucide-react": "^0.438.0",
|
||||
"next": "14.2.23",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-markdown": "^10.1.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"tailwind-merge": "^2.5.2",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^15.1.6",
|
||||
"postcss": "^8",
|
||||
"prettier": "^3.3.3",
|
||||
"serve": "^14.2.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
8
postcss.config.mjs
Normal file
8
postcss.config.mjs
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
BIN
public/images/logo.png
Normal file
BIN
public/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
16
public/site.webmanifest
Normal file
16
public/site.webmanifest
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "HaoAWS",
|
||||
"short_name": "HaoAWS",
|
||||
"description": "HaoAWS官方网站",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#ffffff",
|
||||
"theme_color": "#ffffff",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/favicon.ico",
|
||||
"sizes": "48x48",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
]
|
||||
}
|
||||
67
tailwind.config.ts
Normal file
67
tailwind.config.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
backgroundImage: {
|
||||
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
||||
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))'
|
||||
},
|
||||
borderRadius: {
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
sm: 'calc(var(--radius) - 4px)'
|
||||
},
|
||||
colors: {
|
||||
background: 'hsl(var(--background))',
|
||||
foreground: 'hsl(var(--foreground))',
|
||||
card: {
|
||||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))'
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: 'hsl(var(--popover))',
|
||||
foreground: 'hsl(var(--popover-foreground))'
|
||||
},
|
||||
primary: {
|
||||
DEFAULT: 'hsl(var(--primary))',
|
||||
foreground: 'hsl(var(--primary-foreground))'
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))'
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: 'hsl(var(--muted))',
|
||||
foreground: 'hsl(var(--muted-foreground))'
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: 'hsl(var(--accent))',
|
||||
foreground: 'hsl(var(--accent-foreground))'
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: 'hsl(var(--destructive))',
|
||||
foreground: 'hsl(var(--destructive-foreground))'
|
||||
},
|
||||
border: 'hsl(var(--border))',
|
||||
input: 'hsl(var(--input))',
|
||||
ring: 'hsl(var(--ring))',
|
||||
chart: {
|
||||
'1': 'hsl(var(--chart-1))',
|
||||
'2': 'hsl(var(--chart-2))',
|
||||
'3': 'hsl(var(--chart-3))',
|
||||
'4': 'hsl(var(--chart-4))',
|
||||
'5': 'hsl(var(--chart-5))'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
};
|
||||
export default config;
|
||||
40
tsconfig.json
Normal file
40
tsconfig.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"out/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user