|
@@ -25,13 +25,7 @@ import MusicScore from './component/musicScore';
|
|
|
// import iconDian from './image/icon-dian.svg';
|
|
|
// import iconPoint from './image/icon-point.svg';
|
|
|
// import qs from 'query-string';
|
|
|
-import {
|
|
|
- iconUp,
|
|
|
- iconDown,
|
|
|
- // iconPen,
|
|
|
- iconTouping,
|
|
|
- iconMenu
|
|
|
-} from './image/icons.json';
|
|
|
+import { iconUp, iconDown, iconPen, iconTouping, iconMenu, iconCourseType } from './image/icons.json';
|
|
|
import Points from './component/points';
|
|
|
import { browser } from '@/helpers/utils';
|
|
|
import { Vue3Lottie } from 'vue3-lottie';
|
|
@@ -40,12 +34,14 @@ import { usePageVisibility } from '@vant/use';
|
|
|
// import PlayRecordTime from './playRecordTime';
|
|
|
import { handleCheckVip } from '../hook/useFee';
|
|
|
import OGuide from '@/components/o-guide';
|
|
|
-import Tool, { ToolItem, ToolType } from './component/tool';
|
|
|
-import Pen from './component/tools/pen';
|
|
|
// import VideoItem from './component/video-item';
|
|
|
import VideoPlay from './component/video-play';
|
|
|
import deepClone from '@/helpers/deep-clone';
|
|
|
import { useInterval, useIntervalFn } from '@vueuse/core';
|
|
|
+import CoursewareType from './component/courseware-type';
|
|
|
+import CoursewareTips from './component/courseware-tips';
|
|
|
+import GlobalTools from '@/components/globalTools';
|
|
|
+import { isPlay, penShow, toolOpen, whitePenShow } from '@/components/globalTools/globalTools';
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'CoursewarePlay',
|
|
@@ -77,7 +73,7 @@ export default defineComponent({
|
|
|
};
|
|
|
const handleInit = (type = 0) => {
|
|
|
//设置容器16:9
|
|
|
- setContainer();
|
|
|
+ // setContainer();
|
|
|
// 横屏
|
|
|
postMessage(
|
|
|
{
|
|
@@ -121,7 +117,9 @@ export default defineComponent({
|
|
|
const route = useRoute();
|
|
|
const headeRef = ref();
|
|
|
const data = reactive({
|
|
|
+ currentId: route.query.id as any,
|
|
|
detail: null as any,
|
|
|
+ refLevelList: [] as any, // 课堂类型
|
|
|
knowledgePointList: [] as any,
|
|
|
itemList: [] as any,
|
|
|
showHead: true,
|
|
@@ -282,11 +280,11 @@ export default defineComponent({
|
|
|
}, 500);
|
|
|
});
|
|
|
};
|
|
|
- const getDetail = async () => {
|
|
|
+ const getDetail = async (id?: any) => {
|
|
|
try {
|
|
|
const res: any = await request.get(
|
|
|
state.platformApi +
|
|
|
- `/lessonCourseware/getLessonCourseDetail/${route.query.id}`,
|
|
|
+ `/lessonCourseware/getLessonCourseDetail/${id || route.query.id}`,
|
|
|
{
|
|
|
hideLoading: true
|
|
|
}
|
|
@@ -365,6 +363,17 @@ export default defineComponent({
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ const onTitleTip = (type: "phaseGoals" | "checkItem", text: string) => {
|
|
|
+ handleStop()
|
|
|
+ popupData.pointOpen = true
|
|
|
+ popupData.pointContent = text
|
|
|
+ if(type === "checkItem") {
|
|
|
+ popupData.pointTitle = '阶段目标'
|
|
|
+ } else if(type === "phaseGoals") {
|
|
|
+ popupData.pointTitle = '检查事项'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// ifram事件处理
|
|
|
const iframeHandle = (ev: MessageEvent) => {
|
|
|
if (ev.data?.api === 'headerTogge') {
|
|
@@ -453,8 +462,24 @@ export default defineComponent({
|
|
|
//
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+ const getRefLevel = async (id?: any) => {
|
|
|
+ try {
|
|
|
+ const res = await request.post(state.platformApi + '/lessonCourseware/refLevel', {
|
|
|
+ data: {
|
|
|
+ lessonCoursewareDetailId: id || route.query.id
|
|
|
+ }
|
|
|
+ })
|
|
|
+ console.log(res.data, '1212')
|
|
|
+ data.refLevelList = res.data || []
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
onMounted(async () => {
|
|
|
await sysParamConfig();
|
|
|
+ await getRefLevel()
|
|
|
await getDetail();
|
|
|
const hasFree = String(data.detail?.accessScope) === '0';
|
|
|
if (!hasFree) {
|
|
@@ -506,6 +531,10 @@ export default defineComponent({
|
|
|
};
|
|
|
|
|
|
const popupData = reactive({
|
|
|
+ pointOpen: false,
|
|
|
+ pointContent: "",
|
|
|
+ pointTitle: "",
|
|
|
+ coursewareOpen: false,
|
|
|
open: false,
|
|
|
activeIndex: 0,
|
|
|
playIndex: 0,
|
|
@@ -570,18 +599,6 @@ export default defineComponent({
|
|
|
activeData.model = type;
|
|
|
};
|
|
|
|
|
|
- // 去点名,签退
|
|
|
- // const gotoRollCall = (pageTag: string) => {
|
|
|
- // postMessage({
|
|
|
- // api: 'open_app_page',
|
|
|
- // content: {
|
|
|
- // action: 'app',
|
|
|
- // pageTag: pageTag,
|
|
|
- // url: '',
|
|
|
- // params: JSON.stringify({ courseId: route.query.courseId })
|
|
|
- // }
|
|
|
- // });
|
|
|
- // };
|
|
|
|
|
|
// 双击
|
|
|
const handleDbClick = () => {
|
|
@@ -743,42 +760,6 @@ export default defineComponent({
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- /** 教学数据 */
|
|
|
- const studyData = reactive({
|
|
|
- type: '' as ToolType,
|
|
|
- penShow: false
|
|
|
- });
|
|
|
-
|
|
|
- /** 打开教学工具 */
|
|
|
- const openStudyTool = (item: ToolItem) => {
|
|
|
- const activeItem = data.itemList[popupData.activeIndex];
|
|
|
- // 暂停视频和曲谱的播放
|
|
|
- if (activeItem.typeCode === 'VIDEO' && activeItem.videoEle) {
|
|
|
- activeItem.videoEle.pause();
|
|
|
- }
|
|
|
- if (activeItem.typeCode === 'SONG') {
|
|
|
- activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
- { api: 'setPlayState' },
|
|
|
- '*'
|
|
|
- );
|
|
|
- }
|
|
|
- clearModel();
|
|
|
- popupData.toolOpen = false;
|
|
|
- studyData.type = item.type;
|
|
|
-
|
|
|
- switch (item.type) {
|
|
|
- case 'pen':
|
|
|
- studyData.penShow = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- /** 关闭教学工具 */
|
|
|
- const closeStudyTool = () => {
|
|
|
- studyData.type = 'init';
|
|
|
- toggleModel();
|
|
|
- };
|
|
|
-
|
|
|
const activeVideoItem = computed(() => {
|
|
|
const item = data.itemList[popupData.activeIndex];
|
|
|
if (
|
|
@@ -851,6 +832,28 @@ export default defineComponent({
|
|
|
}
|
|
|
);
|
|
|
|
|
|
+ // 是否收起
|
|
|
+ watch(
|
|
|
+ () => activeData.model,
|
|
|
+ () => {
|
|
|
+ if (activeData.model) {
|
|
|
+ isPlay.value = false
|
|
|
+ } else {
|
|
|
+ isPlay.value = true
|
|
|
+ toolOpen.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ // 白板的批注打开时暂停播放
|
|
|
+ watch(
|
|
|
+ () => [whitePenShow.value, penShow.value],
|
|
|
+ () => {
|
|
|
+ if (whitePenShow.value || penShow.value) {
|
|
|
+ handleStop()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
/**
|
|
|
* 初始化视频时长
|
|
|
* @param newVal 播放状态
|
|
@@ -894,24 +897,6 @@ export default defineComponent({
|
|
|
// 更新时间
|
|
|
const updateStat = async () => {
|
|
|
try {
|
|
|
- // const itemList = data.itemList;
|
|
|
- // const params: any = [];
|
|
|
- // itemList.forEach((item: any) => {
|
|
|
- // if (item.moreTime.length > 0) {
|
|
|
- // const videoBrowseData = formatEffectiveTime(item.moreTime);
|
|
|
- // const time =
|
|
|
- // videoBrowseData.length > 0 ? formatTimer(videoBrowseData) : 0;
|
|
|
- // const temp = {
|
|
|
- // lessonCoursewareDetailId: route.query.id,
|
|
|
- // browseTime: time, // 播放时长
|
|
|
- // videoBrowseData: JSON.stringify(videoBrowseData), // 播放的数据
|
|
|
- // videoTime: item.videoTime, // 视频时长
|
|
|
- // materialId: item.materialId
|
|
|
- // };
|
|
|
- // params.push(temp);
|
|
|
- // }
|
|
|
- // });
|
|
|
-
|
|
|
// 只有学生才统计数据
|
|
|
if (state.platformType === 'STUDENT') {
|
|
|
const videoTime = videoIntervalRef.counter.value;
|
|
@@ -1048,52 +1033,6 @@ export default defineComponent({
|
|
|
? effects[effectIndex.value].next
|
|
|
: {}
|
|
|
}>
|
|
|
- {/* {m.type === 'VIDEO' && (
|
|
|
- <>
|
|
|
- <VideoPlay
|
|
|
- ref={(v: any) => (data.videoRefs[mIndex] = v)}
|
|
|
- item={m}
|
|
|
- isActive={activeEle}
|
|
|
- isEmtry={isEmtry}
|
|
|
- onPrepare={(val) => {
|
|
|
- m.isprepare = val
|
|
|
- }}
|
|
|
- onLoadedmetadata={(videoItem: any) => {
|
|
|
- m.videoEle = videoItem
|
|
|
- }}
|
|
|
- onTogglePlay={(paused: boolean) => {
|
|
|
- // console.log('播放切换', paused)
|
|
|
- if (!m.isprepare) {
|
|
|
- m.isprepare = true
|
|
|
- }
|
|
|
- m.autoPlay = false
|
|
|
- if (paused || popupData.open || popupData.guideOpen) {
|
|
|
- clearTimeout(activeData.timer)
|
|
|
- } else {
|
|
|
- setModelOpen()
|
|
|
- }
|
|
|
- }}
|
|
|
- onEnded={() => {
|
|
|
- const _index = popupData.activeIndex + 1
|
|
|
- if (_index < data.itemList.length) {
|
|
|
- handleSwipeChange(_index)
|
|
|
- }
|
|
|
- }}
|
|
|
- onReset={() => {
|
|
|
- if (!m.videoEle?.paused) {
|
|
|
- setModelOpen()
|
|
|
- }
|
|
|
- }}
|
|
|
- />
|
|
|
- <Transition name="van-fade">
|
|
|
- {!m.isprepare && (
|
|
|
- <div class={styles.loadWrap}>
|
|
|
- <Vue3Lottie animationData={playLoadData}></Vue3Lottie>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </Transition>
|
|
|
- </>
|
|
|
- )} */}
|
|
|
<Transition name="van-fade">
|
|
|
{m.typeCode === 'VIDEO' &&
|
|
|
data.animationState !== 'end' &&
|
|
@@ -1152,160 +1091,84 @@ export default defineComponent({
|
|
|
);
|
|
|
})}
|
|
|
</div>
|
|
|
- <Transition name="right">
|
|
|
- {activeData.model && (
|
|
|
- <div
|
|
|
- class={styles.rightFixedBtns}
|
|
|
- onClick={(e: Event) => {
|
|
|
- e.stopPropagation();
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- }}>
|
|
|
- <div class={styles.btnsWrap}>
|
|
|
- <div
|
|
|
- class={[styles.fullBtn, styles.point]}
|
|
|
- onClick={() => (popupData.open = true)}>
|
|
|
- <img src={iconMenu} />
|
|
|
- <span>知识点</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class={[styles.btnsWrap, styles.btnsBottom]}>
|
|
|
- {/* <div class={styles.fullBtn} onClick={() => (popupData.guideOpen = true)}>
|
|
|
- <img src={iconTouping} />
|
|
|
- <span>投屏</span>
|
|
|
- </div> */}
|
|
|
- {/* {data.isCourse && (
|
|
|
- <>
|
|
|
- <div
|
|
|
- class={styles.fullBtn}
|
|
|
- onClick={() => gotoRollCall('student_roll_call')}>
|
|
|
- <img src={iconDian} />
|
|
|
- <span>点名</span>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class={styles.fullBtn}
|
|
|
- onClick={() => gotoRollCall('sign_out')}>
|
|
|
- <img src={iconPoint} />
|
|
|
- <span>签退</span>
|
|
|
- </div>
|
|
|
- </>
|
|
|
- )} */}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </Transition>
|
|
|
|
|
|
<Transition name="left">
|
|
|
{activeData.model && (
|
|
|
- <div
|
|
|
- class={styles.leftFixedBtns}
|
|
|
- onClick={(e: Event) => e.stopPropagation()}>
|
|
|
- {popupData.activeIndex != 0 && (
|
|
|
- <div class={[styles.btnsWrap, styles.prePoint]}>
|
|
|
+ <div class={styles.leftFixedBtns} onClick={(e: Event) => e.stopPropagation()}>
|
|
|
+ <div class={[styles.btnsWrap, styles.prePoint]}>
|
|
|
+ <div class={styles.fullBtn} onClick={() => {
|
|
|
+ handleStop()
|
|
|
+ popupData.coursewareOpen = true
|
|
|
+ }}>
|
|
|
+ <img src={iconCourseType} />
|
|
|
+ </div>
|
|
|
+ <div class={styles.fullBtn} onClick={() => {
|
|
|
+ handleStop()
|
|
|
+ popupData.open = true
|
|
|
+ }}>
|
|
|
+ <img src={iconMenu} />
|
|
|
+ {/* <span>知识点</span> */}
|
|
|
+ </div>
|
|
|
+
|
|
|
<div
|
|
|
- class={styles.fullBtn}
|
|
|
+ class={[styles.fullBtn, !(popupData.activeIndex != 0) && styles.disabled]}
|
|
|
onClick={() => {
|
|
|
- // useThrottleFn(() => {
|
|
|
- // handlePreAndNext('up')
|
|
|
- // }, 300)
|
|
|
- // onChangeSwiper('up')
|
|
|
- handlePreAndNext('up');
|
|
|
- }}>
|
|
|
+ if(popupData.activeIndex != 0) handlePreAndNext('up')
|
|
|
+ }}
|
|
|
+ >
|
|
|
<img src={iconUp} />
|
|
|
- <span style={{ textAlign: 'center' }}>上一个</span>
|
|
|
+ {/* <span style={{ textAlign: 'center' }}>上一个</span> */}
|
|
|
</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- {popupData.activeIndex != data.itemList.length - 1 && (
|
|
|
- <div class={styles.btnsWrap}>
|
|
|
<div
|
|
|
- class={styles.fullBtn}
|
|
|
+ class={[styles.fullBtn, !(popupData.activeIndex != data.itemList.length - 1) && styles.disabled]}
|
|
|
onClick={() => {
|
|
|
- // console.log('click down')
|
|
|
- // useThrottleFn(() => {
|
|
|
- // console.log('click down pass')
|
|
|
- // handlePreAndNext('down')
|
|
|
- // }, 300)
|
|
|
- // onChangeSwiper('down')
|
|
|
- handlePreAndNext('down');
|
|
|
- }}>
|
|
|
- <span style={{ textAlign: 'center' }}>下一个</span>
|
|
|
+ if(popupData.activeIndex != data.itemList.length - 1) handlePreAndNext('down')
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {/* <span style={{ textAlign: 'center' }}>下一个</span> */}
|
|
|
<img src={iconDown} />
|
|
|
</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
)}
|
|
|
</Transition>
|
|
|
</div>
|
|
|
|
|
|
- <div
|
|
|
- style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
|
|
|
- id="coursePlayHeader"
|
|
|
- class={styles.headerContainer}
|
|
|
- ref={headeRef}>
|
|
|
- <div class={styles.backBtn} onClick={() => goback()}>
|
|
|
- <Icon name={iconBack} />
|
|
|
- 返回
|
|
|
- </div>
|
|
|
- {/* {data.isCourse && (
|
|
|
- <PlayRecordTime ref={playRef} list={data.knowledgePointList} />
|
|
|
- )} */}
|
|
|
<div
|
|
|
- class={styles.menu}
|
|
|
- onClick={() => {
|
|
|
- const _effectIndex = effectIndex.value + 1;
|
|
|
- effectIndex.value =
|
|
|
- _effectIndex >= effects.length - 1 ? 0 : _effectIndex;
|
|
|
- setModelOpen();
|
|
|
- }}>
|
|
|
- {popupData.tabName}
|
|
|
- </div>
|
|
|
-
|
|
|
- {state.platformType == 'TEACHER' && (
|
|
|
- <div
|
|
|
- class={styles.headRight}
|
|
|
- onClick={(e: Event) => {
|
|
|
- e.stopPropagation();
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- }}>
|
|
|
- <div
|
|
|
- class={styles.rightBtn}
|
|
|
- onClick={() => (popupData.guideOpen = true)}>
|
|
|
- <img src={iconTouping} />
|
|
|
+ style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
|
|
|
+ id="coursePlayHeader"
|
|
|
+ class={styles.headerContainer}
|
|
|
+ ref={headeRef}
|
|
|
+ >
|
|
|
+ <div class={styles.backBtn} onClick={() => goback()}>
|
|
|
+ <Icon name={iconBack} />
|
|
|
+ <div class={styles.titleSection}>
|
|
|
+ <div class={styles.title}>{popupData.tabName}</div>
|
|
|
+ <div class={styles.titleContent}>
|
|
|
+ <p>{data.itemList[popupData.activeIndex]?.name}</p>
|
|
|
+ {data.detail?.lessonTargetDesc ? <span onClick={() => onTitleTip('phaseGoals', data.detail?.lessonTargetDesc)}>阶段目标</span>: ""}
|
|
|
+ {data.itemList[popupData.activeIndex]?.checkItem ? <span onClick={() => onTitleTip('checkItem', data.itemList[popupData.activeIndex]?.checkItem)}>检查事项</span> : ""}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- {/* <div
|
|
|
- class={styles.rightBtn}
|
|
|
- onClick={() => {
|
|
|
- openStudyTool({
|
|
|
- type: 'pen',
|
|
|
- icon: iconPen,
|
|
|
- name: '批注'
|
|
|
- });
|
|
|
- }}>
|
|
|
- <img src={iconPen} />
|
|
|
- </div> */}
|
|
|
- {/* <div class={styles.rightBtn} onClick={() => (popupData.toolOpen = true)}>
|
|
|
- <img src={iconMore} />
|
|
|
- </div> */}
|
|
|
</div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
|
|
|
- {/* 更多弹窗 */}
|
|
|
- <Popup
|
|
|
- class={styles.popupMore}
|
|
|
- overlayClass={styles.overlayClass}
|
|
|
- position="right"
|
|
|
- round
|
|
|
- v-model:show={popupData.toolOpen}
|
|
|
- onClose={handleClosePopup}>
|
|
|
- <Tool onHandleTool={openStudyTool} />
|
|
|
- </Popup>
|
|
|
+ {state.platformType === 'TEACHER' && (
|
|
|
+ <div
|
|
|
+ class={styles.headRight}
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ e.stopPropagation()
|
|
|
+ clearTimeout(activeData.timer)
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div class={styles.rightBtn} onClick={() => (popupData.guideOpen = true)}>
|
|
|
+ <img src={iconTouping} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
|
|
|
<Popup
|
|
|
- class={styles.popup}
|
|
|
- style={{ background: 'rgba(0,0,0, 0.75)' }}
|
|
|
+ class={[styles.popup, styles.popupCoursewarePlay]}
|
|
|
overlayClass={styles.overlayClass}
|
|
|
position="right"
|
|
|
round
|
|
@@ -1324,7 +1187,31 @@ export default defineComponent({
|
|
|
</Popup>
|
|
|
|
|
|
<Popup
|
|
|
- class={styles.popup}
|
|
|
+ class={[styles.popup, styles.popupCoursewarePlay]}
|
|
|
+ overlayClass={styles.overlayClass}
|
|
|
+ position="right"
|
|
|
+ round
|
|
|
+ v-model:show={popupData.coursewareOpen}
|
|
|
+ onClose={handleClosePopup}>
|
|
|
+ {/* 课件类型 */}
|
|
|
+ <CoursewareType list={data.refLevelList} onConfirm={async (item: any) => {
|
|
|
+ // 判断是否为当前课程类型
|
|
|
+ if(data.currentId === item.id) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ data.currentId = item.id;
|
|
|
+ await getDetail(item.id);
|
|
|
+ await getRefLevel(item.id);
|
|
|
+ popupData.coursewareOpen = false;
|
|
|
+ popupData.activeIndex = 0;
|
|
|
+ nextTick(() => {
|
|
|
+ popupData.open = true
|
|
|
+ })
|
|
|
+ }} />
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ <Popup
|
|
|
+ class={[styles.popup, styles.popupCoursewarePlay]}
|
|
|
overlayClass={styles.overlayClass}
|
|
|
position="right"
|
|
|
round
|
|
@@ -1333,9 +1220,16 @@ export default defineComponent({
|
|
|
<OGuide />
|
|
|
</Popup>
|
|
|
|
|
|
- {studyData.penShow && (
|
|
|
- <Pen show={studyData.type === 'pen'} close={() => closeStudyTool()} />
|
|
|
- )}
|
|
|
+ <Popup
|
|
|
+ class={[styles.popup, styles.popupCoursewarePlay, styles.popupPoint]}
|
|
|
+ round
|
|
|
+ closeable
|
|
|
+ v-model:show={popupData.pointOpen}
|
|
|
+ onClose={handleClosePopup}>
|
|
|
+ <CoursewareTips content={popupData.pointContent} titleName={popupData.pointTitle} />
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ <GlobalTools />
|
|
|
</div>
|
|
|
);
|
|
|
}
|