Browse Source

Merge branch 'master' of http://git.ius.plus/gavin.chen/fis_h5_school

guanxinyi 1 year ago
parent
commit
23b43d5f4f
3 changed files with 408 additions and 399 deletions
  1. 6 1
      src/App.css
  2. 394 395
      src/app-pages/VideoCoursePlayerPage.jsx
  3. 8 3
      src/index.css

+ 6 - 1
src/App.css

@@ -1,3 +1,8 @@
 @tailwind base;
 @tailwind components;
-@tailwind utilities;
+@tailwind utilities;
+
+/* 移除所有按钮的黄色边框 */
+button:focus {
+  outline: none;
+}

+ 394 - 395
src/app-pages/VideoCoursePlayerPage.jsx

@@ -1,10 +1,10 @@
 import React, { useState, useCallback, useEffect, useRef } from "react";
 import Plyr from "plyr-react";
 import {
-  Worker,
-  Viewer,
-  ScrollMode,
-  LocalizationMap,
+    Worker,
+    Viewer,
+    ScrollMode,
+    LocalizationMap,
 } from "@react-pdf-viewer/core";
 import { defaultLayoutPlugin } from "@react-pdf-viewer/default-layout";
 import { bookmarkPlugin } from "@react-pdf-viewer/bookmark";
