diff --git a/.gitignore b/.gitignore index 7d4585e..fcd12c1 100755 --- a/.gitignore +++ b/.gitignore @@ -67,5 +67,5 @@ yarn-error.log* # Ignore .idea files in the Expo monorepo **/.idea/ - -uploads \ No newline at end of file +uploads +packages/mind-elixir-core \ No newline at end of file diff --git a/apps/web/src/app/main/layout/MainHeader.tsx b/apps/web/src/app/main/layout/MainHeader.tsx index 47503b5..1461b4e 100755 --- a/apps/web/src/app/main/layout/MainHeader.tsx +++ b/apps/web/src/app/main/layout/MainHeader.tsx @@ -2,7 +2,7 @@ import { useContext, useState } from "react"; import { Input, Layout, Avatar, Button, Dropdown } from "antd"; import { EditFilled, SearchOutlined, UserOutlined } from "@ant-design/icons"; import { useAuth } from "@web/src/providers/auth-provider"; -import { useNavigate, useSearchParams } from "react-router-dom"; +import { useNavigate, useParams, useSearchParams } from "react-router-dom"; import { UserMenu } from "./UserMenu/UserMenu"; import { NavigationMenu } from "./NavigationMenu"; import { useMainContext } from "./MainProvider"; @@ -10,6 +10,7 @@ const { Header } = Layout; export function MainHeader() { const { isAuthenticated, user } = useAuth(); + const { id } = useParams(); const navigate = useNavigate(); const { searchValue, setSearchValue } = useMainContext(); return ( @@ -52,10 +53,15 @@ export function MainHeader() { {isAuthenticated && ( <> )} diff --git a/apps/web/src/components/common/container/CollapsibleContent.tsx b/apps/web/src/components/common/container/CollapsibleContent.tsx index 831bdad..9352183 100644 --- a/apps/web/src/components/common/container/CollapsibleContent.tsx +++ b/apps/web/src/components/common/container/CollapsibleContent.tsx @@ -28,9 +28,15 @@ const CollapsibleContent: React.FC = ({ {/* 包装整个内容区域的容器 */}
{/* 内容区域 */} diff --git a/apps/web/src/components/models/course/detail/CourseDetailContext.tsx b/apps/web/src/components/models/course/detail/CourseDetailContext.tsx index 8702d19..6787e13 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailContext.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailContext.tsx @@ -7,7 +7,7 @@ import { } from "@nice/common"; import { useAuth } from "@web/src/providers/auth-provider"; import React, { createContext, ReactNode, useEffect, useState } from "react"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; interface CourseDetailContextType { editId?: string; // 添加 editId @@ -33,6 +33,7 @@ export function CourseDetailProvider({ const navigate = useNavigate(); const { read } = useVisitor(); const { user } = useAuth(); + const { lectureId } = useParams(); const { data: course, isLoading }: { data: CourseDto; isLoading: boolean } = (api.post as any).findFirst.useQuery( { @@ -47,7 +48,7 @@ export function CourseDetailProvider({ const [selectedLectureId, setSelectedLectureId] = useState< string | undefined - >(undefined); + >(lectureId || undefined); const { data: lecture, isLoading: lectureIsLoading } = ( api.post as any ).findFirst.useQuery( diff --git a/apps/web/src/components/models/course/detail/CourseDetailDescription.tsx b/apps/web/src/components/models/course/detail/CourseDetailDescription.tsx index feba41d..6573753 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailDescription.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailDescription.tsx @@ -61,7 +61,6 @@ export const CourseDetailDescription: React.FC = () => { expandable: true, symbol: "展开", onExpand: () => console.log("展开"), - // collapseText: "收起", }}> {course?.content} diff --git a/apps/web/src/components/models/course/detail/CourseDetailDisplayArea.tsx b/apps/web/src/components/models/course/detail/CourseDetailDisplayArea.tsx index 142abde..447ecda 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailDisplayArea.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailDisplayArea.tsx @@ -51,7 +51,7 @@ export const CourseDetailDisplayArea: React.FC = () => {
diff --git a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx b/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx index 7e708e1..acb8d70 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx @@ -7,7 +7,7 @@ import { UserOutlined, } from "@ant-design/icons"; import { useAuth } from "@web/src/providers/auth-provider"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { UserMenu } from "@web/src/app/main/layout/UserMenu/UserMenu"; import { CourseDetailContext } from "../CourseDetailContext"; @@ -15,7 +15,8 @@ const { Header } = Layout; export function CourseDetailHeader() { const [searchValue, setSearchValue] = useState(""); - const { isAuthenticated, user } = useAuth(); + const { id } = useParams(); + const { isAuthenticated, user, hasSomePermissions } = useAuth(); const navigate = useNavigate(); const { course } = useContext(CourseDetailContext); @@ -51,10 +52,15 @@ export function CourseDetailHeader() { {isAuthenticated && ( <> )} diff --git a/apps/web/src/components/models/course/detail/CourseSyllabus/LectureItem.tsx b/apps/web/src/components/models/course/detail/CourseSyllabus/LectureItem.tsx index ed73745..f4276bf 100755 --- a/apps/web/src/components/models/course/detail/CourseSyllabus/LectureItem.tsx +++ b/apps/web/src/components/models/course/detail/CourseSyllabus/LectureItem.tsx @@ -1,7 +1,7 @@ // components/CourseSyllabus/LectureItem.tsx -import { Lecture, LectureType } from "@nice/common"; -import React from "react"; +import { Lecture, LectureType, LessonTypeLabel } from "@nice/common"; +import React, { useMemo } from "react"; import { ClockCircleOutlined, FileTextOutlined, @@ -19,15 +19,24 @@ export const LectureItem: React.FC = ({ onClick, }) => { const { lectureId } = useParams(); + const isReading = useMemo(() => { + return lecture?.id === lectureId; + }, [lectureId, lecture]); return (
onClick(lecture.id)}> - {lecture.type === LectureType.VIDEO && ( - + {lecture?.meta?.type === LectureType.VIDEO && ( +
+ + {LessonTypeLabel[lecture?.meta?.type]} +
)} - {lecture.type === LectureType.ARTICLE && ( - // 为文章类型添加图标 + {lecture?.meta?.type === LectureType.ARTICLE && ( +
+ {" "} + {LessonTypeLabel[lecture?.meta?.type]} +
)}

{lecture.title}

@@ -37,10 +46,6 @@ export const LectureItem: React.FC = ({

)}
- {/*
- - {lecture.duration}分钟 -
*/}
); }; diff --git a/apps/web/src/components/models/course/detail/CourseSyllabus/SectionItem.tsx b/apps/web/src/components/models/course/detail/CourseSyllabus/SectionItem.tsx index 6cd1627..3c0a4c5 100755 --- a/apps/web/src/components/models/course/detail/CourseSyllabus/SectionItem.tsx +++ b/apps/web/src/components/models/course/detail/CourseSyllabus/SectionItem.tsx @@ -1,10 +1,9 @@ import { ChevronDownIcon } from "@heroicons/react/24/outline"; import { SectionDto } from "@nice/common"; import { AnimatePresence, motion } from "framer-motion"; -import React from "react"; +import React, { useMemo } from "react"; import { LectureItem } from "./LectureItem"; - -// components/CourseSyllabus/SectionItem.tsx +import { useParams } from "react-router-dom"; interface SectionItemProps { section: SectionDto; index?: number; @@ -13,57 +12,68 @@ interface SectionItemProps { onLectureClick: (lectureId: string) => void; ref: React.RefObject; } - export const SectionItem = React.forwardRef( - ({ section, index, isExpanded, onToggle, onLectureClick }, ref) => ( -
- - - {isExpanded && ( - - {section.lectures.map((lecture) => ( - - ))} - - )} - -
- ) + + {isExpanded && ( + + {section.lectures.map((lecture) => ( + + ))} + + )} + + + ); + } ); diff --git a/apps/web/src/components/models/course/editor/form/CourseContentForm/SortableLecture.tsx b/apps/web/src/components/models/course/editor/form/CourseContentForm/SortableLecture.tsx index d421ba2..a3ed362 100755 --- a/apps/web/src/components/models/course/editor/form/CourseContentForm/SortableLecture.tsx +++ b/apps/web/src/components/models/course/editor/form/CourseContentForm/SortableLecture.tsx @@ -237,7 +237,10 @@ export const SortableLecture: React.FC = ({ {isContentVisible && !editing && // Conditionally render content based on type (field?.meta?.type === LectureType.ARTICLE ? ( - + ) : ( ))} diff --git a/apps/web/src/components/models/course/editor/layout/CourseEditorLayout.tsx b/apps/web/src/components/models/course/editor/layout/CourseEditorLayout.tsx index 39ace5d..aaa823d 100755 --- a/apps/web/src/components/models/course/editor/layout/CourseEditorLayout.tsx +++ b/apps/web/src/components/models/course/editor/layout/CourseEditorLayout.tsx @@ -25,7 +25,7 @@ export default function CourseEditorLayout() { const navigate = useNavigate(); const handleNavigation = (item: NavItem, index: number) => { setSelectedSection(index); - navigate(item.path, { replace: true }); + navigate(item.path); }; return ( diff --git a/apps/web/src/components/presentation/collapse-section.tsx b/apps/web/src/components/presentation/collapse-section.tsx index 072e596..d0a9798 100755 --- a/apps/web/src/components/presentation/collapse-section.tsx +++ b/apps/web/src/components/presentation/collapse-section.tsx @@ -14,7 +14,7 @@ interface CollapsibleSectionProps { interface MenuItem { key: string; link?: string; - blank?: boolean + blank?: boolean; icon?: React.ReactNode; label: string; children?: Array; @@ -69,7 +69,10 @@ const CollapsibleSection: React.FC = ({ const isChildCollapsed = !expandedSections[item.key]; return ( -
+
{ @@ -78,7 +81,7 @@ const CollapsibleSection: React.FC = ({ } if (item.link) { if (!item.blank) { - navigate(item.link, { replace: true }); + navigate(item.link); } else { window.open(item.link, "_blank"); } @@ -86,12 +89,20 @@ const CollapsibleSection: React.FC = ({ }} initial={false} animate={{ - backgroundColor: isActive ? token.colorPrimaryBorder : token.colorPrimary, + backgroundColor: isActive + ? token.colorPrimaryBorder + : token.colorPrimary, }} - whileHover={{ backgroundColor: token.colorPrimaryHover }} - transition={{ type: "spring", stiffness: 300, damping: 25, duration: 0.3 }} - style={{ marginLeft: `${level * 16}px` }} - > + whileHover={{ + backgroundColor: token.colorPrimaryHover, + }} + transition={{ + type: "spring", + stiffness: 300, + damping: 25, + duration: 0.3, + }} + style={{ marginLeft: `${level * 16}px` }}>
{item.icon && {item.icon}} @@ -100,8 +111,7 @@ const CollapsibleSection: React.FC = ({ {hasChildren && ( + className={`ml-1 transition-transform duration-300 ${!isChildCollapsed ? "rotate-90" : ""}`}> )}
{item.extra &&
{item.extra}
} @@ -115,11 +125,10 @@ const CollapsibleSection: React.FC = ({ // stiffness: 200, // damping: 20, type: "tween", - duration: 0.2 + duration: 0.2, }} style={{ overflow: "hidden" }} - className="mt-1" - > + className="mt-1"> {renderItems(item.children, level + 1)} )}