|
@@ -1,9 +1,25 @@
|
|
|
-import { computed, defineComponent, onBeforeMount, reactive } from 'vue';
|
|
|
+import {
|
|
|
+ computed,
|
|
|
+ defineComponent,
|
|
|
+ onBeforeMount,
|
|
|
+ onMounted,
|
|
|
+ reactive
|
|
|
+} from 'vue';
|
|
|
import styles from './index.module.less';
|
|
|
import icon_back from './image/icon_back.svg';
|
|
|
import icon_arrow from './image/icon_arrow.svg';
|
|
|
-import { Button, Popover, Tab, Tabs, showToast } from 'vant';
|
|
|
-import { api_lessonCoursewarePage } from './api';
|
|
|
+import { Button, Image, Popover, Tab, Tabs, showToast } from 'vant';
|
|
|
+import {
|
|
|
+ api_lessonCoursewareFavoriteRemove,
|
|
|
+ api_lessonCoursewareFavoriteSave,
|
|
|
+ api_lessonCoursewareFavoriteage,
|
|
|
+ api_lessonCoursewarePage,
|
|
|
+ api_lessonCoursewareQueryStudentLessonDetail
|
|
|
+} from './api';
|
|
|
+import { NImage } from 'naive-ui';
|
|
|
+import { state } from '@/state';
|
|
|
+import TheFavorite from '@/components/the-favorite';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
|
|
|
export const BOOK_DATA = {
|
|
|
grades: [
|
|
@@ -27,6 +43,7 @@ export const BOOK_DATA = {
|
|
|
export default defineComponent({
|
|
|
name: 'courseware-list',
|
|
|
setup() {
|
|
|
+ const router = useRouter();
|
|
|
// 返回
|
|
|
const goback = () => {
|
|
|
postMessage({ api: 'goBack' });
|
|
@@ -48,12 +65,15 @@ export default defineComponent({
|
|
|
});
|
|
|
const onSelect = (action: any, index: number) => {
|
|
|
forms.currentGradeNum = index;
|
|
|
- forms.page = 1;
|
|
|
- getList();
|
|
|
+ handleChange();
|
|
|
};
|
|
|
|
|
|
const data = reactive({
|
|
|
- list: [] as any[]
|
|
|
+ list: [] as any[],
|
|
|
+ favoriteList: [] as any[],
|
|
|
+ tab: 'all',
|
|
|
+ details: [] as any[],
|
|
|
+ showBook: false
|
|
|
});
|
|
|
|
|
|
const getList = async () => {
|
|
@@ -62,25 +82,130 @@ export default defineComponent({
|
|
|
currentGradeNum: forms.currentGradeNum ? forms.currentGradeNum : ''
|
|
|
});
|
|
|
if (res?.code === 200 && Array.isArray(res?.data?.rows)) {
|
|
|
- data.list = [...res.data.rows,...res.data.rows,...res.data.rows,...res.data.rows,...res.data.rows,...res.data.rows].map((item: any) => {
|
|
|
+ data.list = res.data.rows.map((item: any) => {
|
|
|
+ const type = BOOK_DATA.bookTypes[item.bookType];
|
|
|
+ item.name = `${item.name}(${type})`;
|
|
|
+ item.load = false;
|
|
|
+ item.key = Date.now() + item.id;
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const getFavoriteList = async () => {
|
|
|
+ const res = await api_lessonCoursewareFavoriteage({
|
|
|
+ clientType: 'STUDENT',
|
|
|
+ userId: state.user?.data?.id,
|
|
|
+ page: forms.page,
|
|
|
+ rows: forms.rows
|
|
|
+ });
|
|
|
+ if (res?.code === 200 && Array.isArray(res?.data?.rows)) {
|
|
|
+ data.list = res.data.rows.map((item: any) => {
|
|
|
const type = BOOK_DATA.bookTypes[item.bookType];
|
|
|
item.name = `${item.name}(${type})`;
|
|
|
+ item.load = false;
|
|
|
+ item.key = Date.now() + item.id;
|
|
|
return item;
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
- onBeforeMount(() => {
|
|
|
- getList();
|
|
|
+ const getData = () => {
|
|
|
+ if (data.tab === 'all') {
|
|
|
+ getList();
|
|
|
+ }
|
|
|
+ if (data.tab === 'favorite') {
|
|
|
+ getFavoriteList();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const handleChange = () => {
|
|
|
+ forms.page = 1;
|
|
|
+ getData();
|
|
|
+ };
|
|
|
+ onMounted(() => {
|
|
|
+ getData();
|
|
|
});
|
|
|
+
|
|
|
+ const handleFavorite = async (item: any) => {
|
|
|
+ if (item.favoriteFlag) {
|
|
|
+ await api_lessonCoursewareFavoriteSave({
|
|
|
+ lessonCoursewareId: item.id
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ await api_lessonCoursewareFavoriteRemove({
|
|
|
+ lessonCoursewareId: item.id
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ let timer: any = null;
|
|
|
+ const dubounce = (fn: any, delay: number = 300) => {
|
|
|
+ if (timer) {
|
|
|
+ clearTimeout(timer);
|
|
|
+ }
|
|
|
+ timer = setTimeout(fn, delay);
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 学生端根据教材编号获取关联的单元、章节 */
|
|
|
+ const getDetail = async (item: any) => {
|
|
|
+ const res = await api_lessonCoursewareQueryStudentLessonDetail({
|
|
|
+ lessonCoursewareId: item.id
|
|
|
+ });
|
|
|
+ if (res?.code == 200) {
|
|
|
+ data.details = res.data;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleCreateContainer = (id: string) => {
|
|
|
+ const box = document.querySelector(
|
|
|
+ `[data-id="${id}"]`
|
|
|
+ ) as unknown as HTMLElement;
|
|
|
+ if (!box) return;
|
|
|
+ const rect = box.getBoundingClientRect();
|
|
|
+ const container = document.createElement('div');
|
|
|
+ console.log('🚀 ~ box:', box);
|
|
|
+ container.style.left = `${rect.x}px`;
|
|
|
+ container.style.top = `${rect.y}px`;
|
|
|
+ container.style.width = `${rect.width}px`;
|
|
|
+ container.style.height = `${rect.height}px`;
|
|
|
+ container.style.position = 'fixed';
|
|
|
+ container.style.zIndex = '9999';
|
|
|
+ container.appendChild(box.cloneNode(true));
|
|
|
+ document.body.appendChild(container);
|
|
|
+ setTimeout(() => {
|
|
|
+ container.style.transformOrigin = 'left';
|
|
|
+ container.style.left = `50vw`;
|
|
|
+ container.style.top = `25vh`;
|
|
|
+ container.style.transition = 'all 0.3s ease-in-out';
|
|
|
+ container.style.transform = 'scale(1.5)';
|
|
|
+ container.style.backfaceVisibility = 'hidden';
|
|
|
+ setTimeout(() => {
|
|
|
+ container.style.transform = 'scale(1.5) rotateY(180deg)';
|
|
|
+ }, 300);
|
|
|
+ }, 0);
|
|
|
+ };
|
|
|
+ const handleOpen = (item: any) => {
|
|
|
+ getDetail(item);
|
|
|
+ data.showBook = true;
|
|
|
+ // handleCreateContainer(item.id);
|
|
|
+ // postMessage({
|
|
|
+ // api: 'openCourseware',
|
|
|
+ // params: {
|
|
|
+ // lessonCoursewareId: item.id
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ };
|
|
|
+
|
|
|
return () => (
|
|
|
<div class={styles.container}>
|
|
|
<div class={styles.head}>
|
|
|
<div class={styles.back} onClick={goback}>
|
|
|
<img src={icon_back} />
|
|
|
</div>
|
|
|
- <Tabs class={styles.tabs}>
|
|
|
- <Tab title="全部教材" name="全部教材"></Tab>
|
|
|
- <Tab title="我的收藏" name="我的收藏"></Tab>
|
|
|
+ <Tabs
|
|
|
+ class={styles.tabs}
|
|
|
+ v-model:active={data.tab}
|
|
|
+ onChange={() => handleChange()}>
|
|
|
+ <Tab title="全部教材" name="all"></Tab>
|
|
|
+ <Tab title="我的收藏" name="favorite"></Tab>
|
|
|
</Tabs>
|
|
|
<Popover
|
|
|
class={styles.popover}
|
|
@@ -89,7 +214,8 @@ export default defineComponent({
|
|
|
{{
|
|
|
reference: () => (
|
|
|
<Button class={styles.downBtn} round size="small">
|
|
|
- 全部年级 <img class={styles.icon} src={icon_arrow} />
|
|
|
+ {BOOK_DATA.grades[forms.currentGradeNum].text}{' '}
|
|
|
+ <img class={styles.icon} src={icon_arrow} />
|
|
|
</Button>
|
|
|
)
|
|
|
}}
|
|
@@ -100,13 +226,77 @@ export default defineComponent({
|
|
|
<div class={styles.wrap}>
|
|
|
{data.list.map((item, index) => {
|
|
|
return (
|
|
|
- <div class={styles.wrapItem}>
|
|
|
- <img class={styles.cover} src={item.coverImg} />
|
|
|
+ <div
|
|
|
+ class={styles.wrapItem}
|
|
|
+ key={item.key}
|
|
|
+ onClick={() => handleOpen(item)}>
|
|
|
+ <NImage
|
|
|
+ data-id={item.id}
|
|
|
+ class={[styles.cover, item.load ? styles.loaded : '']}
|
|
|
+ objectFit="cover"
|
|
|
+ src={item.coverImg}
|
|
|
+ onLoad={() => {
|
|
|
+ item.load = true;
|
|
|
+ }}
|
|
|
+ onError={() => {
|
|
|
+ item.load = true;
|
|
|
+ }}
|
|
|
+ />
|
|
|
<div class={styles.name}>{item.name}</div>
|
|
|
+ {data.tab === 'all' && (
|
|
|
+ <div
|
|
|
+ class={styles.favoriteBtn}
|
|
|
+ onClick={() => {
|
|
|
+ item.favoriteFlag = !item.favoriteFlag;
|
|
|
+ dubounce(() => handleFavorite(item));
|
|
|
+ }}>
|
|
|
+ <TheFavorite isFavorite={item.favoriteFlag} />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</div>
|
|
|
);
|
|
|
})}
|
|
|
-
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={[styles.book, data.showBook && styles.show]}>
|
|
|
+ <div class={styles.bookWrap}>
|
|
|
+ {data.details.map((item: any) => {
|
|
|
+ return (
|
|
|
+ <div class={styles.detail}>
|
|
|
+ <div class={styles.detailTitle}>{item.name}</div>
|
|
|
+ {item.knowledgeDetails.map((k: any) => {
|
|
|
+ return <div>{k.name}</div>;
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ {!data.details.length && (
|
|
|
+ <div
|
|
|
+ onClick={() => {
|
|
|
+ router.push({
|
|
|
+ path: '/courseware-play',
|
|
|
+ query: {
|
|
|
+ id: '1678286165663399937',
|
|
|
+ name: '人教第一单元第二章节'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }}>
|
|
|
+ 人教第一单元第二章节(如果显示这个,就是返回的数据为空,
|
|
|
+ 次为固定的后台某个单元)
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ <div style={{ padding: '8px 14px' }}>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ block
|
|
|
+ onClick={() => {
|
|
|
+ data.showBook = false;
|
|
|
+ }}>
|
|
|
+ 关闭
|
|
|
+ </Button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|