add
This commit is contained in:
parent
fb026e1fde
commit
32516187b2
|
@ -1,11 +1,12 @@
|
|||
import { api } from "@nice/client";
|
||||
import { courseDetailSelect, CourseDto } from "@nice/common";
|
||||
import { courseDetailSelect, CourseDto, Lecture } from "@nice/common";
|
||||
import React, { createContext, ReactNode, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
interface CourseDetailContextType {
|
||||
editId?: string; // 添加 editId
|
||||
course?: CourseDto;
|
||||
lecture?: Lecture;
|
||||
selectedLectureId?: string | undefined;
|
||||
setSelectedLectureId?: React.Dispatch<React.SetStateAction<string>>;
|
||||
isLoading?: boolean;
|
||||
|
@ -37,9 +38,16 @@ export function CourseDetailProvider({
|
|||
const [selectedLectureId, setSelectedLectureId] = useState<
|
||||
string | undefined
|
||||
>(undefined);
|
||||
const { data: lecture, isLoading: lectureIsLoading } = (
|
||||
api.post as any
|
||||
).findFirst.useQuery(
|
||||
{
|
||||
where: { id: selectedLectureId },
|
||||
},
|
||||
{ enabled: Boolean(editId) }
|
||||
);
|
||||
useEffect(() => {
|
||||
navigate(``)
|
||||
|
||||
navigate(`/course/${editId}/detail/${selectedLectureId}`);
|
||||
}, [selectedLectureId, editId]);
|
||||
const [isHeaderVisible, setIsHeaderVisible] = useState(true); // 新增
|
||||
return (
|
||||
|
@ -47,6 +55,7 @@ export function CourseDetailProvider({
|
|||
value={{
|
||||
editId,
|
||||
course,
|
||||
lecture,
|
||||
selectedLectureId,
|
||||
setSelectedLectureId,
|
||||
isLoading,
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
// components/CourseDetailDisplayArea.tsx
|
||||
import { motion, useScroll, useTransform } from "framer-motion";
|
||||
import React from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { VideoPlayer } from "@web/src/components/presentation/video-player/VideoPlayer";
|
||||
import { CourseDetailDescription } from "./CourseDetailDescription/CourseDetailDescription";
|
||||
import { Course } from "@nice/common";
|
||||
import { Course, PostType } from "@nice/common";
|
||||
import { CourseDetailContext } from "./CourseDetailContext";
|
||||
|
||||
interface CourseDetailDisplayAreaProps {
|
||||
course: Course;
|
||||
// course: Course;
|
||||
videoSrc?: string;
|
||||
videoPoster?: string;
|
||||
isLoading?: boolean;
|
||||
// isLoading?: boolean;
|
||||
}
|
||||
|
||||
export const CourseDetailDisplayArea: React.FC<
|
||||
CourseDetailDisplayAreaProps
|
||||
> = ({ course, videoSrc, videoPoster, isLoading = false }) => {
|
||||
> = ({ videoSrc, videoPoster }) => {
|
||||
// 创建滚动动画效果
|
||||
const { course, isLoading, lecture } = useContext(CourseDetailContext);
|
||||
const { scrollY } = useScroll();
|
||||
const videoScale = useTransform(scrollY, [0, 200], [1, 0.8]);
|
||||
const videoOpacity = useTransform(scrollY, [0, 200], [1, 0.8]);
|
||||
|
@ -25,16 +27,15 @@ export const CourseDetailDisplayArea: React.FC<
|
|||
{/* 固定的视频区域 */}
|
||||
{/* 移除 sticky 定位,让视频区域随页面滚动 */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
style={{
|
||||
opacity: videoOpacity,
|
||||
}}
|
||||
className="w-full bg-black">
|
||||
<div className=" w-full ">
|
||||
<VideoPlayer src={videoSrc} poster={videoPoster} />
|
||||
</div>
|
||||
{lecture.type === PostType.LECTURE && (
|
||||
<div className=" w-full ">
|
||||
<VideoPlayer src={videoSrc} poster={videoPoster} />
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
{/* 课程内容区域 */}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
import { motion, useScroll, useTransform } from "framer-motion";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { CourseDetailContext } from "../CourseDetailContext";
|
||||
import { Button } from "antd";
|
||||
|
||||
export const CourseDetailHeader = () => {
|
||||
const { scrollY } = useScroll();
|
||||
|
||||
const [lastScrollY, setLastScrollY] = useState(0);
|
||||
const { course, isHeaderVisible, setIsHeaderVisible } =
|
||||
const { course, isHeaderVisible, setIsHeaderVisible, lecture } =
|
||||
useContext(CourseDetailContext);
|
||||
useEffect(() => {
|
||||
const updateHeader = () => {
|
||||
|
@ -43,6 +44,12 @@ export const CourseDetailHeader = () => {
|
|||
<div className="flex items-center space-x-4">
|
||||
<h1 className="text-white text-xl ">{course?.title}</h1>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
console.log(lecture);
|
||||
}}>
|
||||
123
|
||||
</Button>
|
||||
<nav className="flex items-center space-x-4">
|
||||
{/* 添加你的导航项目 */}
|
||||
<button className="px-4 py-2 rounded-full bg-blue-500 text-white hover:bg-blue-600 transition-colors">
|
||||
|
|
|
@ -5,10 +5,16 @@ import { CourseDetailContext } from "./CourseDetailContext";
|
|||
import CourseDetailDisplayArea from "./CourseDetailDisplayArea";
|
||||
import { CourseSyllabus } from "./CourseSyllabus/CourseSyllabus";
|
||||
import CourseDetailHeader from "./CourseDetailHeader/CourseDetailHeader";
|
||||
import { Button } from "antd";
|
||||
|
||||
export default function CourseDetailLayout() {
|
||||
const { course, selectedLectureId, isLoading, setSelectedLectureId } =
|
||||
useContext(CourseDetailContext);
|
||||
const {
|
||||
course,
|
||||
selectedLectureId,
|
||||
lecture,
|
||||
isLoading,
|
||||
setSelectedLectureId,
|
||||
} = useContext(CourseDetailContext);
|
||||
|
||||
const handleLectureClick = (lectureId: string) => {
|
||||
setSelectedLectureId(lectureId);
|
||||
|
@ -16,7 +22,8 @@ export default function CourseDetailLayout() {
|
|||
const [isSyllabusOpen, setIsSyllabusOpen] = useState(false);
|
||||
return (
|
||||
<div className="relative">
|
||||
<CourseDetailHeader />
|
||||
<CourseDetailHeader />
|
||||
|
||||
{/* 添加 Header 组件 */}
|
||||
{/* 主内容区域 */}
|
||||
{/* 为了防止 Header 覆盖内容,添加上边距 */}
|
||||
|
@ -30,8 +37,8 @@ export default function CourseDetailLayout() {
|
|||
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||
className="relative">
|
||||
<CourseDetailDisplayArea
|
||||
course={course}
|
||||
isLoading={isLoading}
|
||||
// course={course}
|
||||
// isLoading={isLoading}
|
||||
videoSrc="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
||||
videoPoster="https://picsum.photos/800/450"
|
||||
/>
|
||||
|
|
|
@ -35,7 +35,6 @@ export function useTusUpload() {
|
|||
if (uploadIndex === -1 || uploadIndex + 4 >= parts.length) {
|
||||
throw new Error("Invalid upload URL format");
|
||||
}
|
||||
console.log(env.UPLOAD_PORT);
|
||||
const resUrl = `http://${env.SERVER_IP}:${env.UPLOAD_PORT}/uploads/${parts.slice(uploadIndex + 1, uploadIndex + 6).join("/")}`;
|
||||
|
||||
return resUrl;
|
||||
|
|
Loading…
Reference in New Issue