From e769005b87d27f7eb9a80824a33d0c002c4d3248 Mon Sep 17 00:00:00 2001 From: ditiqi Date: Tue, 25 Feb 2025 20:40:34 +0800 Subject: [PATCH] add --- apps/server/src/models/term/term.router.ts | 2 +- apps/server/src/models/term/term.service.ts | 4 +- .../courses/components/CoursesContainer.tsx | 52 ++++++++++++++++ .../main/courses/components/FilterSection.tsx | 19 +++++- .../main/courses/layout/AllCoursesLayout.tsx | 11 +--- apps/web/src/app/main/courses/page.tsx | 2 +- .../main/home/components/CategorySection.tsx | 21 +------ .../main/home/components/CoursesSection.tsx | 2 +- apps/web/src/app/main/layout/MainProvider.tsx | 9 ++- .../models/course/list}/CourseList.tsx | 6 +- .../models/course/list/course-list.tsx | 61 ------------------- packages/common/src/constants.ts | 8 +-- 12 files changed, 94 insertions(+), 103 deletions(-) create mode 100644 apps/web/src/app/main/courses/components/CoursesContainer.tsx rename apps/web/src/{app/main/courses/components => components/models/course/list}/CourseList.tsx (93%) delete mode 100755 apps/web/src/components/models/course/list/course-list.tsx diff --git a/apps/server/src/models/term/term.router.ts b/apps/server/src/models/term/term.router.ts index 548526c..1b15a3d 100755 --- a/apps/server/src/models/term/term.router.ts +++ b/apps/server/src/models/term/term.router.ts @@ -61,7 +61,7 @@ export class TermRouter { .input(TermMethodSchema.getSimpleTree) .query(async ({ input, ctx }) => { const { staff } = ctx; - return await this.termService.getChildSimpleTree(staff, input); + return await this.termService.getChildSimpleTree(input, staff); }), getParentSimpleTree: this.trpc.procedure .input(TermMethodSchema.getSimpleTree) diff --git a/apps/server/src/models/term/term.service.ts b/apps/server/src/models/term/term.service.ts index 7f21041..676d45e 100755 --- a/apps/server/src/models/term/term.service.ts +++ b/apps/server/src/models/term/term.service.ts @@ -269,10 +269,10 @@ export class TermService extends BaseTreeService { } async getChildSimpleTree( - staff: UserProfile, data: z.infer, + staff?: UserProfile, ) { - const { domainId = null, permissions } = staff; + const domainId = staff?.domainId || null; const hasAnyPerms = staff?.permissions?.includes(RolePerms.MANAGE_ANY_TERM) || staff?.permissions?.includes(RolePerms.READ_ANY_TERM); diff --git a/apps/web/src/app/main/courses/components/CoursesContainer.tsx b/apps/web/src/app/main/courses/components/CoursesContainer.tsx new file mode 100644 index 0000000..9e2d871 --- /dev/null +++ b/apps/web/src/app/main/courses/components/CoursesContainer.tsx @@ -0,0 +1,52 @@ +import CourseList from "@web/src/components/models/course/list/CourseList"; +import { useMainContext } from "../../layout/MainProvider"; +import { PostType, Prisma } from "@nice/common"; +import { useMemo } from "react"; + +export function CoursesContainer() { + const { searchValue, selectedTerms } = useMainContext(); + const termFilters = useMemo(() => { + return Object.entries(selectedTerms) + .filter(([, terms]) => terms.length > 0) + .map(([, terms]) => terms); + }, [selectedTerms]); + const searchCondition: Prisma.StringNullableFilter = { + contains: searchValue, + mode: "insensitive" as Prisma.QueryMode, // 使用类型断言 + }; + return ( + <> + ({ + terms: { + some: { + id: { + in: termFilter, // 确保至少有一个 term.id 在当前 termFilter 中 + }, + }, + }, + })), + OR: [ + { title: searchCondition }, + { subTitle: searchCondition }, + { content: searchCondition }, + { + terms: { + some: { + name: searchCondition, + }, + }, + }, + ], + }, + }} + cols={4}> + + ); +} + +export default CoursesContainer; diff --git a/apps/web/src/app/main/courses/components/FilterSection.tsx b/apps/web/src/app/main/courses/components/FilterSection.tsx index f7a6ced..e6f17eb 100755 --- a/apps/web/src/app/main/courses/components/FilterSection.tsx +++ b/apps/web/src/app/main/courses/components/FilterSection.tsx @@ -2,14 +2,21 @@ import { Checkbox, Divider, Radio, Space, Spin } from "antd"; import { TaxonomySlug, TermDto } from "@nice/common"; -import { useEffect, useMemo } from "react"; +import { useEffect, useMemo, useState } from "react"; import { api } from "@nice/client"; import { useSearchParams } from "react-router-dom"; import TermSelect from "@web/src/components/models/term/term-select"; +import { useMainContext } from "../../layout/MainProvider"; export default function FilterSection() { const { data: taxonomies } = api.taxonomy.getAll.useQuery({}); - + const { setSelectedTerms } = useMainContext(); + const handleTermChange = (slug, selected) => { + setSelectedTerms((prev) => ({ + ...prev, + [slug]: selected, // 更新对应 slug 的选择 + })); + }; return (
{taxonomies?.map((tax, index) => { @@ -18,7 +25,13 @@ export default function FilterSection() {

{tax?.name}

- + + handleTermChange(tax?.slug, selected) + }> {index < taxonomies.length - 1 && ( )} diff --git a/apps/web/src/app/main/courses/layout/AllCoursesLayout.tsx b/apps/web/src/app/main/courses/layout/AllCoursesLayout.tsx index b3089f1..1acc666 100644 --- a/apps/web/src/app/main/courses/layout/AllCoursesLayout.tsx +++ b/apps/web/src/app/main/courses/layout/AllCoursesLayout.tsx @@ -1,9 +1,9 @@ import { useMainContext } from "../../layout/MainProvider"; -import CourseList from "../components/CourseList"; +import CourseList from "../../../../components/models/course/list/CourseList"; import FilterSection from "../components/FilterSection"; +import CoursesContainer from "../components/CoursesContainer"; export function AllCoursesLayout() { - const { searchValue, setSearchValue } = useMainContext(); return ( <>
@@ -12,12 +12,7 @@ export function AllCoursesLayout() {
- +
diff --git a/apps/web/src/app/main/courses/page.tsx b/apps/web/src/app/main/courses/page.tsx index 0b0fb43..b389a4c 100755 --- a/apps/web/src/app/main/courses/page.tsx +++ b/apps/web/src/app/main/courses/page.tsx @@ -1,6 +1,6 @@ import { useState, useMemo, useEffect } from "react"; import FilterSection from "./components/FilterSection"; -import CourseList from "./components/CourseList"; +import CourseList from "../../../components/models/course/list/CourseList"; import { api } from "@nice/client"; import { courseDetailSelect, diff --git a/apps/web/src/app/main/home/components/CategorySection.tsx b/apps/web/src/app/main/home/components/CategorySection.tsx index ddfeab4..0866eb1 100755 --- a/apps/web/src/app/main/home/components/CategorySection.tsx +++ b/apps/web/src/app/main/home/components/CategorySection.tsx @@ -50,13 +50,7 @@ const CategorySection = () => { } } }, [courseCategoriesData, showAll]); - // const courseCategories: CourseCategory[] = useMemo(() => { - // return data?.map((term) => ({ - // name: term.name, - // count: term.hasChildren ? term.children.length : 0, - // description: term.description - // })) || []; - // },[data]) + const handleMouseEnter = useCallback((index: number) => { setHoveredIndex(index); }, []); @@ -102,6 +96,7 @@ const CategorySection = () => { navigate( `/courses?category=${category.name}` ); + window.scrollTo({ top: 0, behavior: "smooth", @@ -135,17 +130,7 @@ const CategorySection = () => { className="text-xl font-medium tracking-wide"> {category.name} - {/* - {category.children.length} 门课程 - */} + >; + setSelectedTerms?: React.Dispatch>; } const MainContext = createContext(null); @@ -12,11 +16,14 @@ interface MainProviderProps { export function MainProvider({ children }: MainProviderProps) { const [searchValue, setSearchValue] = useState(""); + const [selectedTerms, setSelectedTerms] = useState({}); // 初始化状态 return ( {children} diff --git a/apps/web/src/app/main/courses/components/CourseList.tsx b/apps/web/src/components/models/course/list/CourseList.tsx similarity index 93% rename from apps/web/src/app/main/courses/components/CourseList.tsx rename to apps/web/src/components/models/course/list/CourseList.tsx index 97001f0..b637b17 100755 --- a/apps/web/src/app/main/courses/components/CourseList.tsx +++ b/apps/web/src/components/models/course/list/CourseList.tsx @@ -1,5 +1,5 @@ import { Pagination, Empty, Skeleton } from "antd"; -import CourseCard from "./CourseCard"; +import CourseCard from "../../../../app/main/courses/components/CourseCard"; import { courseDetailSelect, CourseDto, Prisma } from "@nice/common"; import { api } from "@nice/client"; import { DefaultArgs } from "@prisma/client/runtime/library"; @@ -49,7 +49,7 @@ export default function CourseList({ useEffect(() => { setCurrentPage(params?.page || 1); - }, [params?.page]); + }, [params?.page, params]); function onPageChange(page: number, pageSize: number) { setCurrentPage(page); window.scrollTo({ top: 0, behavior: "smooth" }); @@ -71,7 +71,7 @@ export default function CourseList({
React.ReactNode; - emptyComponent?: React.ReactNode; - // 新增分页相关属性 - currentPage: number; - totalPages: number; - onPageChange: (page: number) => void; -} - -const container = { - hidden: { opacity: 0 }, - show: { - opacity: 1, - transition: { - staggerChildren: 0.05, - duration: 0.3, - }, - }, -}; -export const CourseList = ({ - courses, - renderItem, - emptyComponent: EmptyComponent, - currentPage, - totalPages, - onPageChange, -}: CourseListProps) => { - if (!courses || courses.length === 0) { - return EmptyComponent || ; - } - - return ( -
- - {courses.map((course) => ( - - {renderItem(course)} - - ))} - - - -
- ); -}; diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts index 9a36b03..34aca4f 100755 --- a/packages/common/src/constants.ts +++ b/packages/common/src/constants.ts @@ -69,10 +69,10 @@ export const InitTaxonomies: { // name: "研判单元", // slug: TaxonomySlug.UNIT, // }, - { - name: "标签", - slug: TaxonomySlug.TAG, - }, + // { + // name: "标签", + // slug: TaxonomySlug.TAG, + // }, ]; export const InitAppConfigs: Prisma.AppConfigCreateInput[] = [ {