diff --git a/src/App.scss b/src/App.scss index a9c2cc8..210bd65 100644 --- a/src/App.scss +++ b/src/App.scss @@ -1,6 +1,5 @@ #root { width: 100%; - min-height: 900px; margin: 0 auto; text-align: center; background-color: #ffffff; diff --git a/src/api/course.ts b/src/api/course.ts index 603604c..53d62bf 100644 --- a/src/api/course.ts +++ b/src/api/course.ts @@ -5,6 +5,11 @@ export function detail(id: number) { return client.get(`/api/v1/course/${id}`, {}); } +// 线上课课时详情 +export function play(courseId: number, id: number) { + return client.get(`/api/v1/course/${courseId}/hour/${id}`, {}); +} + // 获取播放地址 export function playUrl(courseId: number, hourId: number) { return client.get(`/api/v1/course/${courseId}/hour/${hourId}/play`, {}); diff --git a/src/compenents/header/index.module.scss b/src/compenents/header/index.module.scss index 6d3956d..3fb38e2 100644 --- a/src/compenents/header/index.module.scss +++ b/src/compenents/header/index.module.scss @@ -29,7 +29,7 @@ display: flex; align-items: center; .nav-item { - width: 64px; + width: auto; height: 40px; font-size: 16px; font-weight: 400; @@ -47,7 +47,7 @@ } .nav-active-item { - width: 64px; + width: auto; height: 40px; font-size: 16px; font-weight: 600; diff --git a/src/compenents/header/index.tsx b/src/compenents/header/index.tsx index 9c9bd77..0608a7b 100644 --- a/src/compenents/header/index.tsx +++ b/src/compenents/header/index.tsx @@ -73,8 +73,7 @@ export const Header: React.FC = () => { cancelText: "取消", onOk() { dispatch(logoutAction()); - clearToken(); - navigate("/login"); + window.location.href = "/login"; }, onCancel() { console.log("Cancel"); diff --git a/src/compenents/user-info/index.tsx b/src/compenents/user-info/index.tsx index 22dc743..50fa17b 100644 --- a/src/compenents/user-info/index.tsx +++ b/src/compenents/user-info/index.tsx @@ -6,7 +6,7 @@ import { useDispatch } from "react-redux"; import { loginAction } from "../../store/user/loginUserSlice"; import type { UploadProps } from "antd"; import config from "../../js/config"; -import { getToken } from "../../utils/index"; +import { getToken, changeAppUrl } from "../../utils/index"; interface PropInterface { open: boolean; @@ -40,7 +40,7 @@ export const UserInfoModel: React.FC = ({ open, onCancel }) => { name: "file", multiple: false, method: "PUT", - action: config.app_url + "api/v1/user/avatar", + action: changeAppUrl(config.app_url) + "api/v1/user/avatar", headers: { Accept: "application/json", authorization: "Bearer " + getToken(), diff --git a/src/index.scss b/src/index.scss index c37285b..b2dd0e6 100644 --- a/src/index.scss +++ b/src/index.scss @@ -50,7 +50,7 @@ body { height: auto; margin: 0 auto; display: flex; - flex-direction: column + flex-direction: column; } h1 { @@ -291,7 +291,7 @@ h1 { } #meedu-player-container { - width: 1200px; - height: 675px; - float: left; + width: 100%; + height: auto; + position: relative; } diff --git a/src/pages/course/compenents/hour.tsx b/src/pages/course/compenents/hour.tsx index 23be64b..02a30bf 100644 --- a/src/pages/course/compenents/hour.tsx +++ b/src/pages/course/compenents/hour.tsx @@ -1,8 +1,7 @@ -import React, { useState, useEffect } from "react"; +import React from "react"; import { useNavigate } from "react-router-dom"; import styles from "./hour.module.scss"; import { durationFormat } from "../../../utils/index"; -import { VideoModel } from "./video"; interface PropInterface { id: number; @@ -11,9 +10,6 @@ interface PropInterface { duration: number; record: any; progress: number; - totalHours: any; - records: any; - onChange: () => void; } export const HourCompenent: React.FC = ({ @@ -23,73 +19,14 @@ export const HourCompenent: React.FC = ({ duration, record, progress, - totalHours, - records, - onChange, }) => { - // const navigate = useNavigate(); - const [visible, setVisible] = useState(false); - const [currentId, setCurrentId] = useState(id); - const [currentTitle, setCurrentTitle] = useState(title); - const [isLastpage, setIsLastpage] = useState(false); - const [lastSeeDuration, setLastSeeDuration] = useState(0); - - useEffect(() => { - getData(); - }, [totalHours]); - - const getData = () => { - const index = totalHours.findIndex((i: any) => i.id === id); - if (index === totalHours.length - 1) { - setIsLastpage(true); - } - if (records[totalHours[index].id]) { - setLastSeeDuration(records[totalHours[index].id].finished_duration); - } - }; - - const goNextVideo = () => { - const index = totalHours.findIndex((i: any) => i.id === currentId); - if (index === totalHours.length - 1) { - setIsLastpage(true); - } else if (index < totalHours.length - 1) { - setCurrentId(totalHours[index + 1].id); - setCurrentTitle(totalHours[index + 1].title); - if (index + 1 === totalHours.length - 1) { - setIsLastpage(true); - } - if (records[totalHours[index + 1].id]) { - setLastSeeDuration(records[totalHours[index + 1].id].finished_duration); - } - } - setVisible(true); - }; - + const navigate = useNavigate(); return ( <> - { - setVisible(false); - onChange(); - }} - goNextVideo={() => { - setVisible(false); - goNextVideo(); - }} - >
{ - setCurrentId(id); - setCurrentTitle(title); - setVisible(true); + navigate(`/course/${cid}/hour/${id}`); }} >
diff --git a/src/pages/course/compenents/video.tsx b/src/pages/course/compenents/video.tsx deleted file mode 100644 index fbd0930..0000000 --- a/src/pages/course/compenents/video.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import React, { useState, useRef, useEffect } from "react"; -import styles from "./video.module.scss"; -import { course } from "../../../api/index"; -import { ArrowLeftOutlined } from "@ant-design/icons"; -import { useSelector } from "react-redux"; - -declare const window: any; - -interface PropInterface { - id: number; - cid: number; - title: string; - open: boolean; - isLastpage: boolean; - lastSeeDuration: number; - progress: number; - onCancel: () => void; - goNextVideo: () => void; -} - -export const VideoModel: React.FC = ({ - id, - cid, - title, - open, - isLastpage, - lastSeeDuration, - progress, - onCancel, - goNextVideo, -}) => { - const systemConfig = useSelector((state: any) => state.systemConfig.value); - const user = useSelector((state: any) => state.loginUser.value.user); - const [playUrl, setPlayUrl] = useState(""); - const [playDuration, setPlayDuration] = useState(0); - const [playendedStatus, setPlayendedStatus] = useState(false); - const [lastSeeValue, setLastSeeValue] = useState({}); - const [loading, setLoading] = useState(false); - const myRef = useRef(0); - - useEffect(() => { - let params = null; - if (open) { - if (lastSeeDuration > 0 && progress < 100) { - params = { - time: 5, - pos: lastSeeDuration, - }; - setLastSeeValue(params); - } - setPlayendedStatus(false); - getVideoUrl(params); - } - }, [open, id, cid, lastSeeDuration]); - - useEffect(() => { - myRef.current = playDuration; - }, [playDuration]); - - const getVideoUrl = (params: any) => { - course.playUrl(cid, id).then((res: any) => { - setPlayUrl(res.data.url); - initDPlayer(res.data.url, 0, params); - }); - }; - - const initDPlayer = (playUrl: string, isTrySee: number, params: any) => { - window.player = new window.DPlayer({ - container: document.getElementById("meedu-player-container"), - autoplay: false, - video: { - url: playUrl, - pic: systemConfig.playerPoster, - }, - try: isTrySee === 1, - bulletSecret: { - enabled: systemConfig.playerIsEnabledBulletSecret, - text: systemConfig.playerBulletSecretText - .replace("{name}", user.name) - .replace("{email}", user.email) - .replace("{idCard}", user.id_card), - size: "14px", - color: systemConfig.playerBulletSecretColor || "red", - opacity: Number(systemConfig.playerBulletSecretOpacity), - }, - ban_drag: false, - last_see_pos: params, - }); - // 监听播放进度更新evt - window.player.on("timeupdate", () => { - playTimeUpdate(parseInt(window.player.video.currentTime), false); - }); - window.player.on("ended", () => { - setPlayendedStatus(true); - playTimeUpdate(parseInt(window.player.video.currentTime), true); - window.player && window.player.destroy(); - }); - setLoading(false); - }; - - const playTimeUpdate = (duration: number, isEnd: boolean) => { - if (duration - myRef.current >= 10 || isEnd === true) { - setPlayDuration(duration); - course.record(cid, id, duration).then((res: any) => {}); - course.playPing(cid, id).then((res: any) => {}); - } - }; - - return ( - <> - {open && ( -
-
-
-
{ - window.player && window.player.destroy(); - onCancel(); - }} - > - - 返回 -
-
-
-
-
{title}
-
-
- {playendedStatus && ( -
- {isLastpage && ( -
{ - window.player && window.player.destroy(); - onCancel(); - }} - > - 恭喜你学完最后一节 -
- )} - {!isLastpage && ( -
{ - if (loading) { - return; - } - window.player && window.player.destroy(); - setLoading(true); - setLastSeeValue({}); - setPlayendedStatus(false); - goNextVideo(); - }} - > - 播放下一节 -
- )} -
- )} -
-
-
- )} - - ); -}; diff --git a/src/pages/course/index.tsx b/src/pages/course/index.tsx index 233da2d..220e1dd 100644 --- a/src/pages/course/index.tsx +++ b/src/pages/course/index.tsx @@ -15,7 +15,6 @@ const CoursePage = () => { const [hours, setHours] = useState({}); const [learnRecord, setLearnRecord] = useState({}); const [learnHourRecord, setLearnHourRecord] = useState({}); - const [totalHours, setTotalHours] = useState([]); useEffect(() => { getDetail(); @@ -35,17 +34,6 @@ const CoursePage = () => { if (res.data.learn_hour_records) { setLearnHourRecord(res.data.learn_hour_records); } - if (res.data.chapters.length === 0) { - setTotalHours(res.data.hours[0]); - } else if (res.data.chapters.length > 0) { - const arr: any = []; - for (let key in res.data.hours) { - res.data.hours[key].map((item: any) => { - arr.push(item); - }); - } - setTotalHours(arr); - } setLoading(false); }) .catch((e) => { @@ -159,14 +147,11 @@ const CoursePage = () => { cid={item.course_id} title={item.title} record={learnHourRecord[item.id]} - records={learnHourRecord} duration={item.duration} progress={ (learnHourRecord[item.id].finished_duration * 100) / learnHourRecord[item.id].total_duration } - totalHours={totalHours} - onChange={() => getDetail()} > )} {!learnHourRecord[item.id] && ( @@ -175,11 +160,8 @@ const CoursePage = () => { cid={item.course_id} title={item.title} record={null} - records={learnHourRecord} duration={item.duration} progress={0} - totalHours={totalHours} - onChange={() => getDetail()} > )}
@@ -199,14 +181,11 @@ const CoursePage = () => { cid={item.course_id} title={it.title} record={learnHourRecord[it.id]} - records={learnHourRecord} duration={it.duration} progress={ (learnHourRecord[it.id].finished_duration * 100) / learnHourRecord[it.id].total_duration } - onChange={() => getDetail()} - totalHours={totalHours} > )} {!learnHourRecord[it.id] && ( @@ -215,11 +194,8 @@ const CoursePage = () => { cid={item.course_id} title={it.title} record={null} - records={learnHourRecord} duration={it.duration} progress={0} - totalHours={totalHours} - onChange={() => getDetail()} > )}
diff --git a/src/pages/course/compenents/video.module.scss b/src/pages/course/video.module.scss similarity index 89% rename from src/pages/course/compenents/video.module.scss rename to src/pages/course/video.module.scss index 31d56aa..c3a07e1 100644 --- a/src/pages/course/compenents/video.module.scss +++ b/src/pages/course/video.module.scss @@ -1,15 +1,10 @@ .video-mask { width: 100%; height: 100%; - top: 0; - bottom: 0; - left: 0; - right: 0; - position: fixed; + min-height: 100vh; background-color: #0e0e1e; display: flex; justify-content: center; - z-index: 100; .top-cont { position: fixed; top: 0; @@ -18,9 +13,8 @@ width: 100%; height: 60px; background: rgba(255, 255, 255, 0.1); - .box { - width: 1200px; + width: 62.5%; height: 60px; display: flex; align-items: center; @@ -42,16 +36,15 @@ } } .video-body { - width: 1200px; + width: 62.5%; height: auto; display: flex; flex-direction: column; box-sizing: border-box; padding-top: 30px; margin-top: 60px; - animation: scaleBig 0.3s; .video-title { - width: 1200px; + width: 100%; height: 36px; font-size: 20px; font-weight: 600; @@ -62,11 +55,10 @@ } .video-box { - width: 1200px; - height: 675px; + width: 100%; + padding-bottom: calc(9 / 16 * 100%); margin: 0 auto; border-radius: 8px; - overflow: hidden; position: relative; .alert-message { position: absolute; diff --git a/src/pages/course/video.tsx b/src/pages/course/video.tsx new file mode 100644 index 0000000..05f938e --- /dev/null +++ b/src/pages/course/video.tsx @@ -0,0 +1,211 @@ +import { useEffect, useRef, useState } from "react"; +import styles from "./video.module.scss"; +import { useParams, useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; +import { course as Course } from "../../api/index"; +import { ArrowLeftOutlined } from "@ant-design/icons"; +import { message } from "antd"; + +declare const window: any; + +const CoursePalyPage = () => { + const navigate = useNavigate(); + const params = useParams(); + const systemConfig = useSelector((state: any) => state.systemConfig.value); + const user = useSelector((state: any) => state.loginUser.value.user); + const [playUrl, setPlayUrl] = useState(""); + const [playDuration, setPlayDuration] = useState(0); + const [playendedStatus, setPlayendedStatus] = useState(false); + const [lastSeeValue, setLastSeeValue] = useState({}); + const [course, setCourse] = useState({}); + const [hour, setHour] = useState({}); + const [loading, setLoading] = useState(false); + const [isLastpage, setIsLastpage] = useState(false); + const [totalHours, setTotalHours] = useState([]); + const myRef = useRef(0); + + useEffect(() => { + getCourse(); + getDetail(); + }, [params.courseId, params.hourId]); + + useEffect(() => { + myRef.current = playDuration; + }, [playDuration]); + + const getCourse = () => { + Course.detail(Number(params.courseId)).then((res: any) => { + let totalHours: any = []; + if (res.data.chapters.length === 0) { + setTotalHours(res.data.hours[0]); + totalHours = res.data.hours[0]; + } else if (res.data.chapters.length > 0) { + const arr: any = []; + for (let key in res.data.hours) { + res.data.hours[key].map((item: any) => { + arr.push(item); + }); + } + setTotalHours(arr); + totalHours = arr; + } + const index = totalHours.findIndex( + (i: any) => i.id === Number(params.hourId) + ); + if (index === totalHours.length - 1) { + setIsLastpage(true); + } + }); + }; + + const getDetail = () => { + if (loading) { + return true; + } + setLoading(true); + Course.play(Number(params.courseId), Number(params.hourId)) + .then((res: any) => { + setCourse(res.data.course); + setHour(res.data.hour); + document.title = res.data.hour.title; + let record = res.data.user_hour_record; + let params = null; + if (record && record.finished_duration && record.is_finished === 0) { + params = { + time: 5, + pos: record.finished_duration, + }; + setLastSeeValue(params); + setLastSeeValue(params); + } + getVideoUrl(params); + setLoading(false); + }) + .catch((e) => { + setLoading(false); + }); + }; + + const getVideoUrl = (data: any) => { + Course.playUrl(Number(params.courseId), Number(params.hourId)).then( + (res: any) => { + setPlayUrl(res.data.url); + initDPlayer(res.data.url, 0, data); + } + ); + }; + + const initDPlayer = (playUrl: string, isTrySee: number, params: any) => { + window.player = new window.DPlayer({ + container: document.getElementById("meedu-player-container"), + autoplay: false, + video: { + url: playUrl, + pic: systemConfig.playerPoster, + }, + try: isTrySee === 1, + bulletSecret: { + enabled: systemConfig.playerIsEnabledBulletSecret, + text: systemConfig.playerBulletSecretText + .replace("{name}", user.name) + .replace("{email}", user.email) + .replace("{idCard}", user.id_card), + size: "14px", + color: systemConfig.playerBulletSecretColor || "red", + opacity: Number(systemConfig.playerBulletSecretOpacity), + }, + ban_drag: false, + last_see_pos: params, + }); + // 监听播放进度更新evt + window.player.on("timeupdate", () => { + playTimeUpdate(parseInt(window.player.video.currentTime), false); + }); + window.player.on("ended", () => { + setPlayendedStatus(true); + playTimeUpdate(parseInt(window.player.video.currentTime), true); + window.player && window.player.destroy(); + }); + setLoading(false); + }; + + const playTimeUpdate = (duration: number, isEnd: boolean) => { + if (duration - myRef.current >= 10 || isEnd === true) { + setPlayDuration(duration); + Course.record( + Number(params.courseId), + Number(params.hourId), + duration + ).then((res: any) => {}); + Course.playPing(Number(params.courseId), Number(params.hourId)).then( + (res: any) => {} + ); + } + }; + + const goNextVideo = () => { + const index = totalHours.findIndex( + (i: any) => i.id === Number(params.hourId) + ); + if (index === totalHours.length - 1) { + setIsLastpage(true); + message.error("已经是最后一节了!"); + } else if (index < totalHours.length - 1) { + navigate(`/course/${params.courseId}/hour/${totalHours[index + 1].id}`, { + replace: true, + }); + } + }; + + return ( +
+
+
+
{ + window.player && window.player.destroy(); + navigate(-1); + }} + > + + 返回 +
+
+
+
+
{hour.title}
+
+
+ {playendedStatus && ( +
+ {isLastpage && ( +
navigate(`/course/${params.courseId}`)} + > + 恭喜你学完最后一节 +
+ )} + {!isLastpage && ( +
{ + window.player && window.player.destroy(); + setLastSeeValue({}); + setPlayendedStatus(false); + goNextVideo(); + }} + > + 播放下一节 +
+ )} +
+ )} +
+
+
+ ); +}; + +export default CoursePalyPage; diff --git a/src/pages/index/compenents/courses-model.tsx b/src/pages/index/compenents/courses-model.tsx index 614ebca..cf8ac7e 100644 --- a/src/pages/index/compenents/courses-model.tsx +++ b/src/pages/index/compenents/courses-model.tsx @@ -63,7 +63,7 @@ export const CoursesModel: React.FC = ({ trailColor="#F6F6F6" /> )} - {progress === 100 && ( + {progress >= 100 && (
恭喜你学完此课程! diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index 5fb956b..377e284 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -12,7 +12,6 @@ import iconRoute from "../../assets/images/commen/icon-route.png"; import { studyTimeFormat } from "../../utils/index"; const IndexPage = () => { - document.title = "首页"; const systemConfig = useSelector((state: any) => state.systemConfig.value); const [loading, setLoading] = useState(false); const [tabKey, setTabKey] = useState(0); @@ -36,7 +35,7 @@ const IndexPage = () => { }, [tabKey, currentDepId]); useEffect(() => { - document.title = systemConfig.systemName; + document.title = systemConfig.systemName || "首页"; }, [systemConfig]); const getData = () => { diff --git a/src/pages/init/index.tsx b/src/pages/init/index.tsx index 7347448..fd76a09 100644 --- a/src/pages/init/index.tsx +++ b/src/pages/init/index.tsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from "react"; import { useDispatch } from "react-redux"; import { Outlet } from "react-router-dom"; // import styles from "./index.module.scss"; @@ -7,7 +8,7 @@ import { } from "../../store/system/systemConfigSlice"; import { loginAction } from "../../store/user/loginUserSlice"; import { Header, NoHeader, Footer } from "../../compenents"; -import { useLocation } from "react-router-dom"; +import { useParams, useLocation } from "react-router-dom"; interface Props { loginData?: any; @@ -15,7 +16,12 @@ interface Props { } export const InitPage = (props: Props) => { + const pathname = useLocation().pathname; + const params = useParams(); const dispatch = useDispatch(); + const [showHeader, setShowHeader] = useState(true); + const [showNoHeader, setShowNoHeader] = useState(false); + const [showFooter, setShowFooter] = useState(true); if (props.loginData) { dispatch(loginAction(props.loginData)); } @@ -43,15 +49,32 @@ export const InitPage = (props: Props) => { dispatch(saveConfigAction(config)); } - const pathname = useLocation().pathname; + useEffect(() => { + setShowHeader(true); + setShowNoHeader(false); + setShowFooter(true); + if (pathname === "/login") { + setShowNoHeader(true); + setShowHeader(false); + setShowFooter(false); + } else if (!params.hourId) { + setShowNoHeader(false); + setShowHeader(true); + setShowFooter(true); + } else { + setShowNoHeader(false); + setShowHeader(false); + setShowFooter(false); + } + }, [pathname, params]); return ( <>
- {pathname === "/login" && } - {pathname !== "/login" &&
} + {showNoHeader && } + {showHeader &&
} - {pathname !== "/login" &&
} + {showFooter &&
}
); diff --git a/src/pages/latest-learn/index.tsx b/src/pages/latest-learn/index.tsx index 6df6a91..c9f4010 100644 --- a/src/pages/latest-learn/index.tsx +++ b/src/pages/latest-learn/index.tsx @@ -45,23 +45,24 @@ const LatestLearnPage = () => { )} {!loading && courses.length > 0 && - courses.map((item: any) => ( - <> + courses.map((item: any, index: number) => ( +
{item.course && (
{ navigate(`/course/${item.course.id}`); }} > - +
+ +
{item.course.is_required === 1 && ( @@ -122,7 +123,7 @@ const LatestLearnPage = () => {
)} - +
))}
{systemConfig.pcIndexFooterMsg}
diff --git a/src/pages/login/index.module.scss b/src/pages/login/index.module.scss index 7da7581..48cd192 100644 --- a/src/pages/login/index.module.scss +++ b/src/pages/login/index.module.scss @@ -7,65 +7,71 @@ display: flex; flex-direction: column; justify-content: space-between; - .title { - width: 120px; - height: auto; - font-size: 30px; - font-weight: 600; - color: #333333; - line-height: 30px; - border-bottom: 4px solid #ff4d4f; - box-sizing: border-box; - padding-bottom: 10px; - margin: 0 auto; - margin-top: 100px; - } - .login-box { - width: 1200px; - height: 366px; - background: #ffffff; + .top-content { + width: 100%; display: flex; - margin: 0 auto; - margin-top: 80px; - .left-box { - width: 595px; - height: 100%; + flex-direction: column; + align-items: flex-start; + .title { + min-width: 125px; + height: auto; + font-size: 30px; + font-weight: 600; + color: #333333; + line-height: 30px; + border-bottom: 4px solid #ff4d4f; box-sizing: border-box; - padding: 33px 60px; - .icon { - width: 475px; - height: 300px; - } + padding-bottom: 10px; + margin: 0 auto; + margin-top: 100px; } - .right-box { - width: 520px; - height: 100%; - box-sizing: border-box; - border-left: 1px solid #d8d8d8; - padding: 0px 60px; + .login-box { + width: 1200px; + height: 366px; + background: #ffffff; display: flex; - flex-direction: column; - .captcha-box { - width: 125px; - height: 54px; - margin-left: 15px; - border-radius: 8px; - background-color: rgba(#ff4d4f, 0.1); - display: flex; - - .catpcha-loading-box { - width: 125px; - height: 54px; - line-height: 54px; - text-align: center; + margin: 0 auto; + margin-top: 80px; + .left-box { + width: 595px; + height: 100%; + box-sizing: border-box; + padding: 33px 60px; + .icon { + width: 475px; + height: 300px; } - - .captcha { + } + .right-box { + width: 520px; + height: 100%; + box-sizing: border-box; + border-left: 1px solid #d8d8d8; + padding: 0px 60px; + display: flex; + flex-direction: column; + .captcha-box { width: 125px; height: 54px; - border: none; - cursor: pointer; + margin-left: 15px; border-radius: 8px; + background-color: rgba(#ff4d4f, 0.1); + display: flex; + + .catpcha-loading-box { + width: 125px; + height: 54px; + line-height: 54px; + text-align: center; + } + + .captcha { + width: 125px; + height: 54px; + border: none; + cursor: pointer; + border-radius: 8px; + } } } } diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index b472b6b..5a7d043 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -86,7 +86,7 @@ const LoginPage: React.FC = () => { const data = res.data; dispatch(loginAction(data)); setLoading(false); - navigate("/"); + navigate("/", { replace: true }); }); }; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index a05b7f9..cb37106 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -5,7 +5,8 @@ import { SystemConfigStoreInterface } from "../store/system/systemConfigSlice"; import { getToken } from "../utils"; import { InitPage } from "../pages/init"; -import CoursePage from "../pages/course"; +import CoursePage from "../pages/course/index"; +import CoursePlayPage from "../pages/course/video"; import IndexPage from "../pages/index"; import LatestLearnPage from "../pages/latest-learn"; import LoginPage from "../pages/login"; @@ -57,6 +58,10 @@ const routes: RouteObject[] = [ path: "/course/:courseId", element: , }, + { + path: "/course/:courseId/hour/:hourId", + element: , + }, { path: "/latest-learn", element: , diff --git a/src/store/user/loginUserSlice.ts b/src/store/user/loginUserSlice.ts index 237e761..d75f83e 100644 --- a/src/store/user/loginUserSlice.ts +++ b/src/store/user/loginUserSlice.ts @@ -1,5 +1,11 @@ import { createSlice } from "@reduxjs/toolkit"; -import { getDepKey } from "../../utils/index"; +import { + getDepKey, + clearDepKey, + clearDepName, + setDepName, + clearToken, +} from "../../utils/index"; type UserStoreInterface = { user: null; @@ -27,6 +33,7 @@ const loginUserSlice = createSlice({ stage.value.isLogin = true; if (e.payload.departments.length > 0 && stage.value.currentDepId === 0) { stage.value.currentDepId = e.payload.departments[0].id; + setDepName(e.payload.departments[0].name); } }, logoutAction(stage) { @@ -34,6 +41,9 @@ const loginUserSlice = createSlice({ stage.value.departments = []; stage.value.isLogin = false; stage.value.currentDepId = 0; + clearToken(); + clearDepKey(); + clearDepName(); }, saveCurrentDepId(stage, e) { stage.value.currentDepId = e.payload; diff --git a/src/utils/index.ts b/src/utils/index.ts index 52657e3..7a18b20 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -95,3 +95,12 @@ export function setDepName(token: string) { export function clearDepName() { window.localStorage.removeItem("playedu-frontend-depatmentName"); } + +export function changeAppUrl(str: string) { + let key = str.slice(str.length - 1); + if (key === "/") { + return str; + } else { + return str + "/"; + } +}