feat: 添加预览效果页面并优化交互效果

refactor: 优化代码健壮性和类型安全

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

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

chore: 更新依赖和ESLint配置

build: 更新构建ID和路由配置
This commit is contained in:
张翔
2026-02-24 10:24:05 +08:00
parent 64165c4499
commit fecbfd1990
239 changed files with 3403 additions and 5181 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ export function CasesSection() {
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setIsVisible(true);
}
},
+1 -1
View File
@@ -46,7 +46,7 @@ export function ContactSection() {
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setIsVisible(true);
}
},
+29 -11
View File
@@ -3,9 +3,9 @@
import { useEffect, useRef, useState } from 'react';
import { motion } from 'framer-motion';
import { RippleButton, SealButton } from '@/components/ui/ripple-button';
import { SplitText, GradientText, MagneticButton, BlurReveal, CounterWithEffect } from '@/lib/animations';
import { GradientText, MagneticButton, BlurReveal, CounterWithEffect } from '@/lib/animations';
import { InkBackground } from '@/components/ui/ink-decoration';
import { GradientFlow } from '@/components/effects/gradient-flow';
import { DataParticleFlow } from '@/components/effects/data-particle-flow';
import { SubtleDots } from '@/components/effects/subtle-dots';
import { COMPANY_INFO, STATS } from '@/lib/constants';
import { ArrowRight, Shield, Zap, Award } from 'lucide-react';
@@ -24,7 +24,7 @@ export function HeroSection() {
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setIsVisible(true);
}
},
@@ -40,11 +40,11 @@ export function HeroSection() {
useEffect(() => {
const statsEl = document.getElementById('stats-section');
if (!statsEl) return;
if (!statsEl) {return;}
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setStatsVisible(true);
}
},
@@ -62,6 +62,13 @@ export function HeroSection() {
}
};
const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, id: string) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleScrollTo(id);
}
};
return (
<section
id="home"
@@ -70,9 +77,12 @@ export function HeroSection() {
className="relative min-h-screen flex items-center pt-16 overflow-hidden bg-linear-to-b from-[#FAFAFA] to-white"
>
<InkBackground />
<GradientFlow
colors={['#FAFAFA', '#FFE8EC', '#FFF0F3', '#F5F5F5', '#FFD6DD']}
duration={15}
<DataParticleFlow
particleCount={60}
color="#C41E3A"
intensity="subtle"
shape="square"
effect="pulse"
/>
<SubtleDots color="#C41E3A" count={8} />
@@ -94,9 +104,15 @@ export function HeroSection() {
initial={{ opacity: 0, y: 20 }}
animate={isVisible ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.1 }}
className="text-5xl sm:text-6xl lg:text-7xl font-bold tracking-tight mb-6"
className="text-5xl sm:text-6xl lg:text-7xl tracking-tight mb-6 font-calligraphy"
style={{
fontWeight: 'normal',
WebkitFontSmoothing: 'antialiased',
MozOsxFontSmoothing: 'grayscale',
textRendering: 'optimizeLegibility'
}}
>
<SplitText text={COMPANY_INFO.shortName} className="text-[#1A1A2E]" delay={0.2} />
{COMPANY_INFO.shortName}
</motion.h1>
<BlurReveal delay={0.3}>
@@ -109,7 +125,7 @@ export function HeroSection() {
<BlurReveal delay={0.4}>
<p className="text-lg text-[#718096] mb-10 max-w-2xl mx-auto leading-relaxed">
</p>
</BlurReveal>
@@ -123,6 +139,7 @@ export function HeroSection() {
<SealButton
size="lg"
onClick={() => handleScrollTo('contact')}
onKeyDown={(e) => handleKeyDown(e, 'contact')}
className="min-w-45"
>
@@ -134,6 +151,7 @@ export function HeroSection() {
size="lg"
variant="outline"
onClick={() => handleScrollTo('about')}
onKeyDown={(e) => handleKeyDown(e, 'about')}
className="min-w-45"
>
+1 -1
View File
@@ -58,7 +58,7 @@ export function InsightsSection() {
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setIsVisible(true);
}
},
@@ -50,7 +50,7 @@ export function TestimonialsSection() {
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setIsVisible(true);
}
},