diff --git a/apps/web/src/app/main/my-learning/page.tsx b/apps/web/src/app/main/my-learning/page.tsx index 0216515..8807119 100644 --- a/apps/web/src/app/main/my-learning/page.tsx +++ b/apps/web/src/app/main/my-learning/page.tsx @@ -7,11 +7,14 @@ export default function MyLearningPage() { <>
diff --git a/apps/web/src/components/models/course/detail/CourseDetailContext.tsx b/apps/web/src/components/models/course/detail/CourseDetailContext.tsx index b722f3c..0da1702 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailContext.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailContext.tsx @@ -28,6 +28,7 @@ interface CourseDetailContextType { isHeaderVisible: boolean; // 新增 setIsHeaderVisible: (visible: boolean) => void; // 新增 canEdit?: boolean; + userIsLearning?: boolean; } interface CourseFormProviderProps { @@ -43,30 +44,25 @@ export function CourseDetailProvider({ }: CourseFormProviderProps) { const navigate = useNavigate(); const { read } = useVisitor(); - const { user, hasSomePermissions } = useAuth(); + const { user, hasSomePermissions, isAuthenticated } = useAuth(); const { lectureId } = useParams(); const { data: course, isLoading }: { data: CourseDto; isLoading: boolean } = (api.post as any).findFirst.useQuery( { where: { id: editId }, - // include: { - // // sections: { include: { lectures: true } }, - // enrollments: true, - // terms:true - // }, - - select:courseDetailSelect + select: courseDetailSelect, }, { enabled: Boolean(editId) } ); + + const userIsLearning = useMemo(() => { + return (course?.studentIds || []).includes(user?.id); + }, [user, course, isLoading]); const canEdit = useMemo(() => { - const isAuthor = user?.id === course?.authorId; - const isDept = course?.depts - ?.map((dept) => dept.id) - .includes(user?.deptId); + const isAuthor = isAuthenticated && user?.id === course?.authorId; const isRoot = hasSomePermissions(RolePerms?.MANAGE_ANY_POST); - return isAuthor || isDept || isRoot; + return isAuthor || isRoot; }, [user, course]); const [selectedLectureId, setSelectedLectureId] = useState< string | undefined @@ -109,6 +105,7 @@ export function CourseDetailProvider({ isHeaderVisible, setIsHeaderVisible, canEdit, + userIsLearning, }}> {children} 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 401484a..e07ad48 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx @@ -10,17 +10,18 @@ import { useAuth } from "@web/src/providers/auth-provider"; import { useNavigate, useParams } from "react-router-dom"; import { UserMenu } from "@web/src/app/main/layout/UserMenu/UserMenu"; import { CourseDetailContext } from "../CourseDetailContext"; - +import { usePost, useStaff } from "@nice/client"; +import toast from "react-hot-toast"; const { Header } = Layout; export function CourseDetailHeader() { - const [searchValue, setSearchValue] = useState(""); const { id } = useParams(); const { isAuthenticated, user, hasSomePermissions, hasEveryPermissions } = useAuth(); const navigate = useNavigate(); - const { course, canEdit } = useContext(CourseDetailContext); + const { course, canEdit, userIsLearning } = useContext(CourseDetailContext); + const { update } = useStaff(); return (
@@ -39,20 +40,48 @@ export function CourseDetailHeader() { {/* */}
+ {isAuthenticated && ( + + )} {canEdit && ( - <> - - + )} {isAuthenticated ? ( diff --git a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader_BACKUP.tsx b/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader_BACKUP.tsx deleted file mode 100755 index 0fc9815..0000000 --- a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader_BACKUP.tsx +++ /dev/null @@ -1,77 +0,0 @@ -// // components/Header.tsx -// import { motion, useScroll, useTransform } from "framer-motion"; -// import { useContext, useEffect, useState } from "react"; -// import { CourseDetailContext } from "../CourseDetailContext"; -// import { Avatar, Button, Dropdown } from "antd"; -// import { UserOutlined } from "@ant-design/icons"; -// import { UserMenu } from "@web/src/app/main/layout/UserMenu"; -// import { useAuth } from "@web/src/providers/auth-provider"; - -// export const CourseDetailHeader = () => { -// const { scrollY } = useScroll(); -// const { user, isAuthenticated } = useAuth(); -// const [lastScrollY, setLastScrollY] = useState(0); -// const { course, isHeaderVisible, setIsHeaderVisible, lecture } = -// useContext(CourseDetailContext); -// useEffect(() => { -// const updateHeader = () => { -// const current = scrollY.get(); -// const direction = current > lastScrollY ? "down" : "up"; - -// if (direction === "down" && current > 100) { -// setIsHeaderVisible(false); -// } else if (direction === "up") { -// setIsHeaderVisible(true); -// } - -// setLastScrollY(current); -// }; - -// // 使用 requestAnimationFrame 来优化性能 -// const unsubscribe = scrollY.on("change", () => { -// requestAnimationFrame(updateHeader); -// }); - -// return () => { -// unsubscribe(); -// }; -// }, [lastScrollY, scrollY, setIsHeaderVisible]); - -// return ( -// -//
-//
-//

{course?.title}

-//
- -// {isAuthenticated ? ( -// } -// trigger={["click"]} -// placement="bottomRight"> -// -// {(user?.showname || -// user?.username || -// "")[0]?.toUpperCase()} -// -// -// ) : ( -// -// )} -//
-//
-// ); -// }; - -// export default CourseDetailHeader; diff --git a/apps/web/src/components/models/course/editor/context/CourseEditorContext.tsx b/apps/web/src/components/models/course/editor/context/CourseEditorContext.tsx index 0fd8040..88571a3 100755 --- a/apps/web/src/components/models/course/editor/context/CourseEditorContext.tsx +++ b/apps/web/src/components/models/course/editor/context/CourseEditorContext.tsx @@ -99,10 +99,10 @@ export function CourseFormProvider({ }), }, terms: { - connect: termIds.map((id) => ({ id })), // 转换成 connect 格式 + set: termIds.map((id) => ({ id })), // 转换成 connect 格式 }, depts: { - connect: deptIds.map((id) => ({ id })), + set: deptIds.map((id) => ({ id })), }, }; // 删除原始的 taxonomy 字段 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 26282d2..a153137 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 @@ -83,7 +83,7 @@ export const SortableLecture: React.FC = ({ : undefined, }, resources: { - connect: [videoUrlId, ...fileIds] + set: [videoUrlId, ...fileIds] .filter(Boolean) .map((fileId) => ({ fileId, @@ -109,7 +109,7 @@ export const SortableLecture: React.FC = ({ : undefined, }, resources: { - connect: [videoUrlId, ...fileIds] + set: [videoUrlId, ...fileIds] .filter(Boolean) .map((fileId) => ({ fileId,