This commit is contained in:
ditiqi 2025-02-25 19:30:59 +08:00
parent dc8bc72687
commit 9319f112b4
1 changed files with 168 additions and 190 deletions

View File

@ -1,9 +1,9 @@
import React, { useState, useCallback, useEffect, useMemo } from 'react';
import { Typography, Button, Spin } from 'antd';
import { stringToColor, TaxonomySlug, TermDto } from '@nice/common';
import { api,} from '@nice/client';
import { ControlOutlined } from '@ant-design/icons';
import { useNavigate, useSearchParams } from 'react-router-dom';
import React, { useState, useCallback, useEffect, useMemo } from "react";
import { Typography, Button, Spin } from "antd";
import { stringToColor, TaxonomySlug, TermDto } from "@nice/common";
import { api } from "@nice/client";
import { ControlOutlined } from "@ant-design/icons";
import { useNavigate, useSearchParams } from "react-router-dom";
const { Title, Text } = Typography;
@ -13,72 +13,43 @@ interface CourseCategory {
description: string;
}
// const courseCategories: CourseCategory[] = [
// {
// name: '计算机基础',
// count: 120,
// description: '计算机组成原理、操作系统、网络等基础知识'
// },
// {
// name: '编程语言',
// count: 85,
// description: 'Python、Java、JavaScript等主流编程语言'
// },
// {
// name: '人工智能',
// count: 65,
// description: '机器学习、深度学习、自然语言处理等前沿技术'
// },
// {
// name: '数据科学',
// count: 45,
// description: '数据分析、数据可视化、商业智能等'
// },
// {
// name: '云计算',
// count: 38,
// description: '云服务、容器化、微服务架构等'
// },
// {
// name: '网络安全',
// count: 42,
// description: '网络安全基础、渗透测试、安全防护等'
// }
// ];
const CategorySection = () => {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
const [showAll, setShowAll] = useState(false);
//获得分类
const {data:courseCategoriesData,isLoading} :{data:TermDto[],isLoading:boolean}= api.term.findMany.useQuery({
where:{
const {
data: courseCategoriesData,
isLoading,
}: { data: TermDto[]; isLoading: boolean } = api.term.findMany.useQuery({
where: {
taxonomy: {
slug:TaxonomySlug.CATEGORY
}
slug: TaxonomySlug.CATEGORY,
},
include:{
children :true
},
include: {
children: true,
},
orderBy: {
createdAt: 'desc', // 按创建时间降序排列
createdAt: "desc", // 按创建时间降序排列
},
take:8
})
take: 8,
});
// 分类展示
const [displayedCategories,setDisplayedCategories] = useState<TermDto[]>([])
const [displayedCategories, setDisplayedCategories] = useState<TermDto[]>(
[]
);
useEffect(() => {
console.log(courseCategoriesData);
// 如果 showAll 为 true则显示所有分类数据
// 如果 showAll 为 false则只显示前 8 个分类数据,
if(!isLoading){
if(showAll){
setDisplayedCategories(courseCategoriesData)
}else{
setDisplayedCategories(courseCategoriesData.slice(0,8))
// 如果 showAll 为 false则只显示前 8 个分类数据,
if (!isLoading) {
if (showAll) {
setDisplayedCategories(courseCategoriesData);
} else {
setDisplayedCategories(courseCategoriesData.slice(0, 8));
}
}
}, [courseCategoriesData,showAll]);
}, [courseCategoriesData, showAll]);
// const courseCategories: CourseCategory[] = useMemo(() => {
// return data?.map((term) => ({
// name: term.name,
@ -94,13 +65,15 @@ const CategorySection = () => {
setHoveredIndex(null);
}, []);
const navigate = useNavigate()
const navigate = useNavigate();
return (
<section className="py-32 relative overflow-hidden">
<div className="max-w-screen-2xl mx-auto px-4 relative">
<div className="text-center mb-24">
<Title level={2} className="font-bold text-5xl mb-6 bg-gradient-to-r from-gray-900 via-gray-700 to-gray-800 bg-clip-text text-transparent motion-safe:animate-gradient-x">
<Title
level={2}
className="font-bold text-5xl mb-6 bg-gradient-to-r from-gray-900 via-gray-700 to-gray-800 bg-clip-text text-transparent motion-safe:animate-gradient-x">
</Title>
<Text type="secondary" className="text-xl font-light">
@ -108,9 +81,10 @@ const CategorySection = () => {
</Text>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{
isLoading ? <Spin></Spin> :
(displayedCategories.map((category, index) => {
{isLoading ? (
<Spin></Spin>
) : (
displayedCategories.map((category, index) => {
const categoryColor = stringToColor(category.name);
const isHovered = hoveredIndex === index;
@ -123,32 +97,42 @@ const CategorySection = () => {
role="button"
tabIndex={0}
aria-label={`查看${category.name}课程类别`}
onClick={()=>{
console.log(category.name)
navigate(`/courses?category=${category.name}`)
window.scrollTo({ top: 0, behavior: 'smooth' })
}}
>
onClick={() => {
console.log(category.name);
navigate(
`/courses?category=${category.name}`
);
window.scrollTo({
top: 0,
behavior: "smooth",
});
}}>
<div className="absolute -inset-0.5 bg-gradient-to-r from-gray-200 to-gray-300 opacity-50 rounded-2xl transition-all duration-700 group-hover:opacity-75" />
<div
className={`absolute inset-0 rounded-2xl bg-gradient-to-br from-white to-gray-50 shadow-lg transition-all duration-700 ease-out ${
isHovered ? 'scale-[1.02] bg-opacity-95' : 'scale-100 bg-opacity-90'
isHovered
? "scale-[1.02] bg-opacity-95"
: "scale-100 bg-opacity-90"
}`}
/>
<div
className={`absolute inset-0 rounded-2xl transition-all duration-700 ease-out ${
isHovered ? 'shadow-[0_8px_30px_rgb(0,0,0,0.12)]' : 'shadow-none opacity-0'
isHovered
? "shadow-[0_8px_30px_rgb(0,0,0,0.12)]"
: "shadow-none opacity-0"
}`}
/>
<div
className={`absolute top-0 left-1/2 -translate-x-1/2 h-1 rounded-full transition-all duration-500 ease-out ${
false ? 'w-36 opacity-90' : 'w-24 opacity-60'
}`}
style={{ backgroundColor: categoryColor }}
className={`absolute top-0 left-1/2 -translate-x-1/2 h-1 rounded-full transition-all duration-500 ease-out `}
style={{
backgroundColor: categoryColor,
}}
/>
<div className="relative w-full h-full p-6">
<div className="flex w-2/3 absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 flex-col space-y-4 mb-4">
<Text strong className="text-xl font-medium tracking-wide">
<Text
strong
className="text-xl font-medium tracking-wide">
{category.name}
</Text>
{/* <span
@ -163,30 +147,25 @@ const CategorySection = () => {
{category.children.length}
</span> */}
</div>
<Text type="secondary" className="block text-sm leading-relaxed opacity-90">
<Text
type="secondary"
className="block text-sm leading-relaxed opacity-90">
{category.description}
</Text>
<div
className={` mt-6 absolute bottom-4 right-6 text-sm font-medium flex items-center space-x-2 transition-all duration-500 ease-out ${
false ? 'translate-x-2' : ''
}`}
style={{ color: categoryColor }}
>
className={` mt-6 absolute bottom-4 right-6 text-sm font-medium flex items-center space-x-2 transition-all duration-500 ease-out `}
style={{ color: categoryColor }}>
<span></span>
<span
className={`transform transition-all duration-500 ease-out ${
false ? 'translate-x-2' : ''
}`}
>
className={`transform transition-all duration-500 ease-out `}>
</span>
</div>
</div>
</div>
);
}))
}
})
)}
</div>
{!isLoading && (
<div className="flex justify-center mt-12">
@ -196,11 +175,10 @@ const CategorySection = () => {
className="px-8 h-12 text-base font-medium hover:shadow-md transition-all duration-300"
onClick={() => {
//setShowAll(!showAll)
navigate("/courses")
window.scrollTo({ top: 0, behavior: 'smooth' })
}}
>
{showAll ? '收起' : '查看更多分类'}
navigate("/courses");
window.scrollTo({ top: 0, behavior: "smooth" });
}}>
{showAll ? "收起" : "查看更多分类"}
</Button>
</div>
)}