web-backset.cn/apps/web/src/view/Course/index.tsx

139 lines
4.0 KiB
TypeScript
Raw Normal View History

2023-02-27 15:41:19 +08:00
import "./index.less";
2023-03-01 11:18:24 +08:00
import Timeline, { IOnScrollParam } from "./components/Timeline";
2023-02-28 17:58:30 +08:00
import Tab20Regular from "@ricons/fluent/Tab20Regular";
import Table20Regular from "@ricons/fluent/Table20Regular";
2023-03-17 17:58:37 +08:00
import { useRef, useState } from "react";
2023-02-28 23:33:16 +08:00
import { Icon } from "@ricons/utils";
2023-03-01 15:24:27 +08:00
import { useNavigate } from "react-router-dom";
2023-03-12 22:30:09 +08:00
import { useMount } from "../../hook";
import { getCourseList } from "../../api";
import { processTime } from "./util";
2023-03-13 16:52:27 +08:00
import { Footer } from "../../components/Footer";
2023-03-17 17:58:37 +08:00
import Card from "./components/Card";
2023-02-27 15:41:19 +08:00
export default function Index() {
2023-03-01 15:24:27 +08:00
const navigate = useNavigate();
2023-03-01 11:18:24 +08:00
const thumbnailRef = useRef<HTMLElement | null>(null);
const scale = useRef<number>(1); // thumbnail / timeline 高度比例
const [timeline, setTimeline] = useState({
2023-02-28 23:58:50 +08:00
top: -4,
});
2023-02-28 23:33:16 +08:00
2023-02-28 17:58:30 +08:00
const [actions, setActions] = useState([
{
key: "table",
2023-02-28 23:33:16 +08:00
icon: <Table20Regular />,
2023-02-28 17:58:30 +08:00
active: true,
2023-03-01 11:18:24 +08:00
tip: "列出更多项目",
gridClass: "table",
2023-02-28 17:58:30 +08:00
},
2023-03-17 17:58:37 +08:00
{
key: "tab",
icon: <Tab20Regular />,
active: false,
tip: "使用大缩略图显示单个项目",
gridClass: "tab",
},
2023-02-28 17:58:30 +08:00
]);
2023-03-12 22:30:09 +08:00
useMount(() => {
getCourseList().then((res) => {
setCourseTimeList(processTime(res.data));
});
});
const [courseTimeList, setCourseTimeList] = useState<any>([]);
2023-02-28 17:58:30 +08:00
const onClickActionItem = (action: any) => {
setActions((p) => p.map((a) => ({ ...a, active: a.key === action.key })));
};
2023-03-01 11:18:24 +08:00
/**
* 线
*/
const onTimelineScroll = (p: IOnScrollParam) => {
2023-02-28 23:33:16 +08:00
const { top, height } = p;
//左侧区域高度
2023-03-01 11:18:24 +08:00
const { scrollHeight, clientHeight } = thumbnailRef.current!;
scale.current = (scrollHeight - clientHeight) / height;
thumbnailRef.current!.scrollTop = top * scale.current;
2023-02-28 23:58:50 +08:00
};
2023-03-01 11:18:24 +08:00
/**
*
*/
const onThumbnailScroll = () => {
const { scrollHeight, scrollTop } = thumbnailRef.current!;
2023-02-28 23:58:50 +08:00
const isTop = scrollTop === 0;
const isBottom = scrollTop === scrollHeight;
2023-03-01 11:18:24 +08:00
const top = isTop ? -4 : scrollTop / scale.current; // 修正顶部
setTimeline({ top });
2023-02-28 23:33:16 +08:00
};
2023-03-18 22:03:17 +08:00
/**
*
*/
2023-03-01 15:24:27 +08:00
const onClickCourseItem = (d: any) => {
2023-03-12 22:30:09 +08:00
navigate(`/course/detail/${d.course_id}`);
2023-03-01 15:24:27 +08:00
};
2023-02-27 15:41:19 +08:00
return (
<div className="container course">
2023-02-28 17:58:30 +08:00
<div className="action-bar">
2023-03-17 17:58:37 +08:00
{actions.map((action) => (
<span
key={action.key}
style={{ cursor: "pointer" }}
onClick={() => onClickActionItem(action)}
className="bs tip ml6"
data-tip={action.tip}
>
<Icon
size={20}
color={
action.active ? "var(--color-text-2)" : "var(--color-text-4)"
2023-03-01 11:18:24 +08:00
}
2023-03-17 17:58:37 +08:00
>
{action.icon}
</Icon>
</span>
))}
2023-02-28 17:58:30 +08:00
</div>
2023-03-01 11:18:24 +08:00
<div className="thumbnail-timeline">
<div className="thumbnail-container">
<article ref={thumbnailRef} onScroll={onThumbnailScroll}>
2023-03-12 22:30:09 +08:00
{courseTimeList.map((item: any, index: number) => (
2023-02-28 23:33:16 +08:00
<section key={index}>
<div className="time">
{item.year}{item.month}
</div>
<div className="statistic">{item.data.length} </div>
2023-03-01 11:18:24 +08:00
<div
className={`grid ${actions.find((a) => a.active)?.gridClass}`}
>
2023-02-28 23:33:16 +08:00
{item.data.map((d: any) => (
2023-03-17 17:58:37 +08:00
<Card
2023-03-01 15:24:27 +08:00
onClick={() => onClickCourseItem(d)}
2023-03-12 22:30:09 +08:00
key={d.course_id}
imgUrl={d.course_cover_url}
title={d.course_title}
2023-03-22 10:09:21 +08:00
summary={d.course_summary}
2023-03-01 15:24:27 +08:00
/>
2023-02-28 23:33:16 +08:00
))}
</div>
</section>
))}
</article>
2023-02-28 17:58:30 +08:00
</div>
2023-03-01 11:18:24 +08:00
<Timeline
className="timeline-container"
2023-02-28 23:33:16 +08:00
data={courseTimeList}
2023-03-01 11:18:24 +08:00
onScroll={onTimelineScroll}
model={{ top: timeline.top }}
2023-02-28 23:33:16 +08:00
/>
2023-02-27 18:01:37 +08:00
</div>
2023-03-13 16:52:27 +08:00
<Footer />
2023-02-27 15:41:19 +08:00
</div>
);
}