feat: sub页 bg

This commit is contained in:
mozzie 2023-03-24 10:51:37 +08:00
parent a153137604
commit a3c17101d6
9 changed files with 99 additions and 65 deletions

View File

@ -70,9 +70,9 @@ export class CourseController {
const user = await this.userService.select({ user_login }); const user = await this.userService.select({ user_login });
// 用户订阅鉴权 // 用户订阅鉴权
if (!user.user_sub) if (!user.user_sub)
return { code: BizCode.FORBID, msg: '无权访问订阅课程' }; return { code: BizCode.AUTH, msg: '无权访问订阅课程' };
if (+user.user_sub_expired < Date.now()) if (+user.user_sub_expired < Date.now())
return { code: BizCode.FORBID, msg: '订阅已过期' }; return { code: BizCode.AUTH, msg: '订阅已过期' };
const course = await this.courseService.select({ course_id }); const course = await this.courseService.select({ course_id });
const chapterList = await this.chapterService.select(course_id); const chapterList = await this.chapterService.select(course_id);
const guide = await this.guideService.select(course_id); const guide = await this.guideService.select(course_id);

View File

@ -127,7 +127,8 @@ export class UserController {
// 防止接口调用 end // 防止接口调用 end
const code = Math.floor(Math.random() * 9000 + 1000); const code = Math.floor(Math.random() * 9000 + 1000);
await this.redisService.set('' + phoneNumbers, code, 'EX', 60); await this.redisService.set('' + phoneNumbers, code, 'EX', 60);
await this.smsService.send({ code, phoneNumbers }); if (process.env.EGG_SERVER_ENV === 'prod')
await this.smsService.send({ code, phoneNumbers });
return { code: BizCode.OK }; return { code: BizCode.OK };
} catch (error) { } catch (error) {
this.ctx.logger.error(error); this.ctx.logger.error(error);

View File

@ -8,7 +8,6 @@ import CaretDown20Filled from "@ricons/fluent/CaretDown20Filled";
import Alert20Regular from "@ricons/fluent/Alert20Regular"; import Alert20Regular from "@ricons/fluent/Alert20Regular";
import DoorArrowRight20Regular from "@ricons/fluent/DoorArrowRight20Regular"; import DoorArrowRight20Regular from "@ricons/fluent/DoorArrowRight20Regular";
import Settings20Regular from "@ricons/fluent/Settings20Regular"; import Settings20Regular from "@ricons/fluent/Settings20Regular";
import PremiumPerson20Regular from "@ricons/fluent/PremiumPerson20Regular";
import { useState } from "react"; import { useState } from "react";
import { useMount } from "../../hook"; import { useMount } from "../../hook";
@ -103,15 +102,6 @@ function Nav() {
</div> </div>
</div> </div>
<div className="main"> <div className="main">
{/* <div
className="bs fc sb"
onClick={() => onClickProfileItem("sub")}
>
<span></span>
<Icon color="var(--color-text-3)">
<PremiumPerson20Regular />
</Icon>
</div> */}
<div className="bs fc sb"> <div className="bs fc sb">
<span <span
style={{ style={{

View File

@ -51,9 +51,7 @@ export default function Result(props: IProps) {
}; };
useEffect(() => { useEffect(() => {
if (props.code) { if (props.code) setView(table[props.code]);
setView(table[props.code]);
}
}, [props.code]); }, [props.code]);
return <>{view}</>; return <>{view}</>;

View File

@ -1,8 +1,7 @@
import { lazy } from "react"; import { lazy } from "react";
import Course from "../view/Course"; import Course from "../view/Course";
import CourseDetail from "../view/CourseDetail";
import Login from "../view/Login"; import Login from "../view/Login";
import Subscribe from "../view/Subscribe"; import ResultPage from "../view/ResultPage";
export interface IRouteMenuItem { export interface IRouteMenuItem {
path: string; path: string;
@ -26,6 +25,12 @@ export const commonRouters: IRoute[] = [
element: <Course />, element: <Course />,
name: "学习", name: "学习",
}, },
{
path: "/result",
element: <ResultPage />,
name: "Ooops!",
invisible: true,
},
]; ];
export const lazyRouters: IRoute[] = [ export const lazyRouters: IRoute[] = [

View File

@ -3,7 +3,7 @@ import "./index.less";
import Guide from "./components/Guide"; import Guide from "./components/Guide";
import { useMount } from "../../hook"; import { useMount } from "../../hook";
import Player from "./components/DPlayer"; import Player from "./components/DPlayer";
import { useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { getCourseDetailById } from "../../api"; import { getCourseDetailById } from "../../api";
import { ms2Time } from "./util"; import { ms2Time } from "./util";
import Result from "../../components/Result"; import Result from "../../components/Result";
@ -34,6 +34,7 @@ const defaultState = {
function CourseDetail() { function CourseDetail() {
const { id: course_id = "" } = useParams(); const { id: course_id = "" } = useParams();
const [state, setState] = useState<IState>(defaultState); const [state, setState] = useState<IState>(defaultState);
const navigate = useNavigate();
const chapters2toc = (chapterList: IChapter[]) => { const chapters2toc = (chapterList: IChapter[]) => {
return chapterList.map((item) => { return chapterList.map((item) => {
@ -93,7 +94,9 @@ function CourseDetail() {
], ],
view: <Guide mdText={data?.guide.guide_value} />, view: <Guide mdText={data?.guide.guide_value} />,
}); });
break;
default: default:
navigate("/result");
break; break;
} }
}); });
@ -109,51 +112,43 @@ function CourseDetail() {
return ( return (
<div className="course-detail"> <div className="course-detail">
{state.toc.length > 0 ? ( <aside className="table-of-content">
<> <h3>{state.course.course_title}</h3>
<aside className="table-of-content"> <div style={{ color: "var(--color-text-3)", fontSize: 13 }}>
<h3>{state.course.course_title}</h3> <span>{state.course.course_createtime}</span>
<div style={{ color: "var(--color-text-3)", fontSize: 13 }}> </div>
<span>{state.course.course_createtime}</span> <div className="toc">
</div> {state.toc.map((i: any) => {
<div className="toc"> if (i.level === 1) {
{state.toc.map((i: any) => { return (
if (i.level === 1) { <div className="level-1" key={i.title}>
return ( {i.title}
<div className="level-1" key={i.title}> </div>
{i.title} );
</div> } else if (i.level === 2) {
); return (
} else if (i.level === 2) { <div
return ( className={`level-2 ${i.active ? "active" : ""}`}
<div key={i.title}
className={`level-2 ${i.active ? "active" : ""}`} onClick={() => onclickItem(i)}
key={i.title} >
onClick={() => onclickItem(i)} <div className="bs fc">
> {i.icon}
<div className="bs fc"> <span style={{ padding: "0 12px 0 6px" }}>{i.title}</span>
{i.icon} </div>
<span style={{ padding: "0 12px 0 6px" }}> <span className="time">{i.time}</span>
{i.title} </div>
</span> );
</div> }
<span className="time">{i.time}</span> })}
</div> </div>
); </aside>
} <div
})} className="content"
</div> style={{ left: state.toc.length > 0 ? 300 : "0" }}
</aside> >
<div {state.view}
className="content" </div>
style={{ left: state.toc.length > 0 ? 300 : "0" }}
>
{state.view}
</div>
</>
) : (
<Result code={403} />
)}
</div> </div>
); );
} }

View File

@ -0,0 +1,7 @@
import Result from "../../components/Result";
const ResultPage = () => {
return <Result code={403} />;
};
export default ResultPage;

View File

@ -17,6 +17,11 @@
// ); // );
background: #e9e8e5; background: #e9e8e5;
.bg {
position: absolute;
bottom: 0;
}
h2 { h2 {
font-size: 24px; font-size: 24px;
} }
@ -40,7 +45,7 @@
width: 35%; width: 35%;
height: 120%; height: 120%;
top: -10%; top: -10%;
background: #fff; background: rgba(255, 255, 255, 0.7);
box-shadow: 0 0.75rem 2rem 0 rgba(0, 0, 0, 0.1); box-shadow: 0 0.75rem 2rem 0 rgba(0, 0, 0, 0.1);
border-radius: 10px; border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.125); border: 1px solid rgba(255, 255, 255, 0.125);

View File

@ -5,6 +5,39 @@ import "./index.less";
function Subscribe() { function Subscribe() {
return ( return (
<div className="subscribe"> <div className="subscribe">
<svg
className="bg"
id="svg"
viewBox="0 0 1440 690"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#F78DA7"></stop>
<stop offset="95%" stop-color="#8ED1FC"></stop>
</linearGradient>
</defs>
<path
d="M 0,700 C 0,700 0,233 0,233 C 70.30622009569379,262.2535885167464 140.61244019138758,291.50717703349284 240,292 C 339.3875598086124,292.49282296650716 467.8564593301435,264.22488038277504 565,272 C 662.1435406698565,279.77511961722496 727.9617224880384,323.5933014354068 821,316 C 914.0382775119616,308.4066985645932 1034.2966507177032,249.40191387559807 1142,227 C 1249.7033492822968,204.59808612440193 1344.8516746411483,218.79904306220095 1440,233 C 1440,233 1440,700 1440,700 Z"
stroke="none"
stroke-width="0"
fill="url(#gradient)"
fill-opacity="0.53"
></path>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#F78DA7"></stop>
<stop offset="95%" stop-color="#8ED1FC"></stop>
</linearGradient>
</defs>
<path
d="M 0,700 C 0,700 0,466 0,466 C 100.29665071770336,416.0478468899521 200.59330143540672,366.09569377990425 301,394 C 401.4066985645933,421.90430622009575 501.92344497607667,527.665071770335 588,536 C 674.0765550239233,544.334928229665 745.7129186602871,455.244019138756 839,417 C 932.2870813397129,378.755980861244 1047.2248803827752,391.35885167464113 1151,408 C 1254.7751196172248,424.64114832535887 1347.3875598086124,445.32057416267946 1440,466 C 1440,466 1440,700 1440,700 Z"
stroke="none"
stroke-width="0"
fill="url(#gradient)"
fill-opacity="1"
></path>
</svg>
<div className="container"> <div className="container">
<h2></h2> <h2></h2>
<h4></h4> <h4></h4>