Files
novalon-website/src/components/sections/insights-section.tsx
T
张翔 fecbfd1990 feat: 添加预览效果页面并优化交互效果
refactor: 优化代码健壮性和类型安全

style: 更新字体样式和全局CSS

fix: 修复IntersectionObserver潜在空引用问题

chore: 更新依赖和ESLint配置

build: 更新构建ID和路由配置
2026-02-24 10:24:05 +08:00

130 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useEffect, useState, useRef } from 'react';
import { InsightCard } from '@/components/ui/insight-card';
import { Button } from '@/components/ui/button';
import { ArrowRight } from 'lucide-react';
interface Insight {
id: string;
title: string;
excerpt: string;
category: string;
readTime: string;
publishedAt: string;
imageUrl?: string;
href: string;
featured?: boolean;
}
const MOCK_INSIGHTS: Insight[] = [
{
id: '1',
title: '2025年技术趋势:AI驱动的数字化转型',
excerpt: '深入探讨人工智能如何重塑企业技术架构,以及如何把握AI时代的机遇',
category: '技术趋势',
readTime: '8 分钟',
publishedAt: '2026-02-10',
imageUrl: '/insights/ai-trend.jpg',
href: '/insights/ai-trend-2025',
featured: true,
},
{
id: '2',
title: '微服务架构最佳实践指南',
excerpt: '从单体应用到微服务的演进之路,包含实战案例和避坑指南',
category: '架构设计',
readTime: '12 分钟',
publishedAt: '2026-02-08',
imageUrl: '/insights/microservices.jpg',
href: '/insights/microservices-best-practices',
},
{
id: '3',
title: '云原生技术栈选型指南',
excerpt: 'Kubernetes、Docker、Service Mesh等技术栈的深度对比与选型建议',
category: '云原生',
readTime: '10 分钟',
publishedAt: '2026-02-05',
imageUrl: '/insights/cloud-native.jpg',
href: '/insights/cloud-native-stack-guide',
},
];
export function InsightsSection() {
const [isVisible, setIsVisible] = useState(false);
const sectionRef = useRef<HTMLElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry?.isIntersecting) {
setIsVisible(true);
}
},
{ threshold: 0.1 }
);
if (sectionRef.current) {
observer.observe(sectionRef.current);
}
return () => observer.disconnect();
}, []);
return (
<section
id="insights"
ref={sectionRef}
className="py-24 bg-[#FAFAFA]"
>
<div className="container-wide">
<div
className={`
text-center mb-16
opacity-0 translate-y-4
${isVisible ? 'animate-fade-in-up' : ''}
`}
>
<h2 className="text-3xl sm:text-4xl font-semibold text-[#171717] mb-4">
</h2>
<p className="text-lg text-[#737373] max-w-2xl mx-auto">
沿
</p>
</div>
<div
className={`
grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12
opacity-0 translate-y-4
${isVisible ? 'animate-fade-in-up stagger-1' : ''}
`}
>
{MOCK_INSIGHTS.map((insight) => (
<InsightCard key={insight.id} {...insight} />
))}
</div>
<div
className={`
text-center
opacity-0 translate-y-4
${isVisible ? 'animate-fade-in-up stagger-2' : ''}
`}
>
<Button
variant="secondary"
size="lg"
className="group"
onClick={() => window.location.href = '/insights'}
>
<ArrowRight className="w-4 h-4 ml-2 group-hover:translate-x-1 transition-transform" />
</Button>
</div>
</div>
</section>
);
}