|
|
@@ -42,45 +42,45 @@ const NewsItem: React.FC<NewsItemProps> = ({news: article}) => {
|
|
|
const coverImageUrl = article.newsUrl ? `${BASE_URL}${article.newsUrl}` : '';
|
|
|
|
|
|
return (
|
|
|
- <div
|
|
|
- className="group flex flex-col md:flex-row md:items-start bg-white rounded-xl p-[15px] md:p-5 shadow-[0_4px_15px_rgba(0,0,0,0.05)] hover:shadow-[0_8px_25px_rgba(0,0,0,0.1)] transition-[transform,box-shadow] duration-300 ease-in-out gap-[15px] md:gap-5 hover:-translate-y-[3px]"
|
|
|
- >
|
|
|
- <div className="shrink-0 w-full h-[180px] md:w-[150px] md:h-[100px] rounded-lg overflow-hidden">
|
|
|
- <Image
|
|
|
- width={1000}
|
|
|
- height={1000}
|
|
|
- src={coverImageUrl}
|
|
|
- alt={article.newsName} // 补充有意义的alt属性,优化可访问性
|
|
|
- loading="lazy"
|
|
|
- className="w-full h-full object-cover transition-transform duration-300 ease-in-out group-hover:scale-[1.05]"
|
|
|
- onError={(e) => {
|
|
|
- // 图片加载失败兜底,提升用户体验
|
|
|
- (e.target as HTMLImageElement).src = '/default-news-cover.png';
|
|
|
- }}
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div className="flex-1 overflow-hidden">
|
|
|
- <h3
|
|
|
- className="text-[1.1rem] md:text-[1.2rem] text-gray-800 font-semibold mb-[10px] leading-snug line-clamp-2 md:line-clamp-1">
|
|
|
- {article.newsName}
|
|
|
- </h3>
|
|
|
- <div className="flex items-center justify-between mb-2 text-[0.85rem] text-gray-400">
|
|
|
- <span className="md:mx-5">{article.newsDesc}</span>
|
|
|
- {/* 可选字段兜底,避免空值展示 */}
|
|
|
- <span className="whitespace-nowrap">作者:{article.newsAuthor || '未知'}</span>
|
|
|
+ <div
|
|
|
+ className="group flex flex-col md:flex-row md:items-start bg-white rounded-xl p-[15px] md:p-5 shadow-[0_4px_15px_rgba(0,0,0,0.05)] hover:shadow-[0_8px_25px_rgba(0,0,0,0.1)] transition-[transform,box-shadow] duration-300 ease-in-out gap-[15px] md:gap-5 hover:-translate-y-[3px]"
|
|
|
+ >
|
|
|
+ <div className="shrink-0 w-full h-[180px] md:w-[150px] md:h-[100px] rounded-lg overflow-hidden">
|
|
|
+ <Image
|
|
|
+ width={1000}
|
|
|
+ height={1000}
|
|
|
+ src={coverImageUrl}
|
|
|
+ alt={article.newsName} // 补充有意义的alt属性,优化可访问性
|
|
|
+ loading="lazy"
|
|
|
+ className="w-full h-full object-cover transition-transform duration-300 ease-in-out group-hover:scale-[1.05]"
|
|
|
+ onError={(e) => {
|
|
|
+ // 图片加载失败兜底,提升用户体验
|
|
|
+ (e.target as HTMLImageElement).src = '/default-news-cover.png';
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="flex-1 overflow-hidden">
|
|
|
+ <h3
|
|
|
+ className="text-[1.1rem] md:text-[1.2rem] text-gray-800 font-semibold mb-[10px] leading-snug line-clamp-2 md:line-clamp-1">
|
|
|
+ {article.newsName}
|
|
|
+ </h3>
|
|
|
+ <div className="flex items-center justify-between mb-2 text-[0.85rem] text-gray-400">
|
|
|
+ <span className="md:mx-5">{article.newsDesc}</span>
|
|
|
+ {/* 可选字段兜底,避免空值展示 */}
|
|
|
+ <span className="whitespace-nowrap">作者:{article.newsAuthor || '未知'}</span>
|
|
|
+ </div>
|
|
|
+ <p className="text-[0.9rem] md:text-[0.95rem] text-gray-600 leading-relaxed line-clamp-3 md:line-clamp-2">
|
|
|
+ {article.content}
|
|
|
+ </p>
|
|
|
</div>
|
|
|
- <p className="text-[0.9rem] md:text-[0.95rem] text-gray-600 leading-relaxed line-clamp-3 md:line-clamp-2">
|
|
|
- {article.content}
|
|
|
- </p>
|
|
|
+ <Link
|
|
|
+ href={`/news/${article.id}`}
|
|
|
+ className="text-blue-500 hover:underline mt-4 self-start text-sm sm:text-base"
|
|
|
+ aria-label={`查看${article.newsName}详情`} // 优化可访问性
|
|
|
+ >
|
|
|
+ 了解更多 >
|
|
|
+ </Link>
|
|
|
</div>
|
|
|
- <Link
|
|
|
- href={`/news/${article.id}`}
|
|
|
- className="text-blue-500 hover:underline mt-4 self-start text-sm sm:text-base"
|
|
|
- aria-label={`查看${article.newsName}详情`} // 优化可访问性
|
|
|
- >
|
|
|
- 了解更多 >
|
|
|
- </Link>
|
|
|
- </div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
@@ -92,14 +92,14 @@ const NewsList: React.FC<NewsListProps> = ({newsList}) => {
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
- <div className="flex flex-col gap-5 mt-5 mb-10">
|
|
|
- {newsList.map((news) => (
|
|
|
- <NewsItem
|
|
|
- key={news.id}
|
|
|
- news={news}
|
|
|
- />
|
|
|
- ))}
|
|
|
- </div>
|
|
|
+ <div className="flex flex-col gap-5 mt-5 mb-10">
|
|
|
+ {newsList.map((news) => (
|
|
|
+ <NewsItem
|
|
|
+ key={news.id}
|
|
|
+ news={news}
|
|
|
+ />
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
@@ -107,8 +107,8 @@ const NewsList: React.FC<NewsListProps> = ({newsList}) => {
|
|
|
const NewsPage: React.FC<NewsPageProps> = ({newsList = []}) => {
|
|
|
// 类型守卫,确保newsList是数组类型
|
|
|
const safeNewsList = useMemo(() =>
|
|
|
- Array.isArray(newsList) ? newsList : [],
|
|
|
- [newsList]);
|
|
|
+ Array.isArray(newsList) ? newsList : [],
|
|
|
+ [newsList]);
|
|
|
|
|
|
const [activeTab, setActiveTab] = useState<keyof typeof CATEGORY_MAP>('company'); // 严格类型约束
|
|
|
const [filteredNews, setFilteredNews] = useState<Article[]>([]);
|
|
|
@@ -121,7 +121,7 @@ const NewsPage: React.FC<NewsPageProps> = ({newsList = []}) => {
|
|
|
const timer = setTimeout(() => {
|
|
|
const targetCategory = CATEGORY_MAP[activeTab];
|
|
|
const filtered = safeNewsList.filter(
|
|
|
- (news) => news.newsCategory === targetCategory
|
|
|
+ (news) => news.newsCategory === targetCategory
|
|
|
);
|
|
|
|
|
|
setFilteredNews(filtered);
|
|
|
@@ -138,36 +138,39 @@ const NewsPage: React.FC<NewsPageProps> = ({newsList = []}) => {
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <div className="max-w-[1200px] mx-auto min-h-screen px-4">
|
|
|
- <div className="flex justify-center mb-[30px] gap-[10px]">
|
|
|
- <button
|
|
|
- className={`px-[30px] py-3 rounded-full text-base transition-all duration-300 ease-in-out outline-none ${
|
|
|
- activeTab === 'company'
|
|
|
- ? "bg-[#2f54eb] text-white shadow-[0_4px_12px_rgba(47,84,235,0.3)]"
|
|
|
- : "bg-gray-200 text-gray-500 hover:bg-gray-300 hover:text-gray-800"
|
|
|
- }`}
|
|
|
- onClick={() => handleTabChange('company')}
|
|
|
- aria-pressed={activeTab === 'company'} // 优化可访问性
|
|
|
- >
|
|
|
- 公司新闻
|
|
|
- </button>
|
|
|
- <button
|
|
|
- className={`px-[30px] py-3 rounded-full text-base transition-all duration-300 ease-in-out outline-none ${
|
|
|
- activeTab === 'industry'
|
|
|
- ? "bg-[#2f54eb] text-white shadow-[0_4px_12px_rgba(47,84,235,0.3)]"
|
|
|
- : "bg-gray-200 text-gray-500 hover:bg-gray-300 hover:text-gray-800"
|
|
|
- }`}
|
|
|
- onClick={() => handleTabChange('industry')}
|
|
|
- aria-pressed={activeTab === 'industry'}
|
|
|
- >
|
|
|
- 行内新闻
|
|
|
- </button>
|
|
|
- </div>
|
|
|
+ <div className="max-w-[1200px] mx-auto min-h-screen px-4">
|
|
|
+ <div className="flex justify-center mb-[30px] gap-[10px]">
|
|
|
+ {/* 核心修复:提升文字样式优先级 + 调整类名顺序 */}
|
|
|
+ <button
|
|
|
+ className={`px-[30px] py-3 rounded-full transition-all duration-300 ease-in-out outline-none font-medium
|
|
|
+ ${activeTab === 'company'
|
|
|
+ ? 'bg-[#2f54eb] text-white !text-white shadow-[0_4px_12px_rgba(47,84,235,0.3)]'
|
|
|
+ : 'bg-gray-200 text-gray-500 hover:bg-gray-300 hover:text-gray-800'
|
|
|
+ }`}
|
|
|
+ onClick={() => handleTabChange('company')}
|
|
|
+ aria-pressed={activeTab === 'company'}
|
|
|
+ style={{ color: activeTab === 'company' ? 'white' : '' }} // 内联样式兜底,确保优先级
|
|
|
+ >
|
|
|
+ 公司新闻
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ className={`px-[30px] py-3 rounded-full transition-all duration-300 ease-in-out outline-none font-medium
|
|
|
+ ${activeTab === 'industry'
|
|
|
+ ? 'bg-[#2f54eb] text-white !text-white shadow-[0_4px_12px_rgba(47,84,235,0.3)]'
|
|
|
+ : 'bg-gray-200 text-gray-500 hover:bg-gray-300 hover:text-gray-800'
|
|
|
+ }`}
|
|
|
+ onClick={() => handleTabChange('industry')}
|
|
|
+ aria-pressed={activeTab === 'industry'}
|
|
|
+ style={{ color: activeTab === 'industry' ? 'white' : '' }} // 内联样式兜底
|
|
|
+ >
|
|
|
+ 行内新闻
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
|
|
|
- {isLoading && <div className="text-center text-[1.2rem] text-gray-500 py-10">加载中...</div>}
|
|
|
- {!isLoading && <NewsList newsList={filteredNews}/>}
|
|
|
- </div>
|
|
|
+ {isLoading && <div className="text-center text-[1.2rem] text-gray-500 py-10">加载中...</div>}
|
|
|
+ {!isLoading && <NewsList newsList={filteredNews}/>}
|
|
|
+ </div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-export default NewsPage;
|
|
|
+export default NewsPage;
|