123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- import {
- PropType,
- defineComponent,
- nextTick,
- onMounted,
- reactive,
- watch,
- ref
- } from 'vue';
- import styles from './index.module.less';
- import icon_back from '../../image/icon_back.svg';
- import icon_play from '../../image/icon_class.png';
- import pre from '../../image/pre.png';
- import { useRouter } from 'vue-router';
- import { listenerMessage, postMessage } from '@/helpers/native-message';
- import { showToast } from 'vant';
- import queryString from 'query-string';
- import { state } from '@/state';
- import { browser } from '@/helpers/utils';
- export default defineComponent({
- name: 'the-book',
- props: {
- bookData: {
- type: Object as PropType<any>,
- default: () => ({})
- },
- bookLessonId: {
- type: String,
- default: ''
- },
- show: {
- type: Boolean,
- default: false
- },
- rect: {
- type: Object as PropType<DOMRect>,
- default: () => ({})
- }
- },
- emits: ['close', 'confirm'],
- setup(props, { emit }) {
- const router = useRouter();
- const lastTimeKey = 'lastTime' + (state?.user?.data?.phone ?? '');
- const debounceSkip = ref(false);
- const data = reactive({
- show: false,
- width: 0,
- height: 0,
- transform: '',
- list: [] as any[][],
- lastTime: localStorage.getItem(lastTimeKey),
- isClick: false,
- coursewareList: [] as any
- });
- const showSelectCourseware = ref(false);
- const isEnd = ref(false);
- const step = ref(0);
- let book: any = null;
- let timer: any = null;
- const handleBook = () => {
- book = (window as any).$('#flipbook');
- const height = document.body.clientHeight * 0.8;
- data.height = height;
- data.width = Math.ceil(height * (210 / 297) * 2);
- book.turn({
- autoCenter: true,
- duration: 1000,
- disabled: true,
- acceleration: true, // 是否启动硬件加速 如果为触摸设备必须为true
- // pages: 11, // 页码总数
- elevation: 50, // 转换期间页面的高度
- width: data.width, // 宽度 单位 px
- height: data.height, // 高度 单位 px
- gradients: true // 是否显示翻页阴影效果
- // display: 'single', //设置单页还是双页
- });
- book.bind('start', (event: Event, pageObject: any, corner: any) => {
- if (corner == 'tl' || corner == 'tr') {
- event.preventDefault();
- }
- if (data.isClick) {
- nextTick(() => {
- data.isClick = false;
- if (corner == 'tl' || corner == 'tr') {
- event.preventDefault();
- } else {
- book.turn('page', pageObject.next);
- }
- });
- }
- });
- // book.bind('turned', (event: Event, page: any, corner: any) => {
- // });
- book.bind('turning', (event: Event, page: any, corner: any) => {
- // console.log(page, 'page', book.turn('pages'))
- if (page === book.turn('pages')) {
- handleClose(false);
- // handleClose()
- // nextTick(() => {
- // });
- }
- if (page === 1) {
- handleClose(false);
- }
- return;
- });
- // book.bind('turned', (e: any, page: any) => {
- };
- const getRect = () => {
- const bookWrap = document.querySelector(
- '.bookWrap'
- ) as unknown as HTMLElement;
- if (bookWrap) {
- const rect = bookWrap.getBoundingClientRect();
- const xScale = props.rect.width / (rect.width / 2);
- const yScale = props.rect.height / rect.height;
- const left =
- (((rect.width / 2) * (xScale - 1)) / 2 +
- props.rect.x -
- rect.x -
- rect.width / 4) /
- xScale;
- const top =
- ((rect.height * (yScale - 1)) / 2 + props.rect.y - rect.y) / yScale;
- const transform = `scale3d(${xScale}, ${yScale}, 1) translate(${left}px, ${top}px)`;
- bookWrap.style.transform = data.transform = transform;
- bookWrap.style.transition = 'transform 0s';
- nextTick(() => {
- requestAnimationFrame(() => {
- requestAnimationFrame(() => {
- bookWrap.style.transition = 'transform 1s';
- bookWrap.style.transform = '';
- data.show = true;
- timer = setTimeout(() => {
- book.turn('page', 2);
- }, 500);
- });
- });
- });
- }
- };
- const handleClose = (gotoOne = true) => {
- // book.turn('disabled', false);
- if (isEnd.value) {
- return;
- }
- isEnd.value = true;
- clearTimeout(timer);
- const bookWrap = document.querySelector(
- '.bookWrap'
- ) as unknown as HTMLElement;
- if (gotoOne) {
- book.turn('page', 1);
- }
- if (bookWrap) {
- bookWrap.style.transform = data.transform;
- }
- emit('close');
- setTimeout(() => {
- bookWrap.style.transition = '';
- bookWrap.style.transform = '';
- data.show = false;
- data.list = [];
- isEnd.value = false;
- }, 1000);
- };
- onMounted(async () => {
- listenerMessage('webViewOnResume', () => {
- data.lastTime = localStorage.getItem(lastTimeKey);
- });
- });
- const getList = () => {
- if (!props.bookData?.lessonList) return;
- step.value = Math.floor((document.body.clientHeight * 0.8 - 40) / 50);
- const list = [];
- let listItem = [] as any[];
- for (let i = 0; i < props.bookData.lessonList.length; i++) {
- const item = props.bookData.lessonList[i];
- if (listItem.length >= step.value) {
- list.push([...listItem]);
- listItem = [{ name: item.name }];
- } else {
- listItem.push({ name: item.name });
- }
- for (let j = 0; j < item.knowledgeList.length; j++) {
- if (listItem.length >= step.value) {
- list.push([...listItem]);
- listItem = [item.knowledgeList[j]];
- } else {
- listItem.push(item.knowledgeList[j]);
- }
- }
- }
- if (listItem.length) {
- list.push(listItem);
- }
- console.log(list, 'list');
- data.list = list;
- };
- watch(
- () => props.show,
- () => {
- if (props.show) {
- getList();
- nextTick(() => {
- handleBook();
- requestAnimationFrame(() => {
- getRect();
- });
- });
- }
- }
- );
- // 检测有几个课件
- const checkCourseware = async (item: any) => {
- if (item.id) {
- if (!item.containMaterial) {
- showToast('暂无资源');
- return;
- }
- if (item.coursewareNum) {
- handleOpenPlay(item);
- // try {
- // const res = await api_lessonCoursewareStudentDetail({
- // lessonCoursewareKnowledgeDetailId: item.id
- // });
- // if (res?.code == 200) {
- // const details = res?.data?.knowledgeList[0];
- // if (!details) return;
- // // console.log(res.data)
- // // res.data.forEach((n: any) => {
- // // n.coursewareDetailKnowledgeId =
- // // n.coursewareDetailKnowledgeId || item.id;
- // // n.lessonCoursewareId = item.lessonCoursewareId;
- // // n.lessonCoursewareDetailId = item.lessonCoursewareDetailId;
- // // n.zjName = item.name; // 章节name
- // // });
- // // data.coursewareList = res.data;
- // // 如果只有一个课件,直接进入该课件
- // // if (res.data.length == 1) {
- // // handleOpenPlay(res.data[0]);
- // // } else {
- // // // 如果有多个课件,需要选择一个课件进入上课页面
- // // showSelectCourseware.value = true;
- // // }
- // handleOpenPlay(details);
- // }
- // } catch {
- // //
- // }
- }
- }
- };
- const handleOpenPlay = async (item: any) => {
- if (item.id) {
- if (debounceSkip.value) return;
- debounceSkip.value = true;
- localStorage.setItem(lastTimeKey, item.id);
- const params = {
- id: item.id, // 课件id
- lessonCoursewareId: item.lessonCoursewareId // 教材id
- // courseId: props.bookData.id,
- // lessonCoursewareDetailId: item.lessonCoursewareDetailId,
- // name: item.zjName,
- // coursewareDetailKnowledgeId: item.coursewareDetailKnowledgeId // 章节id
- };
- if (browser().isApp) {
- const query = queryString.stringify(params);
- const url =
- location.origin + location.pathname + '#/courseware-play?' + query;
- console.log('🚀 ~ url:', url);
- postMessage({
- api: 'openWebView',
- content: {
- url,
- orientation: 0,
- isHideTitle: false,
- c_orientation: 0 // 0 横屏 1 竖屏
- }
- });
- } else {
- router.push({
- path: '/courseware-play',
- query: params
- });
- }
- debounceSkip.value = false;
- }
- };
- return () => (
- <div
- class={[styles.book, data.show ? '' : styles.bookHide]}
- onClick={() => handleClose()}
- onTouchmove={() => {
- console.log('sdfds');
- data.isClick = true;
- }}>
- <div class={styles.back}>
- <img src={icon_back} />
- </div>
- <div
- class="bookWrap"
- style={{ width: data.width + 'px' }}
- onClick={(e: Event) => {
- e.stopPropagation();
- }}>
- {!!data.list.length && (
- <div id="flipbook" class={[data.show && 'animated']}>
- <div class="page">
- <img
- style="width: 100%; height: 100%; object-fit: cover;"
- src={props.bookData.coverImg}
- />
- </div>
- {data.list.map((list: any) => {
- return (
- <div class="page">
- <div class={styles.wrap}>
- <div class={styles.wrapItem}>
- {list.map((item: any, index: number) => {
- return (
- <div
- class={[styles.item, item.id && styles.des]}
- onTouchstart={(e: TouchEvent) => {
- e.stopPropagation();
- }}
- onClick={(e: Event) => {
- e.stopPropagation();
- checkCourseware(item);
- }}
- onTouchend={(e: TouchEvent) => {
- console.log(e);
- }}>
- {item.id ? (
- <img
- id={index == 1 ? 'coursewareDetail-0' : ''}
- class={styles.icon}
- src={icon_play}
- />
- ) : null}
- <div
- class={styles.name}
- style={{ lineHeight: '20Px' }}>
- {item.recentFlag && (
- <img
- src={pre}
- alt=""
- class={styles.preIcon}
- />
- )}
- <div
- class={[
- styles.nameText,
- item.recentFlag ? styles.nameTextActive : ''
- ]}>
- {' '}
- {item.name}
- </div>
- {/* <TheNoticeBar text={item.name} isAnimation={isStartAnimate(item)}></TheNoticeBar> */}
- </div>
- </div>
- );
- })}
- </div>
- </div>
- </div>
- );
- })}
- {data.list.length % 2 === 1 && (
- <div class="page" style={{ pointerEvents: 'none' }}>
- <div class={styles.wrap}>
- <div class={styles.wrapItem}></div>
- </div>
- </div>
- )}
- <div class="page">
- <img
- style="width: 100%; height: 100%; object-fit: cover;"
- src={props.bookData.coverImg}
- />
- </div>
- </div>
- )}
- </div>
- </div>
- );
- }
- });
|