@@ -26,436 +26,435 @@ import Icon from "@ant-design/icons";
 import { findAllByDisplayValue } from "@testing-library/react";
 
 const OpenSoundIcon = () => (
-  <img
-    src={process.env.PUBLIC_URL + "/openSound.svg"}
-    className="text-white"
-    alt="开始声音"
-  />
+    <img
+        src={process.env.PUBLIC_URL + "/openSound.svg"}
+        className="text-white"
+        alt="开始声音"
+    />
 );
 const CloseSoundIcon = () => (
-  <img src={process.env.PUBLIC_URL + "/closeSound.svg"} alt="支付宝" />
+    <img src={process.env.PUBLIC_URL + "/closeSound.svg"} alt="支付宝" />
 );
 
 const MyVideoPlayer = ({ url }) => {
-  const divRef = useRef(null);
-  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
-  const [isMuted, setIsMuted] = useState(
-    sessionStorage.getItem("token") === "null" ? true : false
-  );
-  const [isFullScreen, setIsFullScreen] = useState(false);
-  const [player, setPlayer] = useState(null);
-  const [isLiveStreamNotStart, setIsLiveStreamNotStart] = useState(true);
+    const divRef = useRef(null);
+    const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
+    const [isMuted, setIsMuted] = useState(
+        sessionStorage.getItem("token") === "null" ? true : false
+    );
+    const [isFullScreen, setIsFullScreen] = useState(false);
+    const [player, setPlayer] = useState(null);
+    const [isLiveStreamNotStart, setIsLiveStreamNotStart] = useState(true);
 
-  // 动态加载 NodePlayer.min.js 脚本
-  useEffect(() => {
-    const script = document.createElement("script");
-    script.src =
-      process.env.PUBLIC_URL + "/node_player/0.12.6/NodePlayer.min.js";
-    script.async = true;
+    // 动态加载 NodePlayer.min.js 脚本
+    useEffect(() => {
+        const script = document.createElement("script");
+        script.src =
+            process.env.PUBLIC_URL + "/node_player/0.12.6/NodePlayer.min.js";
+        script.async = true;
 
-    try {
-      // 检查 NodePlayer 是否加载成功
-      script.onload = async () => {
-        if (window.NodePlayer !== undefined) {
-          await LivePlayer.init();
-          var newPlayer = new LivePlayer("mian_canvas", url);
-          newPlayer.onError = function (state) {
-            setIsLiveStreamNotStart(true);
-          };
+        try {
+            // 检查 NodePlayer 是否加载成功
+            script.onload = async () => {
+                if (window.NodePlayer !== undefined) {
+                    await LivePlayer.init();
+                    var newPlayer = new LivePlayer("mian_canvas", url);
+                    newPlayer.onError = function (state) {
+                        setIsLiveStreamNotStart(true);
+                    };
 
-          newPlayer.onPlay = function () {
-            setIsLiveStreamNotStart(false);
-          };
-          setPlayer(newPlayer);
-          newPlayer.play(true);
-          function onResize() {
-            if (divRef.current) {
-              const width = divRef.current.clientWidth;
-              const height = divRef.current.clientHeight;
-              console.log("Div width:", width, "Div height:", height);
-              newPlayer.setViewSize(width, height);
-            }
-          }
-          if (divRef.current) {
-            const resizeObserver = new ResizeObserver((entries) => {
-              window.requestAnimationFrame(() => {
-                for (let entry of entries) {
-                  setDimensions({
-                    width: entry.contentRect.width,
-                    height: entry.contentRect.height,
-                  });
+                    newPlayer.onPlay = function () {
+                        setIsLiveStreamNotStart(false);
+                    };
+                    setPlayer(newPlayer);
+                    newPlayer.play(true);
+                    function onResize() {
+                        if (divRef.current) {
+                            const width = divRef.current.clientWidth;
+                            const height = divRef.current.clientHeight;
+                            console.log("Div width:", width, "Div height:", height);
+                            newPlayer.setViewSize(width, height);
+                        }
+                    }
+                    if (divRef.current) {
+                        const resizeObserver = new ResizeObserver((entries) => {
+                            window.requestAnimationFrame(() => {
+                                for (let entry of entries) {
+                                    setDimensions({
+                                        width: entry.contentRect.width,
+                                        height: entry.contentRect.height,
+                                    });
+                                }
+                            });
+                        });
+                        resizeObserver.observe(divRef.current);
+                        // 在组件卸载时取消观察
+                        return () => {
+                            if (resizeObserver && divRef.current) {
+                                resizeObserver.unobserve(divRef.current);
+                            }
+                        };
+                    }
+                    onResize();
+                } else {
+                    console.log("NodePlayer failed to load");
                 }
-              });
-            });
-            resizeObserver.observe(divRef.current);
-            // 在组件卸载时取消观察
-            return () => {
-              if (resizeObserver && divRef.current) {
-                resizeObserver.unobserve(divRef.current);
-              }
             };
-          }
-          onResize();
-        } else {
-          console.log("NodePlayer failed to load");
+
+            document.head.appendChild(script);
+        } catch (err) {
+            console.log("%c Line:90 🥤 err", "color:#33a5ff", err);
         }
-      };
 
-      document.head.appendChild(script);
-    } catch (err) {
-      console.log("%c Line:90 🥤 err", "color:#33a5ff", err);
-    }
+        return () => {
+            document.head.removeChild(script);
+        };
+    }, []);
+    if (player) {
+        player.onTimeout = function () {
+            var newPlayer = new LivePlayer("mian_canvas", url);
 
-    return () => {
-      document.head.removeChild(script);
-    };
-  }, []);
-  if (player) {
-    player.onTimeout = function () {
-      var newPlayer = new LivePlayer("mian_canvas", url);
+            setIsLiveStreamNotStart(true);
+            setPlayer(newPlayer);
+            newPlayer.play(true);
+            newPlayer.onError = function (state) {
+                setIsLiveStreamNotStart(true);
+            };
 
-      setIsLiveStreamNotStart(true);
-      setPlayer(newPlayer);
-      newPlayer.play(true);
-      newPlayer.onError = function (state) {
-        setIsLiveStreamNotStart(true);
-      };
+            newPlayer.onPlay = function () {
+                setIsLiveStreamNotStart(false);
+            };
+        };
+    }
 
-      newPlayer.onPlay = function () {
-        setIsLiveStreamNotStart(false);
-      };
+    useEffect(() => { }, [isLiveStreamNotStart]);
+    const handleToggleMute = () => {
+        setIsMuted(!isMuted);
+        player.audioResume();
+        player.enableAudio(isMuted);
+        // event.stopPropagation()
     };
-  }
 
-  useEffect(() => {}, [isLiveStreamNotStart]);
-  const handleToggleMute = () => {
-    setIsMuted(!isMuted);
-    player.audioResume();
-    player.enableAudio(isMuted);
-    // event.stopPropagation()
-  };
-
-  const handleToggleFullScreen = () => {
-    setIsFullScreen(!isFullScreen);
-    const main = document.getElementById("node_player_video");
-    if (!isFullScreen) {
-      main.requestFullscreen();
-    } else {
-      document.exitFullscreen();
-    }
-  };
+    const handleToggleFullScreen = () => {
+        setIsFullScreen(!isFullScreen);
+        const main = document.getElementById("node_player_video");
+        if (!isFullScreen) {
+            main.requestFullscreen();
+        } else {
+            document.exitFullscreen();
+        }
+    };
 
-  return (
-    <div id="node_player_video">
-      <div id="main">
-        <canvas
-          id="mian_canvas"
-          ref={divRef}
-          style={{ resize: "both", overflow: "auto", backgroundColor: "black" }}
-          className="h-full w-full"
-        ></canvas>
-        {isLiveStreamNotStart && (
-          <div className="absolute inset-0 flex items-center justify-center ">
-            <div className="text-white">直播未开始,请稍等</div>
-          </div>
-        )}
-        {!isLiveStreamNotStart && (
-          <div className="flex justify-end bg-black text-white">
-            <button onClick={handleToggleMute} className="">
-              {!isMuted ? (
-                <img
-                  src={process.env.PUBLIC_URL + "/openSound.svg"}
-                  className="text-white w-10"
-                  alt="开始声音"
-                />
-              ) : (
-                <img
-                  src={process.env.PUBLIC_URL + "/closeSound.svg"}
-                  className="text-white w-10"
-                  alt="关闭声音"
-                />
-              )}
-            </button>
-            <div className="w-5"></div>
-            <button onClick={handleToggleFullScreen}>
-              {isFullScreen ? (
-                <img
-                  src={process.env.PUBLIC_URL + "/cancelFullScreen.svg"}
-                  className="text-white w-10"
-                  alt="取消全屏"
-                />
-              ) : (
-                <img
-                  src={process.env.PUBLIC_URL + "/fullScreen.svg"}
-                  className="text-white w-10"
-                  alt="全屏"
-                />
-              )}
-            </button>
-          </div>
-        )}
-      </div>
-    </div>
-  );
+    return (
+        <div id="node_player_video">
+            <div id="main">
+                <canvas
+                    id="mian_canvas"
+                    ref={divRef}
+                    style={{ resize: "both", overflow: "auto", backgroundColor: "black" }}
+                    className="h-full w-full"
+                ></canvas>
+                {isLiveStreamNotStart && (
+                    <div className="absolute inset-0 flex items-center justify-center ">
+                        <div className="text-white">直播未开始,请稍等</div>
+                    </div>
+                )}
+                {!isLiveStreamNotStart && (
+                    <div className="flex justify-end bg-black text-white">
+                        <button onClick={handleToggleMute} className="border-none p-1">
+                            {!isMuted ? (
+                                <img
+                                    src={process.env.PUBLIC_URL + "/openSound.svg"}
+                                    className="text-white w-10"
+                                    alt="开始声音"
+                                />
+                            ) : (
+                                <img
+                                    src={process.env.PUBLIC_URL + "/closeSound.svg"}
+                                    className="text-white w-10"
+                                    alt="关闭声音"
+                                />
+                            )}
+                        </button>
+                        <div className="w-5"></div>
+                        <button onClick={handleToggleFullScreen} className="border-none p-1">
+                            {isFullScreen ? (
+                                <img
+                                    src={process.env.PUBLIC_URL + "/cancelFullScreen.svg"}
+                                    className="text-white w-10"
+                                    alt="取消全屏"
+                                />
+                            ) : (
+                                <img
+                                    src={process.env.PUBLIC_URL + "/fullScreen.svg"}
+                                    className="text-white w-10"
+                                    alt="全屏"
+                                />
+                            )}
+                        </button>
+                    </div>
+                )}
+            </div>
+        </div>
+    );
 };
 
 const VideoCoursePlayerPage = () => {
-  const { courseCode, currentPlatform, token } = useParams();
-  const [courseData, setcourseData] = useState(null);
-  const [courseFileUrl, setCourseFileUrl] = useState("");
-  const [isShowPdf, setShowPdf] = useState(true);
-  const [courseItems, setCourseItems] = useState([]);
-  if (token) {
-    sessionStorage.setItem("token",JSON.stringify(token));
-  } else {
-    sessionStorage.setItem("token", null);
-  }
+    const { courseCode, currentPlatform, token } = useParams();
+    const [courseData, setcourseData] = useState(null);
+    const [courseFileUrl, setCourseFileUrl] = useState("");
+    const [isShowPdf, setShowPdf] = useState(true);
+    const [courseItems, setCourseItems] = useState([]);
+    if (token) {
+        sessionStorage.setItem("token", JSON.stringify(token));
+    } else {
+        sessionStorage.setItem("token", null);
+    }
 
-  const [plyrProps, setPlyrProps] = useState({
-    source: {
-      type: "video",
-      title: "Example Video",
-      sources: [
-        {
-          src: courseFileUrl,
-          type: "video/mp4",
-          size: 720,
-        },
-      ],
-    }, // https://github.com/sampotts/plyr#the-source-setter
-    options: {
-      playsinline: false,
-    }, // https://github.com/sampotts/plyr#options
-  });
-  //   const [courseCatalogData, setCourseCatalogData] = useState(null);
+    const [plyrProps, setPlyrProps] = useState({
+        source: {
+            type: "video",
+            title: "Example Video",
+            sources: [
+                {
+                    src: courseFileUrl,
+                    type: "video/mp4",
+                    size: 720,
+                },
+            ],
+        }, // https://github.com/sampotts/plyr#the-source-setter
+        options: {
+            playsinline: false,
+        }, // https://github.com/sampotts/plyr#options
+    });
+    //   const [courseCatalogData, setCourseCatalogData] = useState(null);
 
-  const [isShellWeb, setIsShellWeb] = useState(false);
-  const [currentTab, setCurrentTab] = useState("简介");
-  const [isAssistant, setIsAssistant] = useState(false);
-  const [tabsList, setTabsList] = useState(["简介", "资料"]);
-  const [isStartRecord, setIsStartRecord] = useState(true);
-  // 常量
+    const [isShellWeb, setIsShellWeb] = useState(false);
+    const [currentTab, setCurrentTab] = useState("简介");
+    const [isAssistant, setIsAssistant] = useState(false);
+    const [tabsList, setTabsList] = useState(["简介", "资料"]);
+    const [isStartRecord, setIsStartRecord] = useState(true);
+    // 常量
 
-  // 数据获取:课程数据
-  const getCourseDeatil = useCallback(async () => {
-    const data = await coursesAPI.fetchCourseDetail(courseCode, "course");
-    setcourseData(data);
-    if (data.CourseType === 1) {
-      setCourseFileUrl(data.CourseChannel.HttpPullUrl);
-    } else {
-      setCourseFileUrl(data.DefaultVideoToken);
-    }
-    if (data.IsAssistant) {
-      setIsAssistant(true);
-    }
-    setCourseItems(data.CourseMaterials ?? []);
-  }, [courseCode]);
-  const getUserInfo = async () => {
+    // 数据获取:课程数据
+    const getCourseDeatil = useCallback(async () => {
+        const data = await coursesAPI.fetchCourseDetail(courseCode, "course");
+        setcourseData(data);
+        if (data.CourseType === 1) {
+            setCourseFileUrl(data.CourseChannel.HttpPullUrl);
+        } else {
+            setCourseFileUrl(data.DefaultVideoToken);
+        }
+        if (data.IsAssistant) {
+            setIsAssistant(true);
+        }
+        setCourseItems(data.CourseMaterials ?? []);
+    }, [courseCode]);
+    const getUserInfo = async () => {
 
-    if (sessionStorage.getItem("token") !== "null") {
-      console.log("%c Line:162 🥖 token", "color:#7f2b82", token);
-      const { UserCode } = await coursesAPI.getUserInfo();
-      sessionStorage.setItem("userCode", UserCode);
-    }
-  };
-  useEffect(() => {
-    getCourseDeatil();
-    getUserInfo();
-    if (isMobileDevice()) {
-      setTabsList(["简介", "资料", "讨论区"]);
-    }
-  }, [getCourseDeatil, courseCode]);
+        if (sessionStorage.getItem("token") !== "null") {
+            console.log("%c Line:162 🥖 token", "color:#7f2b82", token);
+            const { UserCode } = await coursesAPI.getUserInfo();
+            sessionStorage.setItem("userCode", UserCode);
+        }
+    };
+    useEffect(() => {
+        getCourseDeatil();
+        getUserInfo();
+        if (isMobileDevice()) {
+            setTabsList(["简介", "资料", "讨论区"]);
+        }
+    }, [getCourseDeatil, courseCode]);
 
-  useEffect(() => {
+    useEffect(() => {
         console.log("%c Line:271 🥑 courseFileUrl", "color:#93c0a4", courseFileUrl);
-    setShowPdf(courseFileUrl.endsWith(".pdf"));
-  setPlyrProps({
-      source: {
-        type: "video",
-        title: "Example Video",
-        sources: [
-          {
-            src: courseFileUrl,
-            type: "video/mp4",
-            size: 720,
-          },
-        ],
-      },
-      options: undefined,
-    });
-  
-  }, [courseFileUrl]);
+        setShowPdf(courseFileUrl.endsWith(".pdf"));
+        setPlyrProps({
+            source: {
+                type: "video",
+                title: "Example Video",
+                sources: [
+                    {
+                        src: courseFileUrl,
+                        type: "video/mp4",
+                        size: 720,
+                    },
+                ],
+            },
+            options: undefined,
+        });
 
-  useEffect(() => {
-    if (
-      currentPlatform === "FPlatformEnum.webOnWin" ||
-      currentPlatform === "FPlatformEnum.webOnMac"
-    ) {
-      setIsShellWeb(true);
-    } else {
-      setIsShellWeb(false);
-    }
-  }, [currentPlatform]);
+    }, [courseFileUrl]);
 
-  const defaultLayoutPluginInstance = defaultLayoutPlugin({});
-  const scrollModePluginInstance = scrollModePlugin({
-    scrollMode: ScrollMode.Page,
-  });
+    useEffect(() => {
+        if (
+            currentPlatform === "FPlatformEnum.webOnWin" ||
+            currentPlatform === "FPlatformEnum.webOnMac"
+        ) {
+            setIsShellWeb(true);
+        } else {
+            setIsShellWeb(false);
+        }
+    }, [currentPlatform]);
 
-  const bookmarkPluginInstance = bookmarkPlugin();
-  const DisplayRemotePDF = () => {
-    return (
-      <Worker workerUrl={process.env.PUBLIC_URL + "/pdf.worker.min.js"} async>
-        <Viewer
-          fileUrl={courseFileUrl}
-          theme="dark"
-          localization={zh_CN}
-          plugins={[
-            defaultLayoutPluginInstance,
-            scrollModePluginInstance,
-            bookmarkPluginInstance,
-          ]}
-          style={{ width: "100%" }}
-        />
-      </Worker>
-    );
-  };
-  // 交互事件
-  // 切换 Tab
-  const handleTabChange = (index) => {
-    console.log("Tab 切换至", tabsList[index]);
-    setCurrentTab(tabsList[index]);
-  };
-  const handleChildData = (data) => {
-    setCourseFileUrl(data);
-  };
+    const defaultLayoutPluginInstance = defaultLayoutPlugin({});
+    const scrollModePluginInstance = scrollModePlugin({
+        scrollMode: ScrollMode.Page,
+    });
 
-  // 【课程列表】与【简介】Tab
-  const buildTopTabs = () => {
-    return (
-      <NomalTabs
-        className="w-100"
-        tabs={tabsList}
-        initTab={currentTab}
-        onChangeTab={handleTabChange}
-      ></NomalTabs>
-    );
-  };
-  const isMobileDevice = () => {
-    return (
-      typeof window.orientation !== "undefined" ||
-      navigator.userAgent.indexOf("IEMobile") !== -1
-    );
-  };
-  const startRecord = () => {
-    setIsStartRecord(false);
-    coursesAPI.sendCourseEntryNotice(`target=record?code=${courseData.Code}`);
-  };
-  const endRecord = () => {
-    setIsStartRecord(true);
-    coursesAPI.sendCourseEntryNotice(
-      `target=endRecord?code=${courseData.Code}`
-    );
-  };
+    const bookmarkPluginInstance = bookmarkPlugin();
+    const DisplayRemotePDF = () => {
+        return (
+            <Worker workerUrl={process.env.PUBLIC_URL + "/pdf.worker.min.js"} async>
+                <Viewer
+                    fileUrl={courseFileUrl}
+                    theme="dark"
+                    localization={zh_CN}
+                    plugins={[
+                        defaultLayoutPluginInstance,
+                        scrollModePluginInstance,
+                        bookmarkPluginInstance,
+                    ]}
+                    style={{ width: "100%" }}
+                />
+            </Worker>
+        );
+    };
+    // 交互事件
+    // 切换 Tab
+    const handleTabChange = (index) => {
+        console.log("Tab 切换至", tabsList[index]);
+        setCurrentTab(tabsList[index]);
+    };
+    const handleChildData = (data) => {
+        setCourseFileUrl(data);
+    };
 
-  // 内容主题区域,显示【课程列表】或【简介】
-  const buildContentArea = () => {
-    console.log("当前 Tab", currentTab);
-    if (currentTab === "简介") {
-      return (
-        <div className="flex-grow flex flex-col  bg-gray-50 rounded p-5">
-          <div className="text-xl mb-2">课程简介</div>
-          <div className="text-sm text-gray-600">
-            {courseData == null || courseData.CourseIntro == null
-              ? "暂无简介"
-              : courseData.CourseIntro}
-          </div>
-        </div>
-      );
-    } else if (currentTab === "讨论区") {
-      return (
-        <div className=" h-full">
-          <InteractiveArea h5courseCode={courseCode} />
-        </div>
-      );
-    }
-    return (
-      <div className="flex flex-col  bg-gray-50 rounded">
-        <CourseInformation
-          courseItems={courseItems}
-          onChildData={handleChildData}
-          currentPlatform={currentPlatform}
-        />
-      </div>
-    );
-  };
+    // 【课程列表】与【简介】Tab
+    const buildTopTabs = () => {
+        return (
+            <NomalTabs
+                className="w-100"
+                tabs={tabsList}
+                initTab={currentTab}
+                onChangeTab={handleTabChange}
+            ></NomalTabs>
+        );
+    };
+    const isMobileDevice = () => {
+        return (
+            typeof window.orientation !== "undefined" ||
+            navigator.userAgent.indexOf("IEMobile") !== -1
+        );
+    };
+    const startRecord = () => {
+        setIsStartRecord(false);
+        coursesAPI.sendCourseEntryNotice(`target=record?code=${courseData.Code}`);
+    };
+    const endRecord = () => {
+        setIsStartRecord(true);
+        coursesAPI.sendCourseEntryNotice(
+            `target=endRecord?code=${courseData.Code}`
+        );
+    };
 
-  return (
-    <main className="flex min-h-screen flex-col p-5 h-[100vh]">
-      <div className="flex-grow flex ">
-        {/* 视频播放器与PDF显示器 */}
-        <div className={`h-full ${isMobileDevice() ? "w-full" : "w-3/4"}`}>
-          {(courseData === null || courseData.CourseType !== 1) && (
-            <div>
-              {isShowPdf && (
-                <div className={`h-[70vh]`}>{DisplayRemotePDF()}</div>
-              )}
-              {!isShowPdf && (
-                <div>
-                  {" "}
-                  <Plyr {...plyrProps} />{" "}
+    // 内容主题区域,显示【课程列表】或【简介】
+    const buildContentArea = () => {
+        console.log("当前 Tab", currentTab);
+        if (currentTab === "简介") {
+            return (
+                <div className="flex-grow flex flex-col  bg-gray-50 rounded p-5">
+                    <div className="text-xl mb-2">课程简介</div>
+                    <div className="text-sm text-gray-600">
+                        {courseData == null || courseData.CourseIntro == null
+                            ? "暂无简介"
+                            : courseData.CourseIntro}
+                    </div>
                 </div>
-              )}
+            );
+        } else if (currentTab === "讨论区") {
+            return (
+                <div className=" h-full">
+                    <InteractiveArea h5courseCode={courseCode} />
+                </div>
+            );
+        }
+        return (
+            <div className="flex flex-col  bg-gray-50 rounded">
+                <CourseInformation
+                    courseItems={courseItems}
+                    onChildData={handleChildData}
+                    currentPlatform={currentPlatform}
+                />
             </div>
-          )}
+        );
+    };
 
-          {courseData != null && courseData.CourseType === 1 && (
-            <div className="relative">
-              <MyVideoPlayer url={courseFileUrl} />
-              {/* 录制按钮 */}
-              {/* isAssistant 后面加上 */}
-              {isShellWeb && (
-                <div className="absolute top-0 right-0 mt-2 mr-2 flex">
-                  {isStartRecord && (
-                    <button
-                      className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full"
-                      onClick={() => startRecord()}
-                    >
-                      开始录制
-                    </button>
-                  )}
-                  {!isStartRecord && (
-                    <button
-                      className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 ml-2 rounded-full"
-                      onClick={() => endRecord()}
+    return (
+        <main className="flex min-h-screen flex-col p-5 h-[100vh]">
+            <div className="flex-grow flex ">
+                {/* 视频播放器与PDF显示器 */}
+                <div className={`h-full ${isMobileDevice() ? "w-full" : "w-3/4"}`}>
+                    {(courseData === null || courseData.CourseType !== 1) && (
+                        <div>
+                            {isShowPdf && (
+                                <div className={`h-[70vh]`}>{DisplayRemotePDF()}</div>
+                            )}
+                            {!isShowPdf && (
+                                <div>
+                                    {" "}
+                                    <Plyr {...plyrProps} />{" "}
+                                </div>
+                            )}
+                        </div>
+                    )}
+
+                    {courseData != null && courseData.CourseType === 1 && (
+                        <div className="relative">
+                            <MyVideoPlayer url={courseFileUrl} />
+                            {/* 录制按钮 */}
+                            {/* isAssistant 后面加上 */}
+                            {isShellWeb && (
+                                <div className="absolute top-0 right-0 mt-2 mr-2 flex">
+                                    {isStartRecord && (
+                                        <button
+                                            className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full"
+                                            onClick={() => startRecord()}
+                                        >
+                                            开始录制
+                                        </button>
+                                    )}
+                                    {!isStartRecord && (
+                                        <button
+                                            className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 ml-2 rounded-full"
+                                            onClick={() => endRecord()}
+                                        >
+                                            结束录制
+                                        </button>
+                                    )}
+                                </div>
+                            )}
+                        </div>
+                    )}
+                    {/* 课程简介 */}
+                    <div
+                        className={`mt-2 flex flex-col flex-grow ${isMobileDevice() ? "w-[90vw]" : ""
+                            }`}
                     >
-                      结束录制
-                    </button>
-                  )}
+                        {buildTopTabs()}
+                        {buildContentArea()}
+                    </div>
                 </div>
-              )}
-            </div>
-          )}
-          {/* 课程简介 */}
-          <div
-            className={`mt-2 flex flex-col flex-grow ${
-              isMobileDevice() ? "w-[90vw]" : ""
-            }`}
-          >
-            {buildTopTabs()}
-            {buildContentArea()}
-          </div>
-        </div>
 
-        {/* 互动交流区 */}
-        {!isMobileDevice() && (
-          <div className="w-1/4 h-full">
-            <InteractiveArea courseCode={courseCode} />
-          </div>
-        )}
-      </div>
-    </main>
-  );
+                {/* 互动交流区 */}
+                {!isMobileDevice() && (
+                    <div className="w-1/4 h-full">
+                        <InteractiveArea courseCode={courseCode} />
+                    </div>
+                )}
+            </div>
+        </main>
+    );
 };
 
 export default VideoCoursePlayerPage;

+ 8 - 3
src/index.css

@@ -1,13 +1,18 @@
 body {
   margin: 0;
-  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
-    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
     sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
 }
 
 code {
-  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
     monospace;
 }
+
+/* 移除所有按钮的黄色边框 */
+button:focus {
+  outline: none;
+}