rht02251256

This commit is contained in:
Rao 2025-02-25 12:56:53 +08:00
parent 4d995a24a9
commit 512b2420e3
6 changed files with 59 additions and 31 deletions

View File

@ -29,7 +29,7 @@ function useGetTaxonomy({type}) : GetTaxonomyProps {
include:{ include:{
children :true children :true
}, },
take:10, // 只取前10个 take:20, // 只取前10个
orderBy: { orderBy: {
createdAt: 'desc', // 按创建时间降序排列 createdAt: 'desc', // 按创建时间降序排列
}, },

View File

@ -7,19 +7,24 @@ import { courseDetailSelect, CourseDto, LectureType, PostType } from "@nice/comm
import { useSearchParams } from "react-router-dom"; import { useSearchParams } from "react-router-dom";
import { set } from "idb-keyval"; import { set } from "idb-keyval";
interface paginationData {
items:CourseDto[],
totalPages:number
}
export default function CoursesPage() { export default function CoursesPage() {
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [selectedCategory, setSelectedCategory] = useState(""); const [selectedCategory, setSelectedCategory] = useState("");
const [selectedLevel, setSelectedLevel] = useState(""); const [selectedLevel, setSelectedLevel] = useState("");
const pageSize = 9; const pageSize = 12;
const [isAll,setIsAll] = useState(true) const [isAll,setIsAll] = useState(true)
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
let coursesData = []
let isCourseLoading = false const [coursesData, setCoursesData] = useState<CourseDto[]>([]);
if(!searchParams.get('searchValue')){ const [isCourseLoading, setIsCourseLoading] = useState(false);
console.log('no category') const [totalPagesNum, setTotalPagesNum] = useState(0);
const {data,isLoading} = api.post.findManyWithPagination.useQuery({
if(!searchParams.get('searchValue') && !searchParams.get('searchValue')){
const {data,isLoading} :{ data:paginationData,isLoading:boolean} = api.post.findManyWithPagination.useQuery({
where: { where: {
type: PostType.COURSE, type: PostType.COURSE,
terms:isAll?{}:{ terms:isAll?{}:{
@ -32,14 +37,21 @@ export default function CoursesPage() {
}, },
}, },
select:courseDetailSelect pageSize,
page:currentPage,
select:courseDetailSelect,
}); });
coursesData = data?.items console.log(data)
isCourseLoading = isLoading useEffect(()=>{
console.log(currentPage);
setIsCourseLoading(isLoading)
setCoursesData(data?.items)
setTotalPagesNum(data?.totalPages)
},[currentPage,data])
}else{ }else{
console.log('searchValue:'+searchParams.get('searchValue')) console.log('searchValue:'+searchParams.get('searchValue'))
const searchValue = searchParams.get('searchValue') const searchValue = searchParams.get('searchValue')
const {data,isLoading} = api.post.findManyWithPagination.useQuery({ const {data,isLoading} :{ data:paginationData,isLoading:boolean}= api.post.findManyWithPagination.useQuery({
where: { where: {
type: PostType.COURSE, type: PostType.COURSE,
OR:[ OR:[
@ -49,10 +61,15 @@ export default function CoursesPage() {
{ terms: { some: { name: { contains: searchValue, mode: 'insensitive' } } } } { terms: { some: { name: { contains: searchValue, mode: 'insensitive' } } } }
] ]
}, },
select:courseDetailSelect select:courseDetailSelect,
pageSize,
page:currentPage,
}) })
coursesData = data?.items useEffect(()=>{
isCourseLoading = isLoading setIsCourseLoading(isLoading)
setCoursesData(data?.items)
setTotalPagesNum(data?.totalPages)
},[currentPage])
} }
useEffect(() => { useEffect(() => {
if(searchParams.get('searchValue')==''){ if(searchParams.get('searchValue')==''){
@ -93,13 +110,19 @@ export default function CoursesPage() {
setSelectedCategory(category); setSelectedCategory(category);
setCurrentPage(1); setCurrentPage(1);
setIsAll(!category) setIsAll(!category)
setSearchParams({ searchValue: ''}); setSearchParams(prev => {
prev.delete('searchValue');
return prev;
});
}} }}
onLevelChange={(level) => { onLevelChange={(level) => {
setSelectedLevel(level); setSelectedLevel(level);
setCurrentPage(1); setCurrentPage(1);
setIsAll(!level) setIsAll(!level)
setSearchParams({ searchValue: ''}); setSearchParams(prev => {
prev.delete('searchValue');
return prev;
});
}} }}
/> />
</div> </div>
@ -110,12 +133,12 @@ export default function CoursesPage() {
<div className="bg-white p-6 rounded-lg shadow-sm"> <div className="bg-white p-6 rounded-lg shadow-sm">
<div className="flex justify-between items-center mb-6"> <div className="flex justify-between items-center mb-6">
<span className="text-gray-600"> <span className="text-gray-600">
{filteredCourses.length} {totalPagesNum * pageSize || 0}
</span> </span>
</div> </div>
<CourseList <CourseList
courses={paginatedCourses} courses={paginatedCourses}
total={filteredCourses.length} total={totalPagesNum * pageSize}
pageSize={pageSize} pageSize={pageSize}
currentPage={currentPage} currentPage={currentPage}
onPageChange={handlePageChange} onPageChange={handlePageChange}

View File

@ -3,7 +3,7 @@ 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 } from 'react-router-dom'; import { useNavigate, useSearchParams } from 'react-router-dom';
const { Title, Text } = Typography; const { Title, Text } = Typography;
@ -124,6 +124,7 @@ const CategorySection = () => {
onClick={()=>{ onClick={()=>{
console.log(category.name) console.log(category.name)
navigate(`/courses?category=${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.5 bg-gradient-to-r from-gray-200 to-gray-300 opacity-50 rounded-2xl transition-all duration-700 group-hover:opacity-75" />

View File

@ -56,7 +56,7 @@ function useFetchCoursesByCategory(category: string) {
terms:true terms:true
} }
}); });
console.log("ss",data)
return { data, isLoading}; return { data, isLoading};
} }

View File

@ -48,12 +48,11 @@ const carouselItems: CarouselItem[] = [
const HeroSection = () => { const HeroSection = () => {
const carouselRef = useRef<CarouselRef>(null); const carouselRef = useRef<CarouselRef>(null);
const { statistics, baseSetting } = useAppConfig(); const { statistics, baseSetting } = useAppConfig();
const platformStats: PlatformStat[] = [ const platformStats: PlatformStat[] = [
{ icon: <TeamOutlined />, value: "50,000+", label: "注册学员" }, { icon: <TeamOutlined />, value: statistics.staffs.toString(), label: "注册学员" },
{ icon: <BookOutlined />, value: "1,000+", label: "精品课程" }, { icon: <StarOutlined />, value: statistics.courses.toString(), label: "精品课程" },
// { icon: <StarOutlined />, value: '98%', label: '好评度' }, { icon: <BookOutlined />, value: statistics.lectures.toString(), label: '课程章节' },
{ icon: <EyeOutlined />, value: "4552", label: "观看次数" }, { icon: <EyeOutlined />, value: statistics.reads.toString(), label: "观看次数" },
]; ];
const handlePrev = useCallback(() => { const handlePrev = useCallback(() => {
carouselRef.current?.prev(); carouselRef.current?.prev();
@ -119,8 +118,8 @@ const HeroSection = () => {
</div> </div>
{/* Stats Container */} {/* Stats Container */}
<div className="absolute -bottom-24 left-1/2 -translate-x-1/2 w-1/2 max-w-6xl px-4"> <div className="absolute -bottom-20 left-1/2 -translate-x-1/2 w-2/3 max-w-6xl px-4">
<div className="rounded-2xl grid grid-cols-2 md:grid-cols-3 gap-4 md:gap-8 p-6 md:p-8 bg-white border shadow-xl hover:shadow-2xl transition-shadow duration-500 will-change-[transform,box-shadow]"> <div className="rounded-2xl grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-8 p-6 md:p-8 bg-white border shadow-xl hover:shadow-2xl transition-shadow duration-500 will-change-[transform,box-shadow]">
{platformStats.map((stat, index) => ( {platformStats.map((stat, index) => (
<div <div
key={index} key={index}

View File

@ -2,7 +2,7 @@ import { useState } from "react";
import { Input, Layout, Avatar, Button, Dropdown } from "antd"; import { Input, Layout, Avatar, Button, Dropdown } from "antd";
import { EditFilled, SearchOutlined, UserOutlined } from "@ant-design/icons"; import { EditFilled, SearchOutlined, UserOutlined } from "@ant-design/icons";
import { useAuth } from "@web/src/providers/auth-provider"; import { useAuth } from "@web/src/providers/auth-provider";
import { useNavigate } from "react-router-dom"; import { useNavigate, useSearchParams } from "react-router-dom";
import { UserMenu } from "./UserMenu/UserMenu"; import { UserMenu } from "./UserMenu/UserMenu";
import { NavigationMenu } from "./NavigationMenu"; import { NavigationMenu } from "./NavigationMenu";
@ -12,6 +12,7 @@ export function MainHeader() {
const [searchValue, setSearchValue] = useState(""); const [searchValue, setSearchValue] = useState("");
const { isAuthenticated, user } = useAuth(); const { isAuthenticated, user } = useAuth();
const navigate = useNavigate(); const navigate = useNavigate();
const [searchParams,setSearchParams] = useSearchParams();
return ( return (
<Header className="select-none flex items-center justify-center bg-white shadow-md border-b border-gray-100 fixed w-full z-30"> <Header className="select-none flex items-center justify-center bg-white shadow-md border-b border-gray-100 fixed w-full z-30">
@ -37,7 +38,11 @@ export function MainHeader() {
onChange={(e) => setSearchValue(e.target.value)} onChange={(e) => setSearchValue(e.target.value)}
onPressEnter={(e) => { onPressEnter={(e) => {
//console.log(e) //console.log(e)
setSearchValue(""); //setSearchValue("");
setSearchParams((prev)=>{
if(searchParams.get("category")) prev.delete("category")
return prev
})
navigate( navigate(
`/courses/?searchValue=${searchValue}` `/courses/?searchValue=${searchValue}`
); );