405 lines
18 KiB
TypeScript
405 lines
18 KiB
TypeScript
|
|
'use client';
|
|||
|
|
|
|||
|
|
import { useState, useEffect } from 'react';
|
|||
|
|
import Link from 'next/link';
|
|||
|
|
import Header from '@/app/components/Header';
|
|||
|
|
import Footer from '@/app/components/Footer';
|
|||
|
|
import { type Article } from '../../lib/types';
|
|||
|
|
// News translations
|
|||
|
|
export const newsTranslations = {
|
|||
|
|
'zh-CN': {
|
|||
|
|
nav: {
|
|||
|
|
home: '首页',
|
|||
|
|
products: '产品与服务',
|
|||
|
|
news: '新闻资讯',
|
|||
|
|
support: '客户支持',
|
|||
|
|
about: '关于我们',
|
|||
|
|
contact: '联系我们',
|
|||
|
|
},
|
|||
|
|
title: '新闻资讯',
|
|||
|
|
subtitle: '了解最新的云计算技术动态和行业资讯',
|
|||
|
|
categories: [
|
|||
|
|
{ id: 'all', name: '全部' },
|
|||
|
|
{ id: 'tech', name: '技术动态' },
|
|||
|
|
{ id: 'product', name: '产品更新' },
|
|||
|
|
{ id: 'industry', name: '行业资讯' },
|
|||
|
|
{ id: 'company', name: '公司动态' },
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
articles: [
|
|||
|
|
{
|
|||
|
|
id: '1',
|
|||
|
|
title: 'AWS新一代EC2实例发布,性能提升50%',
|
|||
|
|
excerpt:
|
|||
|
|
'AWS发布了新一代EC2实例,采用最新的处理器技术,在计算性能、网络性能和存储性能方面都有显著提升...',
|
|||
|
|
category: 'tech',
|
|||
|
|
date: '2024-01-15',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '2',
|
|||
|
|
title: '云安全最佳实践:保护您的AWS环境',
|
|||
|
|
excerpt:
|
|||
|
|
'随着云计算的普及,云安全变得越来越重要。本文将介绍AWS环境下的安全最佳实践...',
|
|||
|
|
category: 'tech',
|
|||
|
|
date: '2024-01-12',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '3',
|
|||
|
|
title: '合肥懂云获得AWS高级合作伙伴认证',
|
|||
|
|
excerpt: '我们很高兴地宣布,合肥懂云信息科技有限公司正式获得AWS高级合作伙伴认证...',
|
|||
|
|
category: 'company',
|
|||
|
|
date: '2024-01-10',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
readMore: '阅读更多',
|
|||
|
|
noArticles: '暂无相关文章',
|
|||
|
|
footer: {
|
|||
|
|
sections: [
|
|||
|
|
{
|
|||
|
|
title: '目录',
|
|||
|
|
items: ['首页', '产品与服务', '新闻资讯', '客户支持', '关于我们'],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
title: '热门产品',
|
|||
|
|
items: ['轻量云服务器', '站群服务器', 'EC2服务器', '高防服务器', 'S3云存储'],
|
|||
|
|
},
|
|||
|
|
{ title: '客户支持', items: ['技术支持', '在线客服', '帮助文档', '服务状态'] },
|
|||
|
|
{ title: '', items: ['新闻资讯', '关于我们', '隐私政策', '站点地图'] },
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
'zh-TW': {
|
|||
|
|
nav: {
|
|||
|
|
home: '首頁',
|
|||
|
|
products: '產品與服務',
|
|||
|
|
news: '新聞資訊',
|
|||
|
|
support: '客戶支持',
|
|||
|
|
about: '關於我們',
|
|||
|
|
contact: '聯繫我們',
|
|||
|
|
},
|
|||
|
|
title: '新聞資訊',
|
|||
|
|
subtitle: '了解最新的雲計算技術動態和行業資訊',
|
|||
|
|
categories: [
|
|||
|
|
{ id: 'all', name: '全部' },
|
|||
|
|
{ id: 'tech', name: '技術動態' },
|
|||
|
|
{ id: 'product', name: '產品更新' },
|
|||
|
|
{ id: 'industry', name: '行業資訊' },
|
|||
|
|
{ id: 'company', name: '公司動態' },
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
articles: [
|
|||
|
|
{
|
|||
|
|
id: '1',
|
|||
|
|
title: 'AWS新一代EC2實例發布,性能提升50%',
|
|||
|
|
excerpt:
|
|||
|
|
'AWS發布了新一代EC2實例,採用最新的處理器技術,在計算性能、網絡性能和存儲性能方面都有顯著提升...',
|
|||
|
|
category: 'tech',
|
|||
|
|
date: '2024-01-15',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '2',
|
|||
|
|
title: '雲安全最佳實踐:保護您的AWS環境',
|
|||
|
|
excerpt:
|
|||
|
|
'隨著雲計算的普及,雲安全變得越來越重要。本文將介紹AWS環境下的安全最佳實踐...',
|
|||
|
|
category: 'tech',
|
|||
|
|
date: '2024-01-12',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '3',
|
|||
|
|
title: '合肥懂雲獲得AWS高級合作夥伴認證',
|
|||
|
|
excerpt: '我們很高興地宣布,合肥懂雲信息科技有限公司正式獲得AWS高級合作夥伴認證...',
|
|||
|
|
category: 'company',
|
|||
|
|
date: '2024-01-10',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
readMore: '閱讀更多',
|
|||
|
|
noArticles: '暫無相關文章',
|
|||
|
|
footer: {
|
|||
|
|
sections: [
|
|||
|
|
{
|
|||
|
|
title: '目錄',
|
|||
|
|
items: ['首頁', '產品與服務', '新聞資訊', '客戶支持', '關於我們'],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
title: '熱門產品',
|
|||
|
|
items: ['輕量雲服務器', '站群服務器', 'EC2服務器', '高防服務器', 'S3雲存儲'],
|
|||
|
|
},
|
|||
|
|
{ title: '客戶支持', items: ['技術支持', '在線客服', '幫助文檔', '服務狀態'] },
|
|||
|
|
{ title: '', items: ['新聞資訊', '關於我們', '隱私政策', '站點地圖'] },
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
en: {
|
|||
|
|
nav: {
|
|||
|
|
home: 'Home',
|
|||
|
|
products: 'Products & Services',
|
|||
|
|
news: 'News',
|
|||
|
|
support: 'Support',
|
|||
|
|
about: 'About Us',
|
|||
|
|
contact: 'Contact Us',
|
|||
|
|
},
|
|||
|
|
title: 'News & Updates',
|
|||
|
|
subtitle: 'Stay updated with the latest cloud computing technology and industry insights',
|
|||
|
|
categories: [
|
|||
|
|
{ id: 'all', name: 'All' },
|
|||
|
|
{ id: 'tech', name: 'Technology' },
|
|||
|
|
{ id: 'product', name: 'Product Updates' },
|
|||
|
|
{ id: 'industry', name: 'Industry News' },
|
|||
|
|
{ id: 'company', name: 'Company News' },
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
articles: [
|
|||
|
|
{
|
|||
|
|
id: '1',
|
|||
|
|
title: 'AWS Launches New Generation EC2 Instances with 50% Performance Boost',
|
|||
|
|
excerpt:
|
|||
|
|
'AWS has released new generation EC2 instances featuring the latest processor technology, with significant improvements in compute, network, and storage performance...',
|
|||
|
|
category: 'tech',
|
|||
|
|
date: '2024-01-15',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '2',
|
|||
|
|
title: 'Cloud Security Best Practices: Protecting Your AWS Environment',
|
|||
|
|
excerpt:
|
|||
|
|
'As cloud computing becomes more prevalent, cloud security is becoming increasingly important. This article covers security best practices for AWS environments...',
|
|||
|
|
category: 'tech',
|
|||
|
|
date: '2024-01-12',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '3',
|
|||
|
|
title: 'Hefei DongYun Achieves AWS Advanced Partner Certification',
|
|||
|
|
excerpt:
|
|||
|
|
'We are pleased to announce that Hefei DongYun Information Technology Co., Ltd. has officially achieved AWS Advanced Partner certification...',
|
|||
|
|
category: 'company',
|
|||
|
|
date: '2024-01-10',
|
|||
|
|
image: '/api/placeholder/400/250',
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
readMore: 'Read More',
|
|||
|
|
noArticles: 'No articles available',
|
|||
|
|
footer: {
|
|||
|
|
sections: [
|
|||
|
|
{
|
|||
|
|
title: 'Directory',
|
|||
|
|
items: ['Home', 'Products & Services', 'News', 'Support', 'About Us'],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
title: 'Popular Products',
|
|||
|
|
items: [
|
|||
|
|
'Lightweight Cloud Server',
|
|||
|
|
'Station Group Server',
|
|||
|
|
'EC2 Server',
|
|||
|
|
'High-Defense Server',
|
|||
|
|
'S3 Cloud Storage',
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
{ title: 'Customer Support', items: ['Technical Support', 'Online Service', 'Help Documentation', 'Service Status'] },
|
|||
|
|
{ title: '', items: ['News', 'About Us', 'Privacy Policy', 'Site Map'] },
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
type NewsLanguage = keyof typeof newsTranslations;
|
|||
|
|
|
|||
|
|
interface NewsPageClientProps {
|
|||
|
|
locale: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default function NewsPageClient({ locale }: NewsPageClientProps) {
|
|||
|
|
const [language, setLanguage] = useState<NewsLanguage>(
|
|||
|
|
locale === 'zh' ? 'zh-CN' : locale === 'zh-TW' ? 'zh-TW' : 'en',
|
|||
|
|
);
|
|||
|
|
const [selectedCategory, setSelectedCategory] = useState('all');
|
|||
|
|
const [articles, setArticles] = useState<Article[]>([]);
|
|||
|
|
const [categories, setCategories] = useState<{ id: string; name: string }[]>([]);
|
|||
|
|
const t = newsTranslations[language] || newsTranslations['zh-CN'];
|
|||
|
|
const [loading, setLoading] = useState(true);
|
|||
|
|
// Load articles and categories when language or category changes
|
|||
|
|
useEffect(() => {
|
|||
|
|
const fetchArticles = async () => {
|
|||
|
|
setLoading(true);
|
|||
|
|
try {
|
|||
|
|
const response = await fetch(
|
|||
|
|
`/api/articles?locale=${language}&category=${selectedCategory}`,
|
|||
|
|
);
|
|||
|
|
if (response.ok) {
|
|||
|
|
const data = await response.json();
|
|||
|
|
setArticles(data.articles);
|
|||
|
|
|
|||
|
|
// Set categories only on first load or language change
|
|||
|
|
if (selectedCategory === 'all') {
|
|||
|
|
const t = newsTranslations[language] || newsTranslations['zh-CN'];
|
|||
|
|
const categoryMap: { [key: string]: string } = {
|
|||
|
|
tech: t.categories.find((c) => c.id === 'tech')?.name || 'Technology',
|
|||
|
|
product:
|
|||
|
|
t.categories.find((c) => c.id === 'product')?.name || 'Product',
|
|||
|
|
industry:
|
|||
|
|
t.categories.find((c) => c.id === 'industry')?.name || 'Industry',
|
|||
|
|
company:
|
|||
|
|
t.categories.find((c) => c.id === 'company')?.name || 'Company',
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const mappedCategories = [
|
|||
|
|
{
|
|||
|
|
id: 'all',
|
|||
|
|
name: t.categories.find((c) => c.id === 'all')?.name || 'All',
|
|||
|
|
},
|
|||
|
|
...data.categories.map((cat: string) => ({
|
|||
|
|
id: cat,
|
|||
|
|
name: categoryMap[cat] || cat,
|
|||
|
|
})),
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
setCategories(mappedCategories);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Error fetching articles:', error);
|
|||
|
|
} finally {
|
|||
|
|
setLoading(false);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
fetchArticles();
|
|||
|
|
}, [language, selectedCategory]);
|
|||
|
|
|
|||
|
|
const handleLanguageChange = (newLanguage: string) => {
|
|||
|
|
const validLanguage = newLanguage as NewsLanguage;
|
|||
|
|
setLanguage(validLanguage);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="min-h-screen bg-white">
|
|||
|
|
<Header
|
|||
|
|
language={language}
|
|||
|
|
setLanguage={handleLanguageChange}
|
|||
|
|
translations={t}
|
|||
|
|
locale={locale}
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
{/* Hero Section */}
|
|||
|
|
<section className="bg-blue-600 text-white h-96 flex items-center justify-center">
|
|||
|
|
<div className="max-w-6xl mx-auto px-4 text-center">
|
|||
|
|
<h1 className="text-4xl font-bold mb-4">{t.title}</h1>
|
|||
|
|
<p className="text-xl">{t.subtitle}</p>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
{/* Category Filter */}
|
|||
|
|
<section className="py-8 bg-gray-50">
|
|||
|
|
<div className="max-w-6xl mx-auto px-4">
|
|||
|
|
<div className="flex flex-wrap justify-center gap-4">
|
|||
|
|
{categories.map((category) => (
|
|||
|
|
<button
|
|||
|
|
key={category.id}
|
|||
|
|
onClick={() => setSelectedCategory(category.id)}
|
|||
|
|
className={`px-6 py-2 rounded-full transition-colors ${
|
|||
|
|
selectedCategory === category.id
|
|||
|
|
? 'bg-blue-600 text-white'
|
|||
|
|
: 'bg-white text-gray-700 hover:bg-blue-50'
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
{category.name}
|
|||
|
|
</button>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
{/* Articles Section */}
|
|||
|
|
<section className="py-16">
|
|||
|
|
<div className="max-w-6xl mx-auto px-4">
|
|||
|
|
{loading ? (
|
|||
|
|
<div className="flex justify-center items-center py-16">
|
|||
|
|
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
|
|||
|
|
</div>
|
|||
|
|
) : (
|
|||
|
|
<>
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|||
|
|
{articles.map((article) => {
|
|||
|
|
const categoryName =
|
|||
|
|
categories.find(
|
|||
|
|
(cat) => cat.id === article.metadata.category,
|
|||
|
|
)?.name || article.metadata.category;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<article
|
|||
|
|
key={`${article.id}-${article.metadata.locale}`}
|
|||
|
|
className="bg-white rounded-lg shadow-lg overflow-hidden hover:shadow-xl transition-shadow"
|
|||
|
|
>
|
|||
|
|
<img
|
|||
|
|
src={article.metadata.image}
|
|||
|
|
alt={article.metadata.title}
|
|||
|
|
className="w-full h-48 object-cover rounded-t-lg"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<div className="p-6">
|
|||
|
|
<div className="flex items-center justify-between mb-3">
|
|||
|
|
<span className="text-sm text-blue-600 font-medium">
|
|||
|
|
{categoryName}
|
|||
|
|
</span>
|
|||
|
|
<span className="text-sm text-gray-500">
|
|||
|
|
{article.metadata.date}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<h3 className="text-xl font-bold mb-3 line-clamp-2">
|
|||
|
|
{article.metadata.title}
|
|||
|
|
</h3>
|
|||
|
|
<p className="text-gray-600 mb-4 line-clamp-3">
|
|||
|
|
{article.metadata.excerpt}
|
|||
|
|
</p>
|
|||
|
|
<Link
|
|||
|
|
href={
|
|||
|
|
locale === 'zh'
|
|||
|
|
? `/news/${article.metadata.slug}`
|
|||
|
|
: `/${locale}/news/${article.metadata.slug}`
|
|||
|
|
}
|
|||
|
|
className="inline-flex items-center text-blue-600 hover:text-blue-800 font-medium"
|
|||
|
|
>
|
|||
|
|
{t.readMore}
|
|||
|
|
<svg
|
|||
|
|
className="w-4 h-4 ml-2"
|
|||
|
|
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>
|
|||
|
|
</article>
|
|||
|
|
);
|
|||
|
|
})}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{articles.length === 0 && !loading && (
|
|||
|
|
<div className="text-center py-16">
|
|||
|
|
<p className="text-gray-500 text-lg">{t.noArticles}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
<Footer translations={t} />
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|