223 lines
7.4 KiB
TypeScript
223 lines
7.4 KiB
TypeScript
import React, { useRef } from 'react';
|
||
import { Typography, Tag, Carousel } from 'antd';
|
||
import { StarFilled, UserOutlined, ReadOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||
|
||
const { Title, Text } = Typography;
|
||
|
||
interface Teacher {
|
||
name: string;
|
||
title: string;
|
||
avatar: string;
|
||
courses: number;
|
||
students: number;
|
||
rating: number;
|
||
description: string;
|
||
}
|
||
|
||
const featuredTeachers: Teacher[] = [
|
||
{
|
||
name: '张教授',
|
||
title: '资深前端开发专家',
|
||
avatar: '/images/teacher1.jpg',
|
||
courses: 12,
|
||
students: 25000,
|
||
rating: 4.9,
|
||
description: '前 BAT 高级工程师,10年+开发经验'
|
||
},
|
||
{
|
||
name: '李教授',
|
||
title: '算法与数据结构专家',
|
||
avatar: '/images/teacher2.jpg',
|
||
courses: 8,
|
||
students: 18000,
|
||
rating: 4.8,
|
||
description: '计算机博士,专注算法教育8年'
|
||
},
|
||
{
|
||
name: '王博士',
|
||
title: '人工智能研究员',
|
||
avatar: '/images/teacher3.jpg',
|
||
courses: 15,
|
||
students: 30000,
|
||
rating: 4.95,
|
||
description: '人工智能领域专家,曾主导多个大型AI项目'
|
||
},
|
||
{
|
||
name: '陈教授',
|
||
title: '云计算架构师',
|
||
avatar: '/images/teacher4.jpg',
|
||
courses: 10,
|
||
students: 22000,
|
||
rating: 4.85,
|
||
description: '知名云服务提供商技术总监,丰富的实战经验'
|
||
},
|
||
{
|
||
name: '郑老师',
|
||
title: '移动开发专家',
|
||
avatar: '/images/teacher5.jpg',
|
||
courses: 14,
|
||
students: 28000,
|
||
rating: 4.88,
|
||
description: '资深移动端开发者,著名互联网公司技术专家'
|
||
}
|
||
];
|
||
|
||
const generateGradientColors = (name: string) => {
|
||
// 优化的哈希函数
|
||
const hash = name.split('').reduce((acc, char, index) => {
|
||
return char.charCodeAt(0) + ((acc << 5) - acc) + index;
|
||
}, 0);
|
||
|
||
// 定义蓝色色相范围(210-240)
|
||
const blueHueStart = 210;
|
||
const blueHueRange = 30;
|
||
|
||
// 基础蓝色色相 - 将哈希值映射到蓝色范围内
|
||
const baseHue = blueHueStart + Math.abs(hash % blueHueRange);
|
||
|
||
// 生成第二个蓝色色相,保持在蓝色范围内
|
||
let secondHue = baseHue + 15; // 在基础色相的基础上略微偏移
|
||
if (secondHue > blueHueStart + blueHueRange) {
|
||
secondHue -= blueHueRange;
|
||
}
|
||
|
||
// 基于输入字符串的特征调整饱和度和亮度
|
||
const nameLength = name.length;
|
||
const saturation = Math.max(65, Math.min(85, 75 + (nameLength % 10))); // 65-85%范围
|
||
const lightness = Math.max(45, Math.min(65, 55 + (hash % 10))); // 45-65%范围
|
||
|
||
// 为第二个颜色稍微调整饱和度和亮度,创造层次感
|
||
const saturation2 = Math.max(60, saturation - 5);
|
||
const lightness2 = Math.min(70, lightness + 5);
|
||
|
||
return {
|
||
from: `hsl(${Math.round(baseHue)}, ${Math.round(saturation)}%, ${Math.round(lightness)}%)`,
|
||
to: `hsl(${Math.round(secondHue)}, ${Math.round(saturation2)}%, ${Math.round(lightness2)}%)`
|
||
};
|
||
};
|
||
|
||
const FeaturedTeachersSection: React.FC = () => {
|
||
const carouselRef = useRef<any>(null);
|
||
|
||
const settings = {
|
||
dots: true,
|
||
infinite: true,
|
||
speed: 500,
|
||
slidesToShow: 4,
|
||
slidesToScroll: 1,
|
||
autoplay: true,
|
||
autoplaySpeed: 5000,
|
||
responsive: [
|
||
{
|
||
breakpoint: 1024,
|
||
settings: {
|
||
slidesToShow: 2,
|
||
slidesToScroll: 1
|
||
}
|
||
},
|
||
{
|
||
breakpoint: 640,
|
||
settings: {
|
||
slidesToShow: 1,
|
||
slidesToScroll: 1
|
||
}
|
||
}
|
||
]
|
||
};
|
||
|
||
const TeacherCard = ({ teacher }: { teacher: Teacher }) => {
|
||
const gradientColors = generateGradientColors(teacher.name);
|
||
return (
|
||
<div className="p-8">
|
||
<div className="bg-white rounded-2xl shadow-[0_4px_20px_-2px_rgba(0,0,0,0.1)] overflow-hidden transform transition-all duration-300 hover:shadow-[0_8px_30px_-4px_rgba(0,0,0,0.15)] hover:-translate-y-1">
|
||
<div className="relative h-48" style={{
|
||
background: `linear-gradient(to right, ${gradientColors.from}, ${gradientColors.to})`
|
||
}}>
|
||
<img
|
||
src={teacher.avatar}
|
||
alt={teacher.name}
|
||
className="absolute left-1/2 bottom-0 transform -translate-x-1/2 translate-y-1/2 w-24 h-24 rounded-full border-4 border-white object-cover shadow-lg"
|
||
/>
|
||
</div>
|
||
<div className="pt-16 p-6 min-h-[280px] flex flex-col">
|
||
<div className="text-center mb-4">
|
||
<Title level={4} className="mb-1">
|
||
{teacher.name}
|
||
</Title>
|
||
<Tag color="blue" className="text-sm">
|
||
{teacher.title}
|
||
</Tag>
|
||
</div>
|
||
|
||
<Text type="secondary" className="block text-center mb-6 line-clamp-2 min-h-[3rem]">
|
||
{teacher.description}
|
||
</Text>
|
||
|
||
<div className="grid grid-cols-3 gap-4 border-t pt-4">
|
||
<div className="text-center">
|
||
<div className="flex items-center justify-center gap-1 text-blue-600">
|
||
<ReadOutlined className="text-lg" />
|
||
<span className="font-bold">{teacher.courses}</span>
|
||
</div>
|
||
<Text type="secondary" className="text-sm">课程</Text>
|
||
</div>
|
||
<div className="text-center border-x">
|
||
<div className="flex items-center justify-center gap-1 text-blue-600">
|
||
<UserOutlined className="text-lg" />
|
||
<span className="font-bold">{(teacher.students / 1000).toFixed(1)}k</span>
|
||
</div>
|
||
<Text type="secondary" className="text-sm">学员</Text>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className="flex items-center justify-center gap-1 text-blue-600">
|
||
<StarFilled className="text-lg" />
|
||
<span className="font-bold">{teacher.rating}</span>
|
||
</div>
|
||
<Text type="secondary" className="text-sm">评分</Text>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
return (
|
||
<section className="py-20 px-4 bg-gradient-to-b from-gray-50/50 to-transparent">
|
||
<div className="max-w-screen-2xl mx-auto">
|
||
<div className="relative z-10 text-center mb-16">
|
||
<Title level={2} className="font-bold text-4xl mb-4">
|
||
优秀讲师
|
||
</Title>
|
||
<Text type="secondary" className="text-lg">
|
||
业界专家实战分享,传授独家经验
|
||
</Text>
|
||
</div>
|
||
|
||
<div className="relative group">
|
||
<Carousel ref={carouselRef} {...settings}>
|
||
{featuredTeachers.map((teacher, index) => (
|
||
<TeacherCard key={index} teacher={teacher} />
|
||
))}
|
||
</Carousel>
|
||
|
||
<button
|
||
onClick={() => carouselRef.current?.prev()}
|
||
className="absolute left-0 top-1/2 -translate-y-1/2 -ml-4 w-10 h-10 bg-white rounded-full shadow-lg flex items-center justify-center hover:bg-gray-50 transition-colors opacity-0 group-hover:opacity-100"
|
||
>
|
||
<LeftOutlined />
|
||
</button>
|
||
<button
|
||
onClick={() => carouselRef.current?.next()}
|
||
className="absolute right-0 top-1/2 -translate-y-1/2 -mr-4 w-10 h-10 bg-white rounded-full shadow-lg flex items-center justify-center hover:bg-gray-50 transition-colors opacity-0 group-hover:opacity-100"
|
||
>
|
||
<RightOutlined />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
);
|
||
};
|
||
|
||
export default FeaturedTeachersSection;
|