Files
novalon-website/src/components/products/product-features-section.tsx
T
张翔 1f591fe2b4 feat: 完成网站功能开发与优化
- 完善产品页面布局与交互
- 优化服务详情页用户体验
- 增强新闻模块内容展示
- 改进团队页面设计
- 优化全局样式和响应式布局
- 添加分页组件支持
- 提升性能与SEO优化
- 修复已知问题与改进代码质量
2026-04-27 20:53:39 +08:00

139 lines
5.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 { useRef, Fragment } from 'react';
import { InkReveal, FadeUp, InkCard, PulseElement } from '@/lib/animations';
import { RippleButton } from '@/components/ui/ripple-button';
import { ScrollReveal, inkRevealVariants, slideInLeftVariants } from '@/components/ui/scroll-animations';
import type { Product } from '@/lib/constants/products';
interface ProductFeaturesSectionProps {
product: Product;
}
function FeatureItem({
feature,
index,
}: {
feature: string;
index: number;
}) {
// 解析功能标题和描述(中文冒号分隔)
const colonIndex = feature.indexOf('');
const title = colonIndex > -1 ? feature.substring(0, colonIndex) : feature;
const description = colonIndex > -1 ? feature.substring(colonIndex + 1) : '';
// 编号格式化
const number = String(index + 1).padStart(2, '0');
return (
<div className="min-h-[50vh] flex items-center py-16">
<div className="container-wide">
<div className="max-w-6xl mx-auto grid md:grid-cols-2 gap-12 items-center">
{/* 左侧:编号和文字 */}
<div className="order-2 md:order-1">
{/* 编号 - InkReveal 模糊揭示 */}
<InkReveal delay={0}>
<span className="block text-7xl md:text-8xl font-mono text-[var(--color-brand-primary)]/10 mb-4">
{number}
</span>
</InkReveal>
{/* 功能标题 - ScrollReveal + slideInLeft */}
<ScrollReveal variants={slideInLeftVariants} delay={0.1}>
<h3 className="text-2xl md:text-3xl font-bold text-[#1C1C1C] mb-4">
{title}
</h3>
</ScrollReveal>
{/* 功能描述 - FadeUp */}
{description && (
<FadeUp delay={0.2}>
<p className="text-lg text-[#5C5C5C] leading-relaxed">
{description}
</p>
</FadeUp>
)}
</div>
{/* 右侧:InkCard 弹簧物理悬浮 + PulseElement 脉冲同心圆 */}
<div className="order-1 md:order-2">
<InkCard
className="aspect-square rounded-2xl bg-white border border-[#E5E5E5] shadow-lg flex items-center justify-center"
hoverScale={1.03}
hoverShadow="0 25px 50px rgba(196, 30, 58, 0.15)"
>
<PulseElement scale={1.08} duration={2.5}>
<div className="w-24 h-24 rounded-full bg-[var(--color-brand-primary)]/10 flex items-center justify-center">
<div className="w-12 h-12 rounded-full bg-[var(--color-brand-primary)]/20" />
</div>
</PulseElement>
</InkCard>
</div>
</div>
</div>
</div>
);
}
export function ProductFeaturesSection({ product }: ProductFeaturesSectionProps) {
const sectionRef = useRef<HTMLElement>(null);
return (
<section id="features" ref={sectionRef} className="relative bg-[#F8F8F8] overflow-hidden">
{/* 标题 - ScrollReveal + inkRevealVariants 模糊揭示 */}
<div className="pt-32 md:pt-40 pb-16">
<div className="container-wide">
<ScrollReveal variants={inkRevealVariants} delay={0}>
<h2 className="text-3xl md:text-4xl font-bold text-[#1C1C1C] text-center mb-4">
</h2>
</ScrollReveal>
<ScrollReveal variants={inkRevealVariants} delay={0.1}>
<p className="text-lg text-[#5C5C5C] text-center max-w-2xl mx-auto">
</p>
</ScrollReveal>
</div>
</div>
{/* 功能列表 */}
{product.features.map((feature, index) => (
<Fragment key={index}>
<FeatureItem feature={feature} index={index} />
{(index === 1 || index === 3) && (
<div className="py-8">
<div className="container-wide">
<div className="max-w-2xl mx-auto bg-white rounded-2xl border border-[#E5E5E5] p-6 md:p-8 text-center shadow-sm">
<p className="text-[#1C1C1C] font-semibold text-lg mb-4">
</p>
<p className="text-[#5C5C5C] mb-6">
30 线
</p>
<div className="flex flex-col sm:flex-row gap-3 justify-center">
<RippleButton
href="/contact"
variant="outline"
rippleColor="rgba(196, 30, 58, 0.2)"
className="border-2 border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)] hover:text-white px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
>
</RippleButton>
<RippleButton
href="/contact"
rippleColor="rgba(196, 30, 58, 0.2)"
className="border border-[#E5E5E5] text-[#5C5C5C] hover:text-[var(--color-brand-primary)] hover:border-[var(--color-brand-primary)]/30 px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
>
</RippleButton>
</div>
</div>
</div>
</div>
)}
</Fragment>
))}
</section>
);
}