add
This commit is contained in:
parent
dc8bc72687
commit
9319f112b4
|
@ -1,9 +1,9 @@
|
||||||
import React, { useState, useCallback, useEffect, useMemo } from 'react';
|
import React, { useState, useCallback, useEffect, useMemo } from "react";
|
||||||
import { Typography, Button, Spin } from 'antd';
|
import { Typography, Button, Spin } from "antd";
|
||||||
import { stringToColor, TaxonomySlug, TermDto } from '@nice/common';
|
import { stringToColor, TaxonomySlug, TermDto } from "@nice/common";
|
||||||
import { api,} from '@nice/client';
|
import { api } from "@nice/client";
|
||||||
import { ControlOutlined } from '@ant-design/icons';
|
import { ControlOutlined } from "@ant-design/icons";
|
||||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
|
|
||||||
|
@ -13,69 +13,40 @@ interface CourseCategory {
|
||||||
description: string;
|
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 CategorySection = () => {
|
||||||
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
|
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
|
||||||
const [showAll, setShowAll] = useState(false);
|
const [showAll, setShowAll] = useState(false);
|
||||||
//获得分类
|
//获得分类
|
||||||
const {data:courseCategoriesData,isLoading} :{data:TermDto[],isLoading:boolean}= api.term.findMany.useQuery({
|
const {
|
||||||
|
data: courseCategoriesData,
|
||||||
|
isLoading,
|
||||||
|
}: { data: TermDto[]; isLoading: boolean } = api.term.findMany.useQuery({
|
||||||
where: {
|
where: {
|
||||||
taxonomy: {
|
taxonomy: {
|
||||||
slug:TaxonomySlug.CATEGORY
|
slug: TaxonomySlug.CATEGORY,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
children :true
|
children: true,
|
||||||
},
|
},
|
||||||
orderBy: {
|
orderBy: {
|
||||||
createdAt: 'desc', // 按创建时间降序排列
|
createdAt: "desc", // 按创建时间降序排列
|
||||||
},
|
},
|
||||||
take:8
|
take: 8,
|
||||||
})
|
});
|
||||||
// 分类展示
|
// 分类展示
|
||||||
const [displayedCategories,setDisplayedCategories] = useState<TermDto[]>([])
|
const [displayedCategories, setDisplayedCategories] = useState<TermDto[]>(
|
||||||
|
[]
|
||||||
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(courseCategoriesData);
|
console.log(courseCategoriesData);
|
||||||
// 如果 showAll 为 true,则显示所有分类数据,
|
// 如果 showAll 为 true,则显示所有分类数据,
|
||||||
// 如果 showAll 为 false,则只显示前 8 个分类数据,
|
// 如果 showAll 为 false,则只显示前 8 个分类数据,
|
||||||
if (!isLoading) {
|
if (!isLoading) {
|
||||||
if (showAll) {
|
if (showAll) {
|
||||||
setDisplayedCategories(courseCategoriesData)
|
setDisplayedCategories(courseCategoriesData);
|
||||||
} else {
|
} else {
|
||||||
setDisplayedCategories(courseCategoriesData.slice(0,8))
|
setDisplayedCategories(courseCategoriesData.slice(0, 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [courseCategoriesData, showAll]);
|
}, [courseCategoriesData, showAll]);
|
||||||
|
@ -94,13 +65,15 @@ const CategorySection = () => {
|
||||||
setHoveredIndex(null);
|
setHoveredIndex(null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-32 relative overflow-hidden">
|
<section className="py-32 relative overflow-hidden">
|
||||||
<div className="max-w-screen-2xl mx-auto px-4 relative">
|
<div className="max-w-screen-2xl mx-auto px-4 relative">
|
||||||
<div className="text-center mb-24">
|
<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>
|
</Title>
|
||||||
<Text type="secondary" className="text-xl font-light">
|
<Text type="secondary" className="text-xl font-light">
|
||||||
|
@ -108,9 +81,10 @@ const CategorySection = () => {
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
{
|
{isLoading ? (
|
||||||
isLoading ? <Spin></Spin> :
|
<Spin></Spin>
|
||||||
(displayedCategories.map((category, index) => {
|
) : (
|
||||||
|
displayedCategories.map((category, index) => {
|
||||||
const categoryColor = stringToColor(category.name);
|
const categoryColor = stringToColor(category.name);
|
||||||
const isHovered = hoveredIndex === index;
|
const isHovered = hoveredIndex === index;
|
||||||
|
|
||||||
|
@ -124,31 +98,41 @@ const CategorySection = () => {
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
aria-label={`查看${category.name}课程类别`}
|
aria-label={`查看${category.name}课程类别`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log(category.name)
|
console.log(category.name);
|
||||||
navigate(`/courses?category=${category.name}`)
|
navigate(
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
`/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.5 bg-gradient-to-r from-gray-200 to-gray-300 opacity-50 rounded-2xl transition-all duration-700 group-hover:opacity-75" />
|
||||||
<div
|
<div
|
||||||
className={`absolute inset-0 rounded-2xl bg-gradient-to-br from-white to-gray-50 shadow-lg transition-all duration-700 ease-out ${
|
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
|
<div
|
||||||
className={`absolute inset-0 rounded-2xl transition-all duration-700 ease-out ${
|
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
|
<div
|
||||||
className={`absolute top-0 left-1/2 -translate-x-1/2 h-1 rounded-full transition-all duration-500 ease-out ${
|
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,
|
||||||
style={{ backgroundColor: categoryColor }}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="relative w-full h-full p-6">
|
<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">
|
<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}
|
{category.name}
|
||||||
</Text>
|
</Text>
|
||||||
{/* <span
|
{/* <span
|
||||||
|
@ -163,30 +147,25 @@ const CategorySection = () => {
|
||||||
{category.children.length} 门课程
|
{category.children.length} 门课程
|
||||||
</span> */}
|
</span> */}
|
||||||
</div>
|
</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}
|
{category.description}
|
||||||
</Text>
|
</Text>
|
||||||
<div
|
<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 ${
|
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 }}>
|
||||||
}`}
|
|
||||||
style={{ color: categoryColor }}
|
|
||||||
>
|
|
||||||
<span>了解更多</span>
|
<span>了解更多</span>
|
||||||
<span
|
<span
|
||||||
className={`transform transition-all duration-500 ease-out ${
|
className={`transform transition-all duration-500 ease-out `}>
|
||||||
false ? 'translate-x-2' : ''
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
→
|
→
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}))
|
})
|
||||||
}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<div className="flex justify-center mt-12">
|
<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"
|
className="px-8 h-12 text-base font-medium hover:shadow-md transition-all duration-300"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
//setShowAll(!showAll)
|
//setShowAll(!showAll)
|
||||||
navigate("/courses")
|
navigate("/courses");
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
}}
|
}}>
|
||||||
>
|
{showAll ? "收起" : "查看更多分类"}
|
||||||
{showAll ? '收起' : '查看更多分类'}
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Reference in New Issue