|
@@ -1,2422 +1,2445 @@
|
|
|
-import {
|
|
|
- defineComponent,
|
|
|
- onMounted,
|
|
|
- reactive,
|
|
|
- onUnmounted,
|
|
|
- ref,
|
|
|
- Transition,
|
|
|
- computed,
|
|
|
- nextTick,
|
|
|
- watch,
|
|
|
- toRef
|
|
|
-} from 'vue';
|
|
|
-import styles from './index.module.less';
|
|
|
-import 'plyr/dist/plyr.css';
|
|
|
-import MusicScore from './component/musicScore';
|
|
|
-// import iconChange from './image/icon-change.png';
|
|
|
-// import iconMenu from './image/icon-menu.png';
|
|
|
-// import iconUp from './image/icon-up.png';
|
|
|
-// import iconDown from './image/icon-down.png';
|
|
|
-// import iconNote from './image/icon-note.png';
|
|
|
-// import iconWhiteboard from './image/icon-whiteboard.png';
|
|
|
-// import iconAssignHomework from './image/icon-assignHomework.png';
|
|
|
-// import iconClose from './image/icon-close.png';
|
|
|
-// import iconOverPreivew from './image/icon-over-preview.png';
|
|
|
-import { Vue3Lottie } from 'vue3-lottie';
|
|
|
-import playLoadData from './datas/data.json';
|
|
|
-// import Moveable from 'moveable';
|
|
|
-import VideoPlay from './component/video-play';
|
|
|
-import {
|
|
|
- useMessage,
|
|
|
- NDrawer,
|
|
|
- NDrawerContent,
|
|
|
- NModal,
|
|
|
- NSpace,
|
|
|
- NButton,
|
|
|
- NCollapse,
|
|
|
- NCollapseItem,
|
|
|
- NTooltip
|
|
|
-} from 'naive-ui';
|
|
|
-import CardType from '@/components/card-type';
|
|
|
-import Pen from './component/tools/pen';
|
|
|
-import AudioPay from './component/audio-pay';
|
|
|
-import TrainSettings from './model/train-settings';
|
|
|
-import { useRoute } from 'vue-router';
|
|
|
-import {
|
|
|
- api_teacherChapterLessonCoursewareDetail,
|
|
|
- courseScheduleUpdate,
|
|
|
- lessonCoursewareDetail,
|
|
|
- lessonPreTrainingPage,
|
|
|
- queryCourseware
|
|
|
-} from '../prepare-lessons/api';
|
|
|
-import { vaildUrl } from '/src/utils/urlUtils';
|
|
|
-import TimerMeter from '/src/components/timerMeter';
|
|
|
-import Metronome from '/src/components/Metronome';
|
|
|
-import { iframeDislableKeyboard, px2vw } from '/src/utils';
|
|
|
-import PlaceholderTone from '/src/components/layout/modals/placeholderTone';
|
|
|
-import { state as globalState } from '/src/state';
|
|
|
-import Chapter from './model/chapter';
|
|
|
-import { useRouter } from 'vue-router';
|
|
|
-import { useUserStore } from '@/store/modules/users';
|
|
|
-import iconNote from './new-image/icon-note.png';
|
|
|
-import iconWhite from './new-image/icon-white.png';
|
|
|
-import timerMeterClose from './image/close.png';
|
|
|
-import rightIconEnd from './image/right_icon1.png';
|
|
|
-import rightIconArrange from './image/right_icon2.png';
|
|
|
-import rightIconPostil from './image/right_icon3.png';
|
|
|
-import rightIconWhiteboard from './image/right_icon4.png';
|
|
|
-import rightIconMetronome from './image/right_icon5.png';
|
|
|
-import rightIconTuner from './image/right_icon6.png';
|
|
|
-import rightIconTimer from './image/right_icon7.png';
|
|
|
-import rightIconCall from './image/right_icon10.png';
|
|
|
-import rightIconPackUp from './image/right_icon11.png';
|
|
|
-import leftIconPackUp from './image/right_icon8.png';
|
|
|
-import rightIconMusic from './image/right_icon9.png';
|
|
|
-import bottomIconSwitch from './image/bottom_icon1.png';
|
|
|
-import bottomIconResource from './image/bottom_icon2.png';
|
|
|
-import bottomIconPre from './image/bottom_icon3.png';
|
|
|
-import bottomIconNext from './image/bottom_icon4.png';
|
|
|
-import rightIconTool from './image/right_icon12.png';
|
|
|
-import rightHideIcon from './image/right_hide_icon.png';
|
|
|
-import leftHideIcon from './image/left_hide_icon.png';
|
|
|
-import SelectResources from '../prepare-lessons/model/select-resources';
|
|
|
-import { getStudentAfterWork, getStudentList } from '../studentList/api';
|
|
|
-import TheNoticeBar from '/src/components/TheNoticeBar';
|
|
|
-import ClassWork from './model/class-work';
|
|
|
-import SelectClass from './model/select-class';
|
|
|
-import SourceList from './model/source-list';
|
|
|
-import RhythmModal from './component/rhythm-modal';
|
|
|
-import InstruemntDetail from '/src/views/prepare-lessons/model/source-instrument/detail';
|
|
|
-import TheotyDetail from '/src/views/prepare-lessons/model/source-knowledge/detail';
|
|
|
-import MusicDetail from '/src/views/prepare-lessons/model/source-music/detail';
|
|
|
-import ListenModal from '/src/components/card-preview/listen-modal';
|
|
|
-import Train from '../prepare-lessons/components/lesson-main/train';
|
|
|
-import ResourceMain from '../prepare-lessons/components/resource-main';
|
|
|
-import { useResizeObserver } from '@vueuse/core';
|
|
|
-import { storage } from '/src/utils/storage';
|
|
|
-import { ACCESS_TOKEN_ADMIN } from '/src/store/mutation-types';
|
|
|
-import useDrag from '@/hooks/useDrag';
|
|
|
-import { getGuidanceShow } from '@/hooks/useDrag/useDragGuidance';
|
|
|
-import Dragbom from '@/hooks/useDrag/dragbom';
|
|
|
-import { api_cousseScheduleDetail } from '/src/api/user';
|
|
|
-
|
|
|
-export type ToolType = 'init' | 'pen' | 'whiteboard' | 'call';
|
|
|
-export type ToolItem = {
|
|
|
- type: ToolType;
|
|
|
- name: string;
|
|
|
- icon: string;
|
|
|
-};
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'CoursewarePlay',
|
|
|
- props: {
|
|
|
- type: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- },
|
|
|
- courseId: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- },
|
|
|
- instrumentId: {
|
|
|
- type: [String, Number],
|
|
|
- default: ''
|
|
|
- },
|
|
|
- // 教材编号
|
|
|
- lessonCourseId: {
|
|
|
- type: [String, Number],
|
|
|
- default: ''
|
|
|
- },
|
|
|
- detailId: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- },
|
|
|
- // 班级编号
|
|
|
- classGroupId: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- },
|
|
|
- // 上课记录编号
|
|
|
- classId: {
|
|
|
- type: String,
|
|
|
- defaault: ''
|
|
|
- },
|
|
|
- preStudentNum: {
|
|
|
- type: [String, Number],
|
|
|
- default: ''
|
|
|
- }
|
|
|
- },
|
|
|
- emits: ['close'],
|
|
|
- setup(props, { emit }) {
|
|
|
- const message = useMessage();
|
|
|
- const route = useRoute();
|
|
|
- const router = useRouter();
|
|
|
- const users = useUserStore();
|
|
|
- /** 设置播放容器 16:9 */
|
|
|
- const parentContainer = reactive({
|
|
|
- width: '100vw'
|
|
|
- });
|
|
|
- // const NPopoverRef = ref();
|
|
|
- // const setContainer = () => {
|
|
|
- // const min = Math.min(screen.width, screen.height);
|
|
|
- // const max = Math.max(screen.width, screen.height);
|
|
|
- // const width = min * (16 / 9);
|
|
|
- // if (width > max) {
|
|
|
- // parentContainer.width = '100vw';
|
|
|
- // return;
|
|
|
- // } else {
|
|
|
- // parentContainer.width = width + 'px';
|
|
|
- // }
|
|
|
- // };
|
|
|
- const handleInit = (type = 0) => {
|
|
|
- //设置容器16:9
|
|
|
- // setContainer();
|
|
|
- };
|
|
|
- handleInit();
|
|
|
- onUnmounted(() => {
|
|
|
- handleInit(1);
|
|
|
- });
|
|
|
-
|
|
|
- const data = reactive({
|
|
|
- type: 'class' as '' | 'preview' | 'class', // 预览类型
|
|
|
- courseId: '' as any, // 课件编号
|
|
|
- instrumentId: '' as any, // 声部编号
|
|
|
- lessonCourseId: '' as any, // 教材编号
|
|
|
- lessonCoursewareDetailId: '' as any, // 章节
|
|
|
- lessonCoursewareSubjectList: [] as any, // 教材上的声部
|
|
|
- detailId: '' as any, // 编号 - 课程编号
|
|
|
- classGroupId: '' as any, // 上课时需要 班级编号
|
|
|
- classId: '' as any, // 上课编号
|
|
|
- preStudentNum: '' as any, // 班上学生
|
|
|
- // detail: null,
|
|
|
- knowledgePointList: [] as any,
|
|
|
- itemList: [] as any,
|
|
|
- // showHead: true,
|
|
|
- // isCourse: false,
|
|
|
- // isRecordPlay: false,
|
|
|
- videoRefs: {} as any[],
|
|
|
- audioRefs: {} as any[],
|
|
|
- modelAttendStatus: false, // 布置作业提示弹窗
|
|
|
- modalAttendMessage: '本节课未设置课后作业,是否继续?',
|
|
|
- modelTrainStatus: false, // 训练设置
|
|
|
- selectClassStatus: false, // 选择课件
|
|
|
- homeworkStatus: true, // 布置作业完成时
|
|
|
- removeVisiable: false,
|
|
|
- nextEndShow: false,
|
|
|
- removeTitle: '',
|
|
|
- removeContent: '',
|
|
|
- removeCourseStatus: false, // 是否布置作业
|
|
|
-
|
|
|
- teacherChapterName: '',
|
|
|
- lessonPreTrainingId: null,
|
|
|
- selectResourceStatus: false,
|
|
|
- videoState: 'init' as 'init' | 'play',
|
|
|
- videoItemRef: null as any,
|
|
|
- animationState: 'start' as 'start' | 'end'
|
|
|
- });
|
|
|
- const activeData = reactive({
|
|
|
- isAutoPlay: false, // 是否自动播放
|
|
|
- nowTime: 0,
|
|
|
- model: true, // 遮罩
|
|
|
- isAnimation: true, // 是否动画
|
|
|
- // videoBtns: true, // 视频
|
|
|
- // currentTime: 0,
|
|
|
- // duration: 0,
|
|
|
- timer: null as any,
|
|
|
- item: null as any
|
|
|
- });
|
|
|
-
|
|
|
- // 键盘事件监听状态
|
|
|
- const listenerKeyUpState = ref(false);
|
|
|
-
|
|
|
- const getDetail = async () => {
|
|
|
- try {
|
|
|
- const res = await api_teacherChapterLessonCoursewareDetail(
|
|
|
- data.courseId
|
|
|
- );
|
|
|
-
|
|
|
- data.teacherChapterName = res.data.name || '';
|
|
|
- // 布置的作业编号
|
|
|
- data.lessonPreTrainingId = res.data.lessonPreTrainingId;
|
|
|
- // activeData.isAutoPlay = res.data.autoPlay || false; // 自动播放
|
|
|
- const tempRows = res.data.chapterKnowledgeList || [];
|
|
|
- const temp: any = [];
|
|
|
- const allItem: any = [];
|
|
|
- tempRows.forEach((row: any, index: number) => {
|
|
|
- if (!Array.isArray(row.chapterKnowledgeMaterialList)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- const childList: any[] = [];
|
|
|
- row.chapterKnowledgeMaterialList.forEach((child: any) => {
|
|
|
- if (!child.removeFlag) {
|
|
|
- childList.push({
|
|
|
- id: child.id,
|
|
|
- materialId: child.bizId,
|
|
|
- coverImg: child.bizInfo.coverImg,
|
|
|
- type: child.type,
|
|
|
- title: child.bizInfo.name,
|
|
|
- dataJson: child.dataJson,
|
|
|
- isCollect: !!child.favoriteFlag,
|
|
|
- isSelected: child.source === 'PLATFORM' ? true : false,
|
|
|
- content: child.bizInfo.content,
|
|
|
- parentIndex: index
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- temp.push({
|
|
|
- title: row.name,
|
|
|
- list: childList
|
|
|
- });
|
|
|
- allItem.push(...childList);
|
|
|
- });
|
|
|
-
|
|
|
- data.knowledgePointList = temp;
|
|
|
- data.itemList = allItem?.map((m: any) => {
|
|
|
- return {
|
|
|
- ...m,
|
|
|
- iframeRef: null,
|
|
|
- videoEle: null,
|
|
|
- audioEle: null,
|
|
|
- autoPlay: res.data.autoPlay || false, //加载完成是否自动播放
|
|
|
- isprepare: false, // 视频是否加载完成
|
|
|
- isRender: false // 是否渲染了
|
|
|
- };
|
|
|
- });
|
|
|
- setTimeout(() => {
|
|
|
- data.animationState = 'end';
|
|
|
- }, 500);
|
|
|
- } catch (e) {
|
|
|
- //
|
|
|
- console.log(e);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const showModalBeat = ref(false);
|
|
|
- const showModalTone = ref(false);
|
|
|
- const showModalTime = ref(false);
|
|
|
- // ifram事件处理
|
|
|
- const iframeHandle = (ev: MessageEvent) => {
|
|
|
- // console.log(ev.data?.api, ev.data, 'ev.data');
|
|
|
- if (ev.data?.api === 'headerTogge') {
|
|
|
- activeData.model =
|
|
|
- ev.data.show || (ev.data.playState == 'play' ? false : true);
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- if (ev.data?.api === 'onAttendToggleMenu') {
|
|
|
- activeData.model = !activeData.model;
|
|
|
- }
|
|
|
-
|
|
|
- if (ev.data?.api === 'api_fingerPreView') {
|
|
|
- clearInterval(activeData.timer);
|
|
|
- activeData.model = !ev.data.state;
|
|
|
- }
|
|
|
- //
|
|
|
- if (ev.data?.api === 'documentBodyKeyup') {
|
|
|
- if (ev.data?.code === 'ArrowUp') {
|
|
|
- setModalOpen();
|
|
|
- handlePreAndNext('up');
|
|
|
- }
|
|
|
-
|
|
|
- if (ev.data?.code === 'ArrowDown') {
|
|
|
- setModalOpen();
|
|
|
- handlePreAndNext('down');
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 点名返回
|
|
|
- if (ev.data?.api === 'callBack') {
|
|
|
- closeStudyTool();
|
|
|
- studyData.callShow = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (ev.data?.api === 'onLogin') {
|
|
|
- const documentDom: any = document;
|
|
|
- documentDom.exitFullscreen
|
|
|
- ? documentDom.exitFullscreen()
|
|
|
- : documentDom.mozCancelFullScreen
|
|
|
- ? documentDom.mozCancelFullScreen()
|
|
|
- : documentDom.webkitExitFullscreen
|
|
|
- ? documentDom.webkitExitFullscreen()
|
|
|
- : '';
|
|
|
- users.logout();
|
|
|
- router.replace('/login');
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- onMounted(async () => {
|
|
|
- // initMoveable();
|
|
|
- const query = route.query;
|
|
|
- // console.log(query, props.preStudentNum, '学生人数');
|
|
|
- // 先取参数,
|
|
|
- data.type = props.type || (query.type as any);
|
|
|
- data.courseId = props.courseId || query.courseId;
|
|
|
- data.instrumentId = props.instrumentId || query.instrumentId;
|
|
|
- data.detailId = props.detailId || query.detailId;
|
|
|
- data.lessonCourseId = props.lessonCourseId || query.lessonCourseId;
|
|
|
- data.classGroupId = props.classGroupId || query.classGroupId;
|
|
|
- data.classId = props.classId || query.classId;
|
|
|
- data.preStudentNum = props.preStudentNum || query.preStudentNum;
|
|
|
- window.addEventListener('message', iframeHandle);
|
|
|
-
|
|
|
- if (data.classId) {
|
|
|
- const res = await api_cousseScheduleDetail(data.classId);
|
|
|
- data.courseId = res.data.useChapterLessonCoursewareId;
|
|
|
- }
|
|
|
-
|
|
|
- getDetail();
|
|
|
- getLessonCoursewareDetail();
|
|
|
- if (data.type === 'preview') {
|
|
|
- // 预览隐藏点名和布置作业
|
|
|
- const hideListIds = [2, 10];
|
|
|
- let index = rightList.length - 1;
|
|
|
- while (index >= 0) {
|
|
|
- if (hideListIds.includes(rightList[index].id)) {
|
|
|
- console.log(index);
|
|
|
- rightList.splice(index, 1);
|
|
|
- }
|
|
|
- index--;
|
|
|
- }
|
|
|
- }
|
|
|
- rollCallStudentList();
|
|
|
- });
|
|
|
-
|
|
|
- // const onFullScreen = () => {
|
|
|
- // if (data.type === 'preview') {
|
|
|
- // const el: any = document.querySelector('#app');
|
|
|
-
|
|
|
- // if (el.mozRequestFullScreen) {
|
|
|
- // el.mozRequestFullScreen();
|
|
|
- // } else if (el.webkitRequestFullscreen) {
|
|
|
- // el.webkitRequestFullscreen();
|
|
|
- // } else if (el.requestFullScreen) {
|
|
|
- // el.requestFullscreen();
|
|
|
- // }
|
|
|
- // }
|
|
|
- // };
|
|
|
-
|
|
|
- const popupData = reactive({
|
|
|
- open: false,
|
|
|
- activeIndex: 0,
|
|
|
- courseActiveIndex: 0, // 课件选择的第几个
|
|
|
- toolOpen: false, // 工具弹窗控制
|
|
|
- chapterOpen: false, // 切换章节
|
|
|
- chapterDetails: [] as any,
|
|
|
- courseId: null as any, // 章节编号
|
|
|
- chapterLoading: false // 加载数据
|
|
|
- });
|
|
|
-
|
|
|
- watch(
|
|
|
- () => [popupData.open, popupData.chapterOpen],
|
|
|
- val => {
|
|
|
- // 为了处理window电脑滑动时的问题 - pointr-events
|
|
|
- setTimeout(() => {
|
|
|
- const drawers = document.querySelectorAll('.n-drawer-container');
|
|
|
- if (val[0] || val[1]) {
|
|
|
- drawers?.forEach(drawer => {
|
|
|
- drawer.classList.remove('n-drawer-container-relative');
|
|
|
- });
|
|
|
- } else {
|
|
|
- drawers?.forEach(drawer => {
|
|
|
- drawer.classList.add('n-drawer-container-relative');
|
|
|
- });
|
|
|
- }
|
|
|
- }, 200);
|
|
|
- }
|
|
|
- );
|
|
|
- const formatParentId = (id: any, list: any, ids = [] as any) => {
|
|
|
- for (const item of list) {
|
|
|
- if (item.knowledgeList && item.knowledgeList.length > 0) {
|
|
|
- const cIds: any = formatParentId(id, item.knowledgeList, [
|
|
|
- ...ids,
|
|
|
- item.id
|
|
|
- ]);
|
|
|
- if (cIds.includes(id)) {
|
|
|
- return cIds;
|
|
|
- }
|
|
|
- }
|
|
|
- if (item.id === id) {
|
|
|
- return [...ids, id];
|
|
|
- }
|
|
|
- }
|
|
|
- return ids;
|
|
|
- };
|
|
|
-
|
|
|
- /** 获取章节 */
|
|
|
- const getLessonCoursewareDetail = async () => {
|
|
|
- try {
|
|
|
- const res = await lessonCoursewareDetail({
|
|
|
- id: data.lessonCourseId,
|
|
|
- instrumentId: data.instrumentId
|
|
|
- });
|
|
|
-
|
|
|
- popupData.chapterDetails = res.data.lessonList || [];
|
|
|
-
|
|
|
- const ids = formatParentId(data.detailId, popupData.chapterDetails);
|
|
|
- data.lessonCoursewareDetailId = ids[0];
|
|
|
- console.log(res.data, 'data');
|
|
|
- data.lessonCoursewareSubjectList = res.data.instrumentList || [];
|
|
|
- } catch {
|
|
|
- //
|
|
|
- }
|
|
|
- };
|
|
|
- /** 更新上课记录 */
|
|
|
- const classCourseScheduleUpdate = async () => {
|
|
|
- try {
|
|
|
- if (!data.classId) return;
|
|
|
- await courseScheduleUpdate({
|
|
|
- lessonCoursewareKnowledgeDetailId: data.detailId,
|
|
|
- id: data.classId
|
|
|
- });
|
|
|
- } catch {
|
|
|
- //
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const activeName = computed(() => {
|
|
|
- let name = '';
|
|
|
- popupData.chapterDetails.forEach((chapter: any) => {
|
|
|
- if (chapter.id === data.lessonCoursewareDetailId) {
|
|
|
- // name = chapter.name;
|
|
|
- chapter.knowledgeList?.forEach((know: any) => {
|
|
|
- if (know.id === data.detailId) {
|
|
|
- name = know.name;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- return name;
|
|
|
- });
|
|
|
-
|
|
|
- /**停止所有的播放 */
|
|
|
- const handleStop = (isStop = true) => {
|
|
|
- // console.log(isStop, 'stop');
|
|
|
- for (let i = 0; i < data.itemList.length; i++) {
|
|
|
- const activeItem = data.itemList[i];
|
|
|
- if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
|
|
|
- try {
|
|
|
- if (isStop) {
|
|
|
- activeItem.videoEle?.currentTime(0);
|
|
|
- }
|
|
|
- activeItem.videoEle?.pause();
|
|
|
- } catch (e: any) {
|
|
|
- // console.log(e, 'e');
|
|
|
- }
|
|
|
- }
|
|
|
- if (activeItem.type === 'SONG' && activeItem.audioEle) {
|
|
|
- activeItem.audioEle?.stop();
|
|
|
- }
|
|
|
- // console.log('🚀 ~ activeItem:', activeItem)
|
|
|
- // 停止曲谱的播放
|
|
|
- if (activeItem.type === 'MUSIC') {
|
|
|
- activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
- { api: 'setPlayState' },
|
|
|
- '*'
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- if (
|
|
|
- activeItem.type === 'INSTRUMENT' ||
|
|
|
- activeItem.type === 'MUSICIAN' ||
|
|
|
- activeItem.type === 'MUSIC_WIKI'
|
|
|
- ) {
|
|
|
- activeItem.iframeRef?.handleChangeAudio('pause');
|
|
|
- }
|
|
|
-
|
|
|
- // console.log(activeItem.type, 'activeItem.type');
|
|
|
- if (activeItem.type === 'RHYTHM') {
|
|
|
- activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
- { api: 'setPlayState', data: false },
|
|
|
- '*'
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- if (activeItem.type === 'LISTEN') {
|
|
|
- activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
- { api: 'setPlayState' },
|
|
|
- '*'
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- // 切换素材
|
|
|
- const toggleMaterial = (itemActive: any) => {
|
|
|
- const index = data.itemList.findIndex((n: any) => n.id == itemActive);
|
|
|
- if (index > -1) {
|
|
|
- handleSwipeChange(index);
|
|
|
- }
|
|
|
- };
|
|
|
- /** 延迟收起模态框 */
|
|
|
- const setModelOpen = () => {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- message.destroyAll();
|
|
|
- activeData.timer = setTimeout(() => {
|
|
|
- activeData.model = false;
|
|
|
- Object.values(data.videoRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(false)
|
|
|
- );
|
|
|
-
|
|
|
- Object.values(data.audioRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(false)
|
|
|
- );
|
|
|
- }, 4000);
|
|
|
- };
|
|
|
-
|
|
|
- /** 立即收起所有的模态框 */
|
|
|
- const clearModel = () => {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- message.destroyAll();
|
|
|
- activeData.model = false;
|
|
|
- Object.values(data.videoRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(false)
|
|
|
- );
|
|
|
- Object.values(data.audioRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(false)
|
|
|
- );
|
|
|
- };
|
|
|
- const toggleModel = (type = true) => {
|
|
|
- activeData.model = type;
|
|
|
- Object.values(data.videoRefs).map((n: any) => n?.toggleHideControl(type));
|
|
|
- Object.values(data.audioRefs).map((n: any) => n?.toggleHideControl(type));
|
|
|
- };
|
|
|
-
|
|
|
- // 双击
|
|
|
- const handleDbClick = (item: any) => {
|
|
|
- if (item && item.type === 'VIDEO') {
|
|
|
- const videoEle: HTMLVideoElement = item.videoEle;
|
|
|
- if (videoEle) {
|
|
|
- if (videoEle.paused) {
|
|
|
- message.destroyAll();
|
|
|
- videoEle.play();
|
|
|
- } else {
|
|
|
- message.warning('已暂停');
|
|
|
- videoEle.pause();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // ppt iframe 点击事件
|
|
|
- // const iframeClick = () => {
|
|
|
- // if(document.all) {
|
|
|
- // document.getElementById("iframe-ppt")?.attachEvent("click", () => {
|
|
|
- // activeData.model = !activeData.model
|
|
|
- // });
|
|
|
- // } else {
|
|
|
- // document.getElementById("iframe-ppt")?.contentWindow?.postMessage({
|
|
|
- // api: 'onAttendToggleMenu'
|
|
|
- // }, '*');
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // 切换播放
|
|
|
- // const togglePlay = (m: any, isPlay: boolean) => {
|
|
|
- // if (isPlay) {
|
|
|
- // m.videoEle?.play();
|
|
|
- // } else {
|
|
|
- // m.videoEle?.pause();
|
|
|
- // }
|
|
|
- // };
|
|
|
-
|
|
|
- // const showIndex = ref(-4);
|
|
|
- const effectIndex = ref(3);
|
|
|
- const effects = [
|
|
|
- {
|
|
|
- prev: {
|
|
|
- transform: 'translate3d(0, 0, -800px) rotateX(180deg)'
|
|
|
- },
|
|
|
- next: {
|
|
|
- transform: 'translate3d(0, 0, -800px) rotateX(-180deg)'
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- prev: {
|
|
|
- transform: 'translate3d(-100%, 0, -800px)'
|
|
|
- },
|
|
|
- next: {
|
|
|
- transform: 'translate3d(100%, 0, -800px)'
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- prev: {
|
|
|
- transform: 'translate3d(-50%, 0, -800px) rotateY(80deg)'
|
|
|
- },
|
|
|
- next: {
|
|
|
- transform: 'translate3d(50%, 0, -800px) rotateY(-80deg)'
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- prev: {
|
|
|
- transform: 'translate3d(-100%, 0, -800px) rotateY(-120deg)'
|
|
|
- },
|
|
|
- next: {
|
|
|
- transform: 'translate3d(100%, 0, -800px) rotateY(120deg)'
|
|
|
- }
|
|
|
- },
|
|
|
- // 风车4
|
|
|
- {
|
|
|
- prev: {
|
|
|
- transform: 'translate3d(-50%, 50%, -800px) rotateZ(-14deg)',
|
|
|
- opacity: 0
|
|
|
- },
|
|
|
- next: {
|
|
|
- transform: 'translate3d(50%, 50%, -800px) rotateZ(14deg)',
|
|
|
- opacity: 0
|
|
|
- }
|
|
|
- },
|
|
|
- // 翻页5
|
|
|
- {
|
|
|
- prev: {
|
|
|
- transform: 'translateZ(-800px) rotate3d(0, -1, 0, 90deg)',
|
|
|
- opacity: 0
|
|
|
- },
|
|
|
- next: {
|
|
|
- transform: 'translateZ(-800px) rotate3d(0, 1, 0, 90deg)',
|
|
|
- opacity: 0
|
|
|
- },
|
|
|
- current: { transitionDelay: '700ms' }
|
|
|
- }
|
|
|
- ];
|
|
|
-
|
|
|
- const acitveTimer = ref();
|
|
|
- // 轮播切换
|
|
|
- const handleSwipeChange = (index: number) => {
|
|
|
- // 如果是当前正在播放 或者是视频最后一个
|
|
|
- if (popupData.activeIndex == index) return;
|
|
|
- data.animationState = 'start';
|
|
|
- data.videoState = 'init';
|
|
|
- handleStop();
|
|
|
- clearTimeout(acitveTimer.value);
|
|
|
- activeData.model = true;
|
|
|
- checkedAnimation(popupData.activeIndex, index);
|
|
|
- popupData.activeIndex = index;
|
|
|
-
|
|
|
- // 处理资源列表滚动
|
|
|
- nextTick(() => {
|
|
|
- scrollResourceSection();
|
|
|
- });
|
|
|
-
|
|
|
- acitveTimer.value = setTimeout(
|
|
|
- () => {
|
|
|
- const item = data.itemList[index];
|
|
|
-
|
|
|
- if (item) {
|
|
|
- if (item.type == 'MUSIC') {
|
|
|
- activeData.model = true;
|
|
|
- }
|
|
|
- if (item.type === 'SONG') {
|
|
|
- // 自动播放下一个音频
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- message.destroyAll();
|
|
|
- // item.autoPlay = false;
|
|
|
- // nextTick(() => {
|
|
|
- // item.audioEle?.onPlay();
|
|
|
- // });
|
|
|
- }
|
|
|
- if (item.type === 'VIDEO') {
|
|
|
- // 自动播放下一个视频
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- message.destroyAll();
|
|
|
- nextTick(() => {
|
|
|
- if (item.error) {
|
|
|
- // console.log(item, 'item error');
|
|
|
- item.videoEle?.src(item.content);
|
|
|
- item.error = false;
|
|
|
- // item.videoEle?.onPlay();
|
|
|
- }
|
|
|
- data.animationState = 'end';
|
|
|
- });
|
|
|
- }
|
|
|
- if (item.type === 'PPT') {
|
|
|
- //
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- activeData.isAnimation ? 800 : 0
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- /** 是否有转场动画 */
|
|
|
- const checkedAnimation = (index: number, nextIndex?: number) => {
|
|
|
- const item = data.itemList[index];
|
|
|
- const nextItem = data.itemList[nextIndex!];
|
|
|
- if (nextItem) {
|
|
|
- if (nextItem.knowledgePointId != item.knowledgePointId) {
|
|
|
- activeData.isAnimation = true;
|
|
|
- return;
|
|
|
- }
|
|
|
- const videoEle = item.videoEle;
|
|
|
- const nextVideo = nextItem.videoEle;
|
|
|
- if (videoEle && videoEle.duration < 8 && index < nextIndex!) {
|
|
|
- activeData.isAnimation = false;
|
|
|
- } else if (nextVideo && nextVideo.duration < 8 && index > nextIndex!) {
|
|
|
- activeData.isAnimation = false;
|
|
|
- } else {
|
|
|
- activeData.isAnimation = true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- activeData.isAnimation = item?.adviseStudyTimeSecond < 8 ? false : true;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 上一个知识点, 下一个知识点
|
|
|
- const handlePreAndNext = async (type: string) => {
|
|
|
- if (type === 'up') {
|
|
|
- // 判断上面是否还有章节
|
|
|
- if (popupData.activeIndex > 0) {
|
|
|
- handleSwipeChange(popupData.activeIndex - 1);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 获取当前是哪个章节
|
|
|
- let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
- (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
- );
|
|
|
- const detailItem =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let lessonIndex = detailItem.findIndex(
|
|
|
- (item: any) => item.id == data.detailId
|
|
|
- );
|
|
|
-
|
|
|
- let lessonStatus = false; // 当前章节上面是否有内容
|
|
|
- let lessonCoursewareDetailId = '';
|
|
|
- let coursewareDetailKnowledgeId = '';
|
|
|
- while (lessonIndex >= 0) {
|
|
|
- lessonIndex--;
|
|
|
-
|
|
|
- if (lessonIndex >= 0) {
|
|
|
- if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
- lessonStatus = true;
|
|
|
- lessonCoursewareDetailId =
|
|
|
- detailItem[lessonIndex].lessonCoursewareDetailId;
|
|
|
- coursewareDetailKnowledgeId = detailItem[lessonIndex].id;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (lessonStatus) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
- if (lessonStatus) {
|
|
|
- popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
- data.selectClassStatus = true;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- let prevLessonStatus = false;
|
|
|
- while (detailIndex >= 0) {
|
|
|
- detailIndex--;
|
|
|
- const tempDetail =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let tempLessonLength = tempDetail.length;
|
|
|
- while (tempLessonLength > 0) {
|
|
|
- if (tempDetail[tempLessonLength - 1].coursewareNum > 0) {
|
|
|
- prevLessonStatus = true;
|
|
|
- lessonCoursewareDetailId =
|
|
|
- tempDetail[tempLessonLength - 1].lessonCoursewareDetailId;
|
|
|
- coursewareDetailKnowledgeId = tempDetail[tempLessonLength - 1].id;
|
|
|
- }
|
|
|
- tempLessonLength--;
|
|
|
- if (prevLessonStatus) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (prevLessonStatus) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
- if (prevLessonStatus) {
|
|
|
- popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
- data.selectClassStatus = true;
|
|
|
- return;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (popupData.activeIndex < data.itemList.length - 1) {
|
|
|
- handleSwipeChange(popupData.activeIndex + 1);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (!isDownArrow.value) return;
|
|
|
- data.nextEndShow = true;
|
|
|
- }
|
|
|
- };
|
|
|
- // 当前课件结束之后选择下一个课件
|
|
|
- function handleNextEnd() {
|
|
|
- // 获取当前是哪个章节
|
|
|
- let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
- (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
- );
|
|
|
- const detailItem =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let lessonIndex = detailItem.findIndex(
|
|
|
- (item: any) => item.id == data.detailId
|
|
|
- );
|
|
|
-
|
|
|
- let lessonStatus = false; // 当前章节下面是否有内容
|
|
|
- let lessonCoursewareDetailId = '';
|
|
|
- let coursewareDetailKnowledgeId = '';
|
|
|
- while (lessonIndex < detailItem.length - 1) {
|
|
|
- lessonIndex++;
|
|
|
- if (lessonIndex >= 0) {
|
|
|
- if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
- lessonStatus = true;
|
|
|
- lessonCoursewareDetailId =
|
|
|
- detailItem[lessonIndex].lessonCoursewareDetailId;
|
|
|
- coursewareDetailKnowledgeId = detailItem[lessonIndex].id;
|
|
|
- }
|
|
|
- }
|
|
|
- if (lessonStatus) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- // 判断当前章节下面课程是否有内容,否则往下一个章节走
|
|
|
- if (lessonStatus) {
|
|
|
- popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
- data.selectClassStatus = true;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- let nextLessonStatus = false;
|
|
|
- while (detailIndex <= popupData.chapterDetails.length - 1) {
|
|
|
- detailIndex++;
|
|
|
- const tempDetail =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let tempLessonLength = 0;
|
|
|
- while (tempLessonLength <= tempDetail.length - 1) {
|
|
|
- if (tempDetail[tempLessonLength].coursewareNum > 0) {
|
|
|
- nextLessonStatus = true;
|
|
|
- lessonCoursewareDetailId =
|
|
|
- tempDetail[tempLessonLength].lessonCoursewareDetailId;
|
|
|
- coursewareDetailKnowledgeId = tempDetail[tempLessonLength].id;
|
|
|
- }
|
|
|
- tempLessonLength++;
|
|
|
- if (nextLessonStatus) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (nextLessonStatus) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
- if (nextLessonStatus) {
|
|
|
- popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
- data.selectClassStatus = true;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- /** 弹窗关闭 */
|
|
|
- const handleClosePopup = () => {
|
|
|
- const item = data.itemList[popupData.activeIndex];
|
|
|
- if (item?.type == 'VIDEO' && !item.videoEle?.paused) {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
-
|
|
|
- if (item?.type == 'SONG' && !item.audioEle?.paused) {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
- };
|
|
|
- document.body.addEventListener('keyup', (e: KeyboardEvent) => {
|
|
|
- if (e.code === 'ArrowUp') {
|
|
|
- // if (popupData.activeIndex === 0) return;
|
|
|
- setModalOpen();
|
|
|
- handlePreAndNext('up');
|
|
|
- } else if (e.code === 'ArrowDown') {
|
|
|
- // if (popupData.activeIndex === data.itemList.length - 1) return;
|
|
|
- setModalOpen();
|
|
|
- handlePreAndNext('down');
|
|
|
- } else if (e.code === 'Space') {
|
|
|
- // const activeItem = data.itemList[popupData.activeIndex];
|
|
|
- // console.log(activeItem, activeItem.videoEle);
|
|
|
- // // 暂停视频和曲谱的播放
|
|
|
- // if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
|
|
|
- // activeItem.videoEle?.play();
|
|
|
- // }
|
|
|
- // if (activeItem.type === 'SONG' && activeItem.audioEle) {
|
|
|
- // activeItem.audioEle?.play();
|
|
|
- // }
|
|
|
- // if (activeItem.type === 'MUSIC') {
|
|
|
- // activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
- // { api: 'setPlayState' },
|
|
|
- // '*'
|
|
|
- // );
|
|
|
- // }
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // const toggleListenerKeyUp = (type: string) => {
|
|
|
- // if (type === 'remove') {
|
|
|
- // document.body.removeEventListener('keyup', () => {
|
|
|
- // listenerKeyUpState.value = false;
|
|
|
- // });
|
|
|
- // } else {
|
|
|
- // // 监听页面键盘事件 - 上下切换
|
|
|
- // document.body.addEventListener('keyup', (e: KeyboardEvent) => {
|
|
|
- // // console.log(e, 'e');
|
|
|
- // if (e.code === 'ArrowLeft') {
|
|
|
- // // if (popupData.activeIndex === 0) return;
|
|
|
- // setModalOpen();
|
|
|
- // handlePreAndNext('up');
|
|
|
- // } else if (e.code === 'ArrowRight') {
|
|
|
- // // if (popupData.activeIndex === data.itemList.length - 1) return;
|
|
|
- // setModalOpen();
|
|
|
- // handlePreAndNext('down');
|
|
|
- // }
|
|
|
- // });
|
|
|
- // listenerKeyUpState.value = true;
|
|
|
- // }
|
|
|
- // };
|
|
|
-
|
|
|
- // 监听切换到ppt课件时,手动移除键盘监听器
|
|
|
- // watch(() => popupData.activeIndex, () => {
|
|
|
- // const activeItem = data.itemList[popupData.activeIndex];
|
|
|
- // if (activeItem?.type === 'PPT') {
|
|
|
- // toggleListenerKeyUp('remove')
|
|
|
- // } else {
|
|
|
- // !listenerKeyUpState.value && toggleListenerKeyUp('add')
|
|
|
- // }
|
|
|
- // })
|
|
|
- watch(
|
|
|
- () => popupData.activeIndex,
|
|
|
- () => {
|
|
|
- const item = data.itemList[popupData.activeIndex];
|
|
|
- popupData.courseActiveIndex = item.parentIndex;
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- const setModalOpen = (status = true) => {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- activeData.model = status;
|
|
|
- Object.values(data.videoRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(status)
|
|
|
- );
|
|
|
- Object.values(data.audioRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(status)
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- /** 教学数据 */
|
|
|
- const studyData = reactive({
|
|
|
- type: '' as ToolType,
|
|
|
- penShow: false,
|
|
|
- whiteboardShow: false,
|
|
|
- callShow: false,
|
|
|
- callStudentList: [] as any // 学生列表
|
|
|
- });
|
|
|
-
|
|
|
- /** 打开教学工具 */
|
|
|
- const openStudyTool = (item: ToolItem) => {
|
|
|
- handleStop(false);
|
|
|
- clearModel();
|
|
|
- popupData.toolOpen = false;
|
|
|
- studyData.type = item.type;
|
|
|
-
|
|
|
- switch (item.type) {
|
|
|
- case 'pen':
|
|
|
- studyData.penShow = true;
|
|
|
- break;
|
|
|
- case 'whiteboard':
|
|
|
- studyData.whiteboardShow = true;
|
|
|
- break;
|
|
|
- case 'call':
|
|
|
- studyData.callShow = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- /** 关闭教学工具 */
|
|
|
- const closeStudyTool = () => {
|
|
|
- studyData.type = 'init';
|
|
|
- toggleModel();
|
|
|
- setModelOpen();
|
|
|
- };
|
|
|
-
|
|
|
- const startShowModal = (
|
|
|
- val: 'setTimeIcon' | 'beatIcon' | 'toneIcon' | 'iconNote2'
|
|
|
- ) => {
|
|
|
- if (val == 'setTimeIcon') {
|
|
|
- showModalTime.value = true;
|
|
|
- }
|
|
|
- if (val == 'beatIcon') {
|
|
|
- showModalBeat.value = true;
|
|
|
- }
|
|
|
- if (val == 'toneIcon') {
|
|
|
- showModalTone.value = true;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 是否允许上一页
|
|
|
- const isUpArrow = computed(() => {
|
|
|
- /**
|
|
|
- * 1,判断当前课程中是否处在第一个资源;
|
|
|
- * 2,判断当前课程是否在当前章节的第一个;
|
|
|
- * 3,判断当前章节,当前课程上面还没有其它课程,是否有资源;
|
|
|
- * 4,判断当前章节上面还没有其它章节;
|
|
|
- * 5,判断上面章节里面课程是否有资源;
|
|
|
- */
|
|
|
- if (popupData.activeIndex > 0) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // 获取当前是哪个章节
|
|
|
- let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
- (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
- );
|
|
|
- const detailItem =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let lessonIndex = detailItem.findIndex(
|
|
|
- (item: any) => item.id == data.detailId
|
|
|
- );
|
|
|
-
|
|
|
- // 说明已经是第一单元,第一课
|
|
|
- if (detailIndex <= 0 && lessonIndex <= 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- let lessonStatus = false; // 当前章节上面是否有内容
|
|
|
- while (lessonIndex >= 0) {
|
|
|
- lessonIndex--;
|
|
|
-
|
|
|
- if (lessonIndex >= 0) {
|
|
|
- if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
- lessonStatus = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
- if (lessonStatus) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // 已经是第一个章节了
|
|
|
- if (detailIndex <= 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- let prevLessonStatus = false;
|
|
|
- while (detailIndex >= 0) {
|
|
|
- detailIndex--;
|
|
|
- const tempDetail =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let tempLessonLength = tempDetail.length;
|
|
|
- while (tempLessonLength > 0) {
|
|
|
- if (tempDetail[tempLessonLength - 1].coursewareNum > 0) {
|
|
|
- prevLessonStatus = true;
|
|
|
- }
|
|
|
- tempLessonLength--;
|
|
|
- }
|
|
|
-
|
|
|
- if (prevLessonStatus) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- });
|
|
|
-
|
|
|
- // 是否允许下一页
|
|
|
- const isDownArrow = computed(() => {
|
|
|
- if (popupData.activeIndex < data.itemList.length - 1) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // 获取当前是哪个章节
|
|
|
- let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
- (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
- );
|
|
|
-
|
|
|
- const detailItem =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let lessonIndex = detailItem.findIndex(
|
|
|
- (item: any) => item.id == data.detailId
|
|
|
- );
|
|
|
-
|
|
|
- // 说明已经是最后-单元,最后一课
|
|
|
- if (
|
|
|
- detailIndex >= popupData.chapterDetails.length - 1 &&
|
|
|
- lessonIndex >= detailItem.length - 1
|
|
|
- ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- let lessonStatus = false; // 当前章节下面是否有内容
|
|
|
- while (lessonIndex < detailItem.length - 1) {
|
|
|
- lessonIndex++;
|
|
|
- if (lessonIndex >= 0) {
|
|
|
- if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
- lessonStatus = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 判断当前章节下面课程是否有内容,否则往下一个章节走
|
|
|
- if (lessonStatus) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // 已经是最后一个章节了
|
|
|
- if (detailIndex >= popupData.chapterDetails.length - 1) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- let nextLessonStatus = false;
|
|
|
- while (detailIndex < popupData.chapterDetails.length - 1) {
|
|
|
- detailIndex++;
|
|
|
- const tempDetail =
|
|
|
- popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
- let tempLessonLength = 0;
|
|
|
- while (tempLessonLength <= tempDetail.length - 1) {
|
|
|
- if (tempDetail[tempLessonLength].coursewareNum > 0) {
|
|
|
- nextLessonStatus = true;
|
|
|
- }
|
|
|
- tempLessonLength++;
|
|
|
- }
|
|
|
-
|
|
|
- if (nextLessonStatus) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- });
|
|
|
- const activeVideoItem = computed(() => {
|
|
|
- const item = data.itemList[popupData.activeIndex];
|
|
|
- if (item && item.type && item.type.toLocaleUpperCase() === 'VIDEO') {
|
|
|
- return item;
|
|
|
- }
|
|
|
- return {};
|
|
|
- });
|
|
|
-
|
|
|
- // 右侧菜单栏
|
|
|
- const rightList = reactive([
|
|
|
- {
|
|
|
- name: '上一个',
|
|
|
- icon: bottomIconPre,
|
|
|
- id: 11
|
|
|
- },
|
|
|
- {
|
|
|
- name: '下一个',
|
|
|
- icon: bottomIconNext,
|
|
|
- id: 12
|
|
|
- },
|
|
|
- {
|
|
|
- name: '切换章节',
|
|
|
- icon: bottomIconSwitch,
|
|
|
- id: 13
|
|
|
- },
|
|
|
- {
|
|
|
- name: '资源列表',
|
|
|
- icon: bottomIconResource,
|
|
|
- id: 14
|
|
|
- },
|
|
|
- {
|
|
|
- name: '曲目资源',
|
|
|
- icon: rightIconMusic,
|
|
|
- id: 9
|
|
|
- },
|
|
|
- {
|
|
|
- name: '点名',
|
|
|
- icon: rightIconCall,
|
|
|
- id: 10
|
|
|
- },
|
|
|
- {
|
|
|
- name: '布置作业',
|
|
|
- icon: rightIconArrange,
|
|
|
- id: 2
|
|
|
- },
|
|
|
- {
|
|
|
- name: '工具箱',
|
|
|
- icon: rightIconTool,
|
|
|
- id: 15
|
|
|
- },
|
|
|
- {
|
|
|
- name: '结束课程',
|
|
|
- name2: '结束预览',
|
|
|
- icon: rightIconEnd,
|
|
|
- id: 1
|
|
|
- },
|
|
|
- {
|
|
|
- name: '收起',
|
|
|
- icon: leftIconPackUp,
|
|
|
- id: 8
|
|
|
- }
|
|
|
- ]);
|
|
|
- const tooltipList = [
|
|
|
- {
|
|
|
- name: '节拍器',
|
|
|
- icon: rightIconMetronome,
|
|
|
- id: 5
|
|
|
- },
|
|
|
- {
|
|
|
- name: '计时器',
|
|
|
- icon: rightIconTimer,
|
|
|
- id: 7
|
|
|
- },
|
|
|
- {
|
|
|
- name: '批注',
|
|
|
- icon: rightIconPostil,
|
|
|
- id: 3
|
|
|
- },
|
|
|
- {
|
|
|
- name: '白板',
|
|
|
- icon: rightIconWhiteboard,
|
|
|
- id: 4
|
|
|
- }
|
|
|
- // {
|
|
|
- // name: '调音器',
|
|
|
- // icon: rightIconTuner,
|
|
|
- // id: 6
|
|
|
- // }
|
|
|
- ];
|
|
|
- // 默认收起菜单
|
|
|
- const columnShow = ref(true);
|
|
|
- // 菜单位置
|
|
|
- const columnPos = ref<'left' | 'right'>('left');
|
|
|
- watch(columnPos, () => {
|
|
|
- for (let i = 0; i < data.itemList.length; i++) {
|
|
|
- const activeItem = data.itemList[i];
|
|
|
- if (['RHYTHM', 'MUSIC'].includes(activeItem.type)) {
|
|
|
- activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
- { api: 'imagePos', data: columnPos.value },
|
|
|
- '*'
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- // 右边栏操作
|
|
|
- const operateRightBtn = async (id: number) => {
|
|
|
- if (![8, 11, 12, 13, 14].includes(id)) {
|
|
|
- handleStop(false);
|
|
|
- }
|
|
|
-
|
|
|
- switch (id) {
|
|
|
- case 1:
|
|
|
- if (data.type === 'preview') {
|
|
|
- data.removeVisiable = true;
|
|
|
- data.removeTitle = '结束预览';
|
|
|
- data.removeContent = '请确认是否结束预览?';
|
|
|
- } else {
|
|
|
- const res = await getStudentAfterWork({
|
|
|
- courseScheduleId: data.classId,
|
|
|
- page: 1,
|
|
|
- rows: 99
|
|
|
- });
|
|
|
- if (res.data.rows && res.data.rows.length) {
|
|
|
- data.removeContent = '请确认是否结束课程?';
|
|
|
- data.removeCourseStatus = false;
|
|
|
- } else {
|
|
|
- data.removeContent = '本次课堂尚未布置作业,是否结束课程?';
|
|
|
- data.removeCourseStatus = true;
|
|
|
- }
|
|
|
- data.removeVisiable = true;
|
|
|
- data.removeTitle = '结束课程';
|
|
|
- }
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- // 学生人数必须大于0,才可以布置作业
|
|
|
- if (data.preStudentNum <= 0) return;
|
|
|
- // const res = await lessonPreTrainingPage({
|
|
|
- // coursewareKnowledgeDetailId: data.detailId,
|
|
|
- // instrumentId: data.instrumentId,
|
|
|
- // page: 1,
|
|
|
- // rows: 99
|
|
|
- // });
|
|
|
- // if (res.data.rows && res.data.rows.length) {
|
|
|
- // data.modalAttendMessage = '本节课已设置课后作业,是否布置?';
|
|
|
- // }
|
|
|
- // data.modelAttendStatus = true;
|
|
|
- const res = await getStudentAfterWork({
|
|
|
- courseScheduleId: data.classId,
|
|
|
- page: 1,
|
|
|
- rows: 99
|
|
|
- });
|
|
|
- if (res.data.rows && res.data.rows.length) {
|
|
|
- // data.modalAttendMessage = '请确认是否结束课程?';
|
|
|
- data.modalAttendMessage = '本次课程已布置作业,是否继续?';
|
|
|
- data.modelAttendStatus = true;
|
|
|
- } else {
|
|
|
- data.modelTrainStatus = true;
|
|
|
- nextTick(() => {
|
|
|
- getModalHeight();
|
|
|
- });
|
|
|
- data.modelAttendStatus = false;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- openStudyTool({
|
|
|
- type: 'pen',
|
|
|
- icon: iconNote,
|
|
|
- name: '批注'
|
|
|
- });
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- openStudyTool({
|
|
|
- type: 'whiteboard',
|
|
|
- icon: iconWhite,
|
|
|
- name: '白板'
|
|
|
- });
|
|
|
- break;
|
|
|
- case 5:
|
|
|
- startShowModal('beatIcon');
|
|
|
- break;
|
|
|
- case 6:
|
|
|
- startShowModal('toneIcon');
|
|
|
- break;
|
|
|
- case 7:
|
|
|
- startShowModal('setTimeIcon');
|
|
|
- break;
|
|
|
- case 8:
|
|
|
- columnShow.value = false;
|
|
|
- break;
|
|
|
- case 9:
|
|
|
- // 选择曲目时需要暂停所有播放
|
|
|
- handleStop(false);
|
|
|
- data.selectResourceStatus = true;
|
|
|
- break;
|
|
|
- case 10:
|
|
|
- // 点名
|
|
|
- // await rollCallStudentList();
|
|
|
- if (studyData.callStudentList.length > 0) {
|
|
|
- openStudyTool({
|
|
|
- type: 'call',
|
|
|
- icon: iconWhite,
|
|
|
- name: '点名'
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 11:
|
|
|
- if (!isUpArrow.value) return;
|
|
|
- handlePreAndNext('up');
|
|
|
- break;
|
|
|
- case 12:
|
|
|
- if (!isDownArrow.value) return;
|
|
|
- handlePreAndNext('down');
|
|
|
- break;
|
|
|
- case 13:
|
|
|
- popupData.chapterOpen = true;
|
|
|
- break;
|
|
|
- case 14:
|
|
|
- popupData.open = true;
|
|
|
- nextTick(() => {
|
|
|
- scrollResourceSection();
|
|
|
- });
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 点名学生列表
|
|
|
- const rollCallStudentList = async () => {
|
|
|
- //
|
|
|
- if (!data.classId) return;
|
|
|
- try {
|
|
|
- const res = await getStudentList({
|
|
|
- classGroupId: data.classGroupId,
|
|
|
- page: 1,
|
|
|
- rows: 999
|
|
|
- });
|
|
|
- const result = res.data || {};
|
|
|
- if (Array.isArray(result.rows) && result.rows.length > 0) {
|
|
|
- const tempStudents: any = [];
|
|
|
- result.rows.forEach((row: any) => {
|
|
|
- tempStudents.push({
|
|
|
- name: row.nickname,
|
|
|
- img: row.avatar
|
|
|
- });
|
|
|
- });
|
|
|
- studyData.callStudentList = [...tempStudents];
|
|
|
- }
|
|
|
- } catch {
|
|
|
- //
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 滚动到某个元素的位置
|
|
|
- const scrollResourceSection = () => {
|
|
|
- const drawerCardItemRefs =
|
|
|
- document.querySelectorAll('.drawerCardItemRef');
|
|
|
- if (
|
|
|
- popupData.activeIndex >= 0 &&
|
|
|
- drawerCardItemRefs[popupData.activeIndex]
|
|
|
- ) {
|
|
|
- drawerCardItemRefs[popupData.activeIndex].scrollIntoView();
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const getModalHeight = () => {
|
|
|
- const dom: any = document.querySelector('#model-homework-height');
|
|
|
- if (dom) {
|
|
|
- useResizeObserver(dom as HTMLElement, (entries: any) => {
|
|
|
- const entry = entries[0];
|
|
|
- const { height } = entry.contentRect;
|
|
|
- dom.style.setProperty('--window-page-lesson-height', height + 'px');
|
|
|
- });
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- /* 弹窗加拖动 */
|
|
|
- // 引导页
|
|
|
- getGuidanceShow();
|
|
|
- // 选择课件弹窗
|
|
|
- const selCourBoxClass = 'selCourBoxClass_drag';
|
|
|
- const selCourDragData = useDrag(
|
|
|
- [`${selCourBoxClass}>.n-card-header`, `${selCourBoxClass} .bom_drag`],
|
|
|
- selCourBoxClass,
|
|
|
- toRef(data, 'selectClassStatus'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 选择资源弹窗
|
|
|
- const selResourBoxClass = 'selResourBoxClass_drag';
|
|
|
- const selResourDragData = useDrag(
|
|
|
- [
|
|
|
- `${selResourBoxClass} .select-resource>.n-tabs>.n-tabs-nav--top.n-tabs-nav`,
|
|
|
- `${selResourBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- selResourBoxClass,
|
|
|
- toRef(data, 'selectResourceStatus'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 结束预览 结束课程确认弹窗
|
|
|
- const removeResourBoxClass = 'removeResourBoxClass_drag';
|
|
|
- const removeResourDragData = useDrag(
|
|
|
- [
|
|
|
- `${removeResourBoxClass}>.n-card-header`,
|
|
|
- `${removeResourBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- removeResourBoxClass,
|
|
|
- toRef(data, 'removeVisiable'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 章节next弹窗
|
|
|
- const nextEndBoxClass = 'nextEndBoxClass_drag';
|
|
|
- const nextEndBoxDragData = useDrag(
|
|
|
- [`${nextEndBoxClass}>.n-card-header`, `${nextEndBoxClass} .bom_drag`],
|
|
|
- nextEndBoxClass,
|
|
|
- toRef(data, 'nextEndShow'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 章节切换弹窗
|
|
|
- const chapterConBoxClass = 'chapterConBoxClass_drag';
|
|
|
- const chapterConBoxDragData = useDrag(
|
|
|
- [
|
|
|
- `${chapterConBoxClass}>.n-card-header`,
|
|
|
- `${chapterConBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- chapterConBoxClass,
|
|
|
- toRef(popupData, 'chapterOpen'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 资源列表弹窗
|
|
|
- const resourcesConBoxClass = 'resourcesConBoxClass_drag';
|
|
|
- const resourcesConDragData = useDrag(
|
|
|
- [
|
|
|
- `${resourcesConBoxClass}>.n-card-header`,
|
|
|
- `${resourcesConBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- resourcesConBoxClass,
|
|
|
- toRef(popupData, 'open'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 计时器
|
|
|
- const timerMeterConBoxClass = 'timerMeterConBoxClass_drag';
|
|
|
- const timerMeterConDragData = useDrag(
|
|
|
- [
|
|
|
- `${timerMeterConBoxClass} .timeBomCon .bom_drag`,
|
|
|
- `${timerMeterConBoxClass} .topDragDom`
|
|
|
- ],
|
|
|
- timerMeterConBoxClass,
|
|
|
- showModalTime,
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 节拍器
|
|
|
- const metronomeConBoxClass = 'metronomeConBoxClass_drag';
|
|
|
- const metronomeConBoxDragData = useDrag(
|
|
|
- [
|
|
|
- `${metronomeConBoxClass} .topDragDom`,
|
|
|
- `${metronomeConBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- metronomeConBoxClass,
|
|
|
- showModalBeat,
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 布置作业弹窗
|
|
|
- const modelTrainStatusConBoxClass = 'modelTrainStatusConBoxClass_drag';
|
|
|
- const modelTrainStatusConBoxDragData = useDrag(
|
|
|
- [
|
|
|
- `${modelTrainStatusConBoxClass}>.n-card-header`,
|
|
|
- `${modelTrainStatusConBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- modelTrainStatusConBoxClass,
|
|
|
- toRef(data, 'modelTrainStatus'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- // 布置作业课后作业
|
|
|
- const modelTrainHomeWordConBoxClass =
|
|
|
- 'modelTrainHomeWordConBoxClassBoxClass_drag';
|
|
|
- const modelTrainHomeWordConBoxDragData = useDrag(
|
|
|
- [
|
|
|
- `${modelTrainHomeWordConBoxClass}>.n-card-header`,
|
|
|
- `${modelTrainHomeWordConBoxClass} .bom_drag`
|
|
|
- ],
|
|
|
- modelTrainHomeWordConBoxClass,
|
|
|
- toRef(data, 'modelAttendStatus'),
|
|
|
- users.info.id
|
|
|
- );
|
|
|
- return () => (
|
|
|
- <div id="playContent" class={[styles.playContent, 'wrap']}>
|
|
|
- <div
|
|
|
- onClick={() => {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- activeData.model = !activeData.model;
|
|
|
- Object.values(data.videoRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(activeData.model)
|
|
|
- );
|
|
|
- Object.values(data.audioRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(activeData.model)
|
|
|
- );
|
|
|
- }}>
|
|
|
- <div
|
|
|
- class={styles.coursewarePlay}
|
|
|
- style={{ width: parentContainer.width }}>
|
|
|
- {!popupData.chapterLoading ? (
|
|
|
- <div class={styles.wraps}>
|
|
|
- <div
|
|
|
- style={
|
|
|
- activeVideoItem.value.type &&
|
|
|
- data.animationState === 'end' &&
|
|
|
- data.videoState === 'play'
|
|
|
- ? {
|
|
|
- zIndex: 15,
|
|
|
- opacity: 1
|
|
|
- }
|
|
|
- : { opacity: 0, zIndex: -1 }
|
|
|
- }
|
|
|
- class={styles.itemDiv}>
|
|
|
- <VideoPlay
|
|
|
- imagePos={columnPos.value}
|
|
|
- ref={(el: any) => (data.videoItemRef = el)}
|
|
|
- item={activeVideoItem.value}
|
|
|
- showModel={activeData.model}
|
|
|
- onClose={setModelOpen}
|
|
|
- onLoadedmetadata={(videoItem: any) => {
|
|
|
- if (data.itemList[popupData.activeIndex]) {
|
|
|
- data.itemList[popupData.activeIndex].videoEle =
|
|
|
- videoItem;
|
|
|
- }
|
|
|
- }}
|
|
|
- onCanplay={() => {
|
|
|
- data.videoState = 'play';
|
|
|
- // activeVideoItem.value.videoEle = videoItem;
|
|
|
- }}
|
|
|
- onPause={() => {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- activeData.model = true;
|
|
|
- }}
|
|
|
- onEnded={() => {
|
|
|
- // const _index = popupData.activeIndex + 1;
|
|
|
- // if (_index < data.itemList.length) {
|
|
|
- // handleSwipeChange(_index);
|
|
|
- // }
|
|
|
- }}
|
|
|
- />
|
|
|
- </div>
|
|
|
- {data.itemList.map((m: any, mIndex: number) => {
|
|
|
- const isRender = Math.abs(popupData.activeIndex - mIndex) < 2;
|
|
|
- const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
|
|
|
- // if (isRender && m.type === 'PPT') {
|
|
|
- // setTimeout(() => iframeClick() ,500)
|
|
|
- // }
|
|
|
- // if (isRender) {
|
|
|
- // m.isRender = true;
|
|
|
- // }
|
|
|
-
|
|
|
- // const isRender =
|
|
|
- // m.isRender || Math.abs(popupData.activeIndex - mIndex) < 2;
|
|
|
- // const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
|
|
|
- // if (isRender) {
|
|
|
- // m.isRender = true;
|
|
|
- // }
|
|
|
-
|
|
|
- return isRender ? (
|
|
|
- <div
|
|
|
- key={'index' + mIndex}
|
|
|
- class={[
|
|
|
- styles.itemDiv,
|
|
|
- popupData.activeIndex === mIndex && styles.itemActive,
|
|
|
- activeData.isAnimation && styles.acitveAnimation,
|
|
|
- Math.abs(popupData.activeIndex - mIndex) < 2
|
|
|
- ? styles.show
|
|
|
- : styles.hide
|
|
|
- ]}
|
|
|
- style={
|
|
|
- mIndex < popupData.activeIndex
|
|
|
- ? effects[effectIndex.value].prev
|
|
|
- : mIndex > popupData.activeIndex
|
|
|
- ? effects[effectIndex.value].next
|
|
|
- : {}
|
|
|
- }
|
|
|
- onClick={(e: Event) => {
|
|
|
- e.stopPropagation();
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- if (Date.now() - activeData.nowTime < 300) {
|
|
|
- handleDbClick(m);
|
|
|
- return;
|
|
|
- }
|
|
|
- activeData.nowTime = Date.now();
|
|
|
- activeData.timer = setTimeout(() => {
|
|
|
- activeData.model = !activeData.model;
|
|
|
- Object.values(data.videoRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(activeData.model)
|
|
|
- );
|
|
|
- Object.values(data.audioRefs).map((n: any) =>
|
|
|
- n?.toggleHideControl(activeData.model)
|
|
|
- );
|
|
|
- if (activeData.model) {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
- }, 300);
|
|
|
- }}>
|
|
|
- {m.type === 'VIDEO' ? (
|
|
|
- <>
|
|
|
- <img
|
|
|
- src={m.coverImg}
|
|
|
- onLoad={() => {
|
|
|
- m.isprepare = true;
|
|
|
- }}
|
|
|
- />
|
|
|
- {/* <VideoPlay
|
|
|
- ref={(v: any) => (data.videoRefs[mIndex] = v)}
|
|
|
- item={m}
|
|
|
- isEmtry={isEmtry}
|
|
|
- onLoadedmetadata={(videoItem: any) => {
|
|
|
- m.videoEle = videoItem;
|
|
|
- m.isprepare = true;
|
|
|
- }}
|
|
|
- onTogglePlay={(paused: boolean) => {
|
|
|
- m.autoPlay = false;
|
|
|
- if (paused || popupData.open) {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- } else {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
- }}
|
|
|
- onReset={() => {
|
|
|
- if (!m.videoEle?.paused) {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
- }}
|
|
|
- onError={() => {
|
|
|
- console.log('video error');
|
|
|
- m.error = true;
|
|
|
- }}
|
|
|
- /> */}
|
|
|
- <Transition name="van-fade">
|
|
|
- {
|
|
|
- <div class={styles.loadWrap}>
|
|
|
- <Vue3Lottie
|
|
|
- animationData={playLoadData}></Vue3Lottie>
|
|
|
- </div>
|
|
|
- }
|
|
|
- </Transition>
|
|
|
- </>
|
|
|
- ) : m.type === 'IMG' ? (
|
|
|
- <img src={m.content} />
|
|
|
- ) : m.type === 'SONG' ? (
|
|
|
- <AudioPay
|
|
|
- imagePos={columnPos.value}
|
|
|
- item={m}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- ref={(v: any) => (data.audioRefs[mIndex] = v)}
|
|
|
- onLoadedmetadata={(audioItem: any) => {
|
|
|
- m.audioEle = audioItem;
|
|
|
- m.isprepare = true;
|
|
|
- }}
|
|
|
- onTogglePlay={(paused: boolean) => {
|
|
|
- // m.autoPlay = false;
|
|
|
- if (paused || popupData.open) {
|
|
|
- clearTimeout(activeData.timer);
|
|
|
- } else {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
- }}
|
|
|
- onEnded={() => {
|
|
|
- // const _index = popupData.activeIndex + 1;
|
|
|
- // if (_index < data.itemList.length) {
|
|
|
- // handleSwipeChange(_index);
|
|
|
- // }
|
|
|
- }}
|
|
|
- onReset={() => {
|
|
|
- if (!m.audioEle?.paused) {
|
|
|
- setModelOpen();
|
|
|
- }
|
|
|
- }}
|
|
|
- />
|
|
|
- ) : // : m.type === 'PPT' ? <div class={styles.iframePpt}>
|
|
|
- // <div class={styles.pptBox}></div>
|
|
|
- // <iframe src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(m.content)}`} width='100%' height='100%' frameborder='1'></iframe>
|
|
|
- // </div>
|
|
|
- m.type === 'PPT' ? (
|
|
|
- <iframe
|
|
|
- src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(
|
|
|
- m.content
|
|
|
- )}`}
|
|
|
- width="100%"
|
|
|
- height="100%"
|
|
|
- frameborder="1"></iframe>
|
|
|
- ) : m.type === 'RHYTHM' ? (
|
|
|
- <RhythmModal
|
|
|
- item={m}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- imagePos={columnPos.value}
|
|
|
- onSetIframe={(el: any) => {
|
|
|
- m.iframeRef = el;
|
|
|
- }}
|
|
|
- />
|
|
|
- ) : m.type === 'LISTEN' ? (
|
|
|
- <ListenModal
|
|
|
- item={m}
|
|
|
- data-vid={m.id}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- onSetIframe={(el: any) => {
|
|
|
- m.iframeRef = el;
|
|
|
- }}
|
|
|
- />
|
|
|
- ) : m.type === 'INSTRUMENT' || m.type === 'MUSICIAN' ? (
|
|
|
- <InstruemntDetail
|
|
|
- type="preview"
|
|
|
- id={m.content}
|
|
|
- contentType={m.type}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- ref={(el: any) => (m.iframeRef = el)}
|
|
|
- />
|
|
|
- ) : m.type === 'MUSIC_WIKI' ? (
|
|
|
- <MusicDetail
|
|
|
- type="preview"
|
|
|
- id={m.content}
|
|
|
- contentType={m.type}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- ref={(el: any) => (m.iframeRef = el)}
|
|
|
- />
|
|
|
- ) : m.type === 'THEORY' ? (
|
|
|
- <TheotyDetail
|
|
|
- type="preview"
|
|
|
- id={m.content}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- ref={(el: any) => (m.iframeRef = el)}
|
|
|
- />
|
|
|
- ) : (
|
|
|
- <MusicScore
|
|
|
- activeModel={activeData.model}
|
|
|
- activeStatus={popupData.activeIndex === mIndex}
|
|
|
- data-vid={m.id}
|
|
|
- music={m}
|
|
|
- imagePos={columnPos.value}
|
|
|
- onSetIframe={(el: any) => {
|
|
|
- m.iframeRef = el;
|
|
|
- }}
|
|
|
- />
|
|
|
- )}
|
|
|
- </div>
|
|
|
- ) : null;
|
|
|
- })}
|
|
|
- </div>
|
|
|
- ) : (
|
|
|
- ''
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* 右边操作栏 */}
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.rightColumn,
|
|
|
- columnShow.value && columnPos.value === 'right'
|
|
|
- ? ''
|
|
|
- : styles.rightColumnHide
|
|
|
- ]}>
|
|
|
- {rightList.map((item: any) => (
|
|
|
- <div class={styles.columnItemBox}>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.columnItem,
|
|
|
- (item.id === 2 && data.preStudentNum <= 0) ||
|
|
|
- (item.id === 10 && studyData.callStudentList.length <= 0) ||
|
|
|
- (item.id === 11 && !isUpArrow.value) ||
|
|
|
- (item.id === 12 && !isDownArrow.value)
|
|
|
- ? styles.itemDisabled
|
|
|
- : ''
|
|
|
- ]}
|
|
|
- onClick={() => operateRightBtn(item.id)}>
|
|
|
- <NTooltip
|
|
|
- showArrow={false}
|
|
|
- placement="left"
|
|
|
- class={[
|
|
|
- item.id === 15
|
|
|
- ? 'columnItemTooltip rightColumnItemTooltip'
|
|
|
- : ''
|
|
|
- ]}>
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <img src={item.id === 8 ? rightIconPackUp : item.icon} />
|
|
|
- ),
|
|
|
- default: () =>
|
|
|
- item.id === 15 ? (
|
|
|
- <div class="tools">
|
|
|
- {tooltipList.map(i => (
|
|
|
- <div onClick={() => operateRightBtn(i.id)}>
|
|
|
- <img src={i.icon} />
|
|
|
- <div class="tit">{i.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- ) : item.id === 1 && data.type === 'preview' ? (
|
|
|
- item.name2
|
|
|
- ) : (
|
|
|
- item.name
|
|
|
- )
|
|
|
- }}
|
|
|
- </NTooltip>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- <NTooltip showArrow={false} placement="left">
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.rightHideIcon,
|
|
|
- !(columnShow.value && columnPos.value === 'right')
|
|
|
- ? styles.rightIconShow
|
|
|
- : ''
|
|
|
- ]}
|
|
|
- onClick={() => {
|
|
|
- columnPos.value = 'right';
|
|
|
- columnShow.value = true;
|
|
|
- }}
|
|
|
- />
|
|
|
- ),
|
|
|
- default: () => '按钮镜像'
|
|
|
- }}
|
|
|
- </NTooltip>
|
|
|
- {/* 左边操作栏 */}
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.leftColumn,
|
|
|
- columnShow.value && columnPos.value === 'left'
|
|
|
- ? ''
|
|
|
- : styles.leftColumnHide
|
|
|
- ]}>
|
|
|
- {rightList.map((item: any) => (
|
|
|
- <div class={styles.columnItemBox}>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.columnItem,
|
|
|
- (item.id === 2 && data.preStudentNum <= 0) ||
|
|
|
- (item.id === 10 && studyData.callStudentList.length <= 0) ||
|
|
|
- (item.id === 11 && !isUpArrow.value) ||
|
|
|
- (item.id === 12 && !isDownArrow.value)
|
|
|
- ? styles.itemDisabled
|
|
|
- : ''
|
|
|
- ]}
|
|
|
- onClick={() => operateRightBtn(item.id)}>
|
|
|
- <NTooltip
|
|
|
- showArrow={false}
|
|
|
- placement="right"
|
|
|
- class={[item.id === 15 ? 'columnItemTooltip' : '']}>
|
|
|
- {{
|
|
|
- trigger: () => <img src={item.icon} />,
|
|
|
- default: () =>
|
|
|
- item.id === 15 ? (
|
|
|
- <div class="tools">
|
|
|
- {tooltipList.map(i => (
|
|
|
- <div onClick={() => operateRightBtn(i.id)}>
|
|
|
- <img src={i.icon} />
|
|
|
- <div class="tit">{i.name}</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- ) : item.id === 1 && data.type === 'preview' ? (
|
|
|
- item.name2
|
|
|
- ) : (
|
|
|
- item.name
|
|
|
- )
|
|
|
- }}
|
|
|
- </NTooltip>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- <NTooltip showArrow={false} placement="right">
|
|
|
- {{
|
|
|
- trigger: () => (
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.leftHideIcon,
|
|
|
- !(columnShow.value && columnPos.value === 'left')
|
|
|
- ? styles.leftIconShow
|
|
|
- : ''
|
|
|
- ]}
|
|
|
- onClick={() => {
|
|
|
- columnPos.value = 'left';
|
|
|
- columnShow.value = true;
|
|
|
- }}
|
|
|
- />
|
|
|
- ),
|
|
|
- default: () => '按钮镜像'
|
|
|
- }}
|
|
|
- </NTooltip>
|
|
|
-
|
|
|
- {/* 显示列表 */}
|
|
|
- {/* <NDrawer
|
|
|
- v-model:show={popupData.open}
|
|
|
- class={[styles.drawerContainer, styles.drawerContainerSource]}
|
|
|
- onAfterLeave={handleClosePopup}
|
|
|
- showMask={false}
|
|
|
- blockScroll={false}
|
|
|
- trapFocus={false}>
|
|
|
- <NDrawerContent closable>
|
|
|
- {{
|
|
|
- header: () => (
|
|
|
- <TheNoticeBar text={activeName.value || '资源列表'} />
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <SourceList
|
|
|
- teacherChapterName={data.teacherChapterName}
|
|
|
- knowledgePointList={data.knowledgePointList}
|
|
|
- courseActiveIndex={popupData.courseActiveIndex}
|
|
|
- activeItem={data.itemList[popupData.activeIndex]}
|
|
|
- onConfirm={(item: any) => {
|
|
|
- popupData.open = false;
|
|
|
- toggleMaterial(item.id);
|
|
|
- }}
|
|
|
- />
|
|
|
- )
|
|
|
- }}
|
|
|
- </NDrawerContent>
|
|
|
- </NDrawer> */}
|
|
|
- <NModal
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={popupData.open}
|
|
|
- preset="card"
|
|
|
- class={[
|
|
|
- 'modalTitle background',
|
|
|
- styles.drawerContainer,
|
|
|
- resourcesConBoxClass
|
|
|
- ]}
|
|
|
- style={resourcesConDragData.styleDrag.value}
|
|
|
- title={activeName.value || '资源列表'}>
|
|
|
- <SourceList
|
|
|
- teacherChapterName={data.teacherChapterName}
|
|
|
- knowledgePointList={data.knowledgePointList}
|
|
|
- courseActiveIndex={popupData.courseActiveIndex}
|
|
|
- activeItem={data.itemList[popupData.activeIndex]}
|
|
|
- onConfirm={(item: any) => {
|
|
|
- popupData.open = false;
|
|
|
- toggleMaterial(item.id);
|
|
|
- }}
|
|
|
- />
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </NModal>
|
|
|
- {/* 章节切换 */}
|
|
|
- {/* <NDrawer
|
|
|
- v-model:show={popupData.chapterOpen}
|
|
|
- class={styles.drawerContainer}
|
|
|
- onAfterLeave={handleClosePopup}
|
|
|
- showMask={false}
|
|
|
- maskClosable={data.selectClassStatus ? false : true}
|
|
|
- blockScroll={false}
|
|
|
- trapFocus={false}>
|
|
|
- <NDrawerContent title="切换章节" closable>
|
|
|
- <Chapter
|
|
|
- treeList={popupData.chapterDetails}
|
|
|
- itemActive={data.detailId as any}
|
|
|
- onHandleSelect={async (val: any) => {
|
|
|
- // itemActive: child.id,
|
|
|
- // itemName: child.name
|
|
|
- popupData.courseId = val.itemActive;
|
|
|
- data.selectClassStatus = true;
|
|
|
- }}
|
|
|
- />
|
|
|
- </NDrawerContent>
|
|
|
- </NDrawer> */}
|
|
|
- <NModal
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={popupData.chapterOpen}
|
|
|
- preset="card"
|
|
|
- class={[
|
|
|
- 'modalTitle background',
|
|
|
- styles.drawerContainer,
|
|
|
- chapterConBoxClass
|
|
|
- ]}
|
|
|
- style={chapterConBoxDragData.styleDrag.value}
|
|
|
- title={'切换章节'}>
|
|
|
- <Chapter
|
|
|
- treeList={popupData.chapterDetails}
|
|
|
- itemActive={data.detailId as any}
|
|
|
- onHandleSelect={async (val: any) => {
|
|
|
- // itemActive: child.id,
|
|
|
- // itemName: child.name
|
|
|
- popupData.courseId = val.itemActive;
|
|
|
- data.selectClassStatus = true;
|
|
|
- }}
|
|
|
- />
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </NModal>
|
|
|
- {/* 批注 */}
|
|
|
- {studyData.penShow && (
|
|
|
- <Pen
|
|
|
- isDrag={true}
|
|
|
- show={studyData.type === 'pen'}
|
|
|
- type={studyData.type}
|
|
|
- close={() => closeStudyTool()}
|
|
|
- />
|
|
|
- )}
|
|
|
-
|
|
|
- {studyData.whiteboardShow && (
|
|
|
- <Pen
|
|
|
- isDrag={true}
|
|
|
- show={studyData.type === 'whiteboard'}
|
|
|
- type={studyData.type}
|
|
|
- close={() => closeStudyTool()}
|
|
|
- />
|
|
|
- )}
|
|
|
-
|
|
|
- {studyData.callShow && (
|
|
|
- <Pen
|
|
|
- isDrag={true}
|
|
|
- imagePos={columnPos.value}
|
|
|
- callStudents={studyData.callStudentList}
|
|
|
- show={studyData.type === 'call'}
|
|
|
- type={studyData.type}
|
|
|
- close={() => {
|
|
|
- closeStudyTool();
|
|
|
- studyData.callShow = false;
|
|
|
- }}
|
|
|
- />
|
|
|
- )}
|
|
|
-
|
|
|
- {/* 选择课件 */}
|
|
|
- <NModal
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={data.selectClassStatus}
|
|
|
- preset="card"
|
|
|
- class={[
|
|
|
- 'modalTitle background',
|
|
|
- // styles.attendClassModal,
|
|
|
- styles.selectClassModal,
|
|
|
- selCourBoxClass
|
|
|
- ]}
|
|
|
- style={selCourDragData.styleDrag.value}
|
|
|
- title={'选择课件'}>
|
|
|
- <SelectClass
|
|
|
- classId={data.classId}
|
|
|
- courseId={popupData.courseId}
|
|
|
- instrumentId={data.instrumentId}
|
|
|
- lessonCoursewareSubjectList={data.lessonCoursewareSubjectList}
|
|
|
- onConfirm={async (val: any) => {
|
|
|
- popupData.chapterLoading = true;
|
|
|
- try {
|
|
|
- data.selectClassStatus = false;
|
|
|
- data.detailId = val.itemActive;
|
|
|
- data.courseId = val.chapterId;
|
|
|
- const ids = formatParentId(
|
|
|
- val.itemActive,
|
|
|
- popupData.chapterDetails
|
|
|
- );
|
|
|
- data.lessonCoursewareDetailId = ids[0];
|
|
|
- // 更新上课记录 上课的时候才更新
|
|
|
- if (data.type !== 'preview') {
|
|
|
- await classCourseScheduleUpdate();
|
|
|
- }
|
|
|
- await getDetail();
|
|
|
- popupData.activeIndex = 0;
|
|
|
- popupData.chapterOpen = false;
|
|
|
- } catch {
|
|
|
- //
|
|
|
- }
|
|
|
- popupData.chapterLoading = false;
|
|
|
- }}
|
|
|
- />
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </NModal>
|
|
|
-
|
|
|
- {/* 布置作业 */}
|
|
|
- <NModal
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={data.modelAttendStatus}
|
|
|
- preset="card"
|
|
|
- title={'课后作业'}
|
|
|
- style={modelTrainHomeWordConBoxDragData.styleDrag.value}
|
|
|
- class={[
|
|
|
- 'modalTitle',
|
|
|
- styles.removeVisiable,
|
|
|
- modelTrainHomeWordConBoxClass
|
|
|
- ]}>
|
|
|
- <div class={styles.studentRemove}>
|
|
|
- <p>{data.modalAttendMessage}</p>
|
|
|
- <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
- <NButton
|
|
|
- type="default"
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- data.modelTrainStatus = true;
|
|
|
- nextTick(() => {
|
|
|
- getModalHeight();
|
|
|
- });
|
|
|
- data.modelAttendStatus = false;
|
|
|
- }}>
|
|
|
- 布置作业
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- type="primary"
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- handleStop();
|
|
|
- data.modelAttendStatus = false;
|
|
|
- }}>
|
|
|
- 取消
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
- </div>
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </NModal>
|
|
|
-
|
|
|
- {/* 训练设置 */}
|
|
|
- {/* <NModal
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={data.modelTrainStatus}
|
|
|
- preset="card"
|
|
|
- class={[styles.attendClassModal, styles.trainClassModal]}
|
|
|
- title={'作业设置'}>
|
|
|
- <ClassWork
|
|
|
- detailId={data.detailId}
|
|
|
- instrumentId={data.instrumentId}
|
|
|
- courseScheduleId={data.classId}
|
|
|
- activeName={activeName.value}
|
|
|
- classGroupId={data.classGroupId}
|
|
|
- onClose={() => (data.modelTrainStatus = false)}
|
|
|
- />
|
|
|
- </NModal> */}
|
|
|
- <NModal
|
|
|
- v-model:show={data.modelTrainStatus}
|
|
|
- preset="card"
|
|
|
- class={[
|
|
|
- 'modalTitle background',
|
|
|
- styles.workVisiable,
|
|
|
- modelTrainStatusConBoxClass
|
|
|
- ]}
|
|
|
- style={modelTrainStatusConBoxDragData.styleDrag.value}
|
|
|
- title={'布置作业'}>
|
|
|
- <div id="model-homework-height" class={styles.workContainer}>
|
|
|
- <div class={styles.workTrain}>
|
|
|
- <Train
|
|
|
- from={'class'}
|
|
|
- cardType="homeworkRecord"
|
|
|
- lessonPreTraining={{
|
|
|
- title: data.lessonPreTrainingId
|
|
|
- ? ''
|
|
|
- : data.teacherChapterName + '-课后作业',
|
|
|
- chapterId: data.courseId, // 课件编号
|
|
|
- id: data.lessonPreTrainingId // 作业编号
|
|
|
- }}
|
|
|
- coursewareKnowledgeDetailId={data.detailId}
|
|
|
- classGroupId={data.classGroupId}
|
|
|
- courseScheduleId={data.classId}
|
|
|
- onChange={async (val: any) => {
|
|
|
- data.modelTrainStatus = val.status;
|
|
|
- // getCoursewareList();
|
|
|
- if (val.saveWork && data.classId) {
|
|
|
- data.lessonPreTrainingId = val.lessonPreTrainingId;
|
|
|
- }
|
|
|
- }}
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class={styles.resourceMain}>
|
|
|
- <ResourceMain from={'class'} cardType="homerowk-record" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </NModal>
|
|
|
-
|
|
|
- {/* <NModal
|
|
|
- transformOrigin="center"
|
|
|
- class={['modalTitle background', metronomeConBoxClass]}
|
|
|
- title={'节拍器'}
|
|
|
- preset="card"
|
|
|
- v-model:show={showModalBeat.value}
|
|
|
- style={{
|
|
|
- width: '687px',
|
|
|
- ...metronomeConBoxDragData.styleDrag.value
|
|
|
- }}>
|
|
|
- <div class={styles.modeWrap}>
|
|
|
- <iframe
|
|
|
- src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
|
|
|
- scrolling="no"
|
|
|
- frameborder="0"
|
|
|
- width="100%"
|
|
|
- onLoad={(val: any) => {
|
|
|
- iframeDislableKeyboard(val.target);
|
|
|
- }}
|
|
|
- height={'650px'}></iframe>
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </div>
|
|
|
- </NModal> */}
|
|
|
- <Metronome
|
|
|
- v-model={showModalBeat.value}
|
|
|
- dragClass={metronomeConBoxClass}
|
|
|
- dragStyle={metronomeConBoxDragData.styleDrag.value}></Metronome>
|
|
|
- <NModal
|
|
|
- transformOrigin="center"
|
|
|
- class={['background']}
|
|
|
- v-model:show={showModalTone.value}>
|
|
|
- <div>
|
|
|
- <PlaceholderTone
|
|
|
- onClose={() => {
|
|
|
- showModalTone.value = false;
|
|
|
- }}></PlaceholderTone>
|
|
|
- </div>
|
|
|
- </NModal>
|
|
|
- <NModal
|
|
|
- v-model:show={showModalTime.value}
|
|
|
- class={timerMeterConBoxClass}
|
|
|
- style={timerMeterConDragData.styleDrag.value}>
|
|
|
- <div>
|
|
|
- <img
|
|
|
- class={styles.timerMeterClose}
|
|
|
- src={timerMeterClose}
|
|
|
- onClick={() => {
|
|
|
- showModalTime.value = false;
|
|
|
- }}
|
|
|
- />
|
|
|
- <div class="topDragDom"></div>
|
|
|
- <TimerMeter></TimerMeter>
|
|
|
- </div>
|
|
|
- </NModal>
|
|
|
-
|
|
|
- <NModal
|
|
|
- v-model:show={data.selectResourceStatus}
|
|
|
- class={['modalTitle', styles.selectMusicModal, selResourBoxClass]}
|
|
|
- style={selResourDragData.styleDrag.value}
|
|
|
- preset="card"
|
|
|
- title={'选择资源'}>
|
|
|
- <SelectResources from="class" />
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </NModal>
|
|
|
- <NModal
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={data.removeVisiable}
|
|
|
- preset="card"
|
|
|
- class={['modalTitle', styles.removeVisiable, removeResourBoxClass]}
|
|
|
- style={removeResourDragData.styleDrag.value}
|
|
|
- title={data.removeTitle}>
|
|
|
- <div class={styles.studentRemove}>
|
|
|
- <p>{data.removeContent}</p>
|
|
|
-
|
|
|
- <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
- <NButton
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- if (data.removeCourseStatus) {
|
|
|
- if (globalState.application) {
|
|
|
- document.exitFullscreen
|
|
|
- ? document.exitFullscreen()
|
|
|
- : document.mozCancelFullScreen
|
|
|
- ? document.mozCancelFullScreen()
|
|
|
- : document.webkitExitFullscreen
|
|
|
- ? document.webkitExitFullscreen()
|
|
|
- : '';
|
|
|
- emit('close');
|
|
|
- } else {
|
|
|
- window.close();
|
|
|
- }
|
|
|
- } else {
|
|
|
- data.removeVisiable = false;
|
|
|
- }
|
|
|
- }}>
|
|
|
- {data.removeCourseStatus ? '结束课程' : '取消'}
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- round
|
|
|
- type="primary"
|
|
|
- onClick={() => {
|
|
|
- //
|
|
|
- if (data.removeCourseStatus) {
|
|
|
- data.modelTrainStatus = true;
|
|
|
- data.removeVisiable = false;
|
|
|
- nextTick(() => {
|
|
|
- getModalHeight();
|
|
|
- });
|
|
|
- } else {
|
|
|
- if (globalState.application) {
|
|
|
- document.exitFullscreen
|
|
|
- ? document.exitFullscreen()
|
|
|
- : document.mozCancelFullScreen
|
|
|
- ? document.mozCancelFullScreen()
|
|
|
- : document.webkitExitFullscreen
|
|
|
- ? document.webkitExitFullscreen()
|
|
|
- : '';
|
|
|
- emit('close');
|
|
|
- } else {
|
|
|
- window.close();
|
|
|
-
|
|
|
- if (route.query.source === 'admin') {
|
|
|
- storage.remove(ACCESS_TOKEN_ADMIN);
|
|
|
- window.parent.postMessage(
|
|
|
- {
|
|
|
- api: 'iframe_exit'
|
|
|
- },
|
|
|
- '*'
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }}>
|
|
|
- {data.removeCourseStatus ? '布置作业' : '确定'}
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </div>
|
|
|
- </NModal>
|
|
|
- <NModal
|
|
|
- style={nextEndBoxDragData.styleDrag.value}
|
|
|
- z-index={3000}
|
|
|
- transformOrigin="center"
|
|
|
- v-model:show={data.nextEndShow}
|
|
|
- preset="card"
|
|
|
- title={'提示'}
|
|
|
- class={['modalTitle', styles.removeVisiable, nextEndBoxClass]}>
|
|
|
- <div class={styles.studentRemove}>
|
|
|
- <p>当前课件已结束,是否进入下一章节</p>
|
|
|
- <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
- <NButton
|
|
|
- type="default"
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- data.nextEndShow = false;
|
|
|
- }}>
|
|
|
- 取消
|
|
|
- </NButton>
|
|
|
- <NButton
|
|
|
- type="primary"
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- data.nextEndShow = false;
|
|
|
- handleNextEnd();
|
|
|
- }}>
|
|
|
- 确认
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
- <Dragbom></Dragbom>
|
|
|
- </div>
|
|
|
- </NModal>
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-});
|
|
|
+import {
|
|
|
+ defineComponent,
|
|
|
+ onMounted,
|
|
|
+ reactive,
|
|
|
+ onUnmounted,
|
|
|
+ ref,
|
|
|
+ Transition,
|
|
|
+ computed,
|
|
|
+ nextTick,
|
|
|
+ watch,
|
|
|
+ toRef
|
|
|
+} from 'vue';
|
|
|
+import styles from './index.module.less';
|
|
|
+import 'plyr/dist/plyr.css';
|
|
|
+import MusicScore from './component/musicScore';
|
|
|
+// import iconChange from './image/icon-change.png';
|
|
|
+// import iconMenu from './image/icon-menu.png';
|
|
|
+// import iconUp from './image/icon-up.png';
|
|
|
+// import iconDown from './image/icon-down.png';
|
|
|
+// import iconNote from './image/icon-note.png';
|
|
|
+// import iconWhiteboard from './image/icon-whiteboard.png';
|
|
|
+// import iconAssignHomework from './image/icon-assignHomework.png';
|
|
|
+// import iconClose from './image/icon-close.png';
|
|
|
+// import iconOverPreivew from './image/icon-over-preview.png';
|
|
|
+import { Vue3Lottie } from 'vue3-lottie';
|
|
|
+import playLoadData from './datas/data.json';
|
|
|
+// import Moveable from 'moveable';
|
|
|
+import VideoPlay from './component/video-play';
|
|
|
+import {
|
|
|
+ useMessage,
|
|
|
+ NDrawer,
|
|
|
+ NDrawerContent,
|
|
|
+ NModal,
|
|
|
+ NSpace,
|
|
|
+ NButton,
|
|
|
+ NCollapse,
|
|
|
+ NCollapseItem,
|
|
|
+ NTooltip
|
|
|
+} from 'naive-ui';
|
|
|
+import CardType from '@/components/card-type';
|
|
|
+import Pen from './component/tools/pen';
|
|
|
+import AudioPay from './component/audio-pay';
|
|
|
+import TrainSettings from './model/train-settings';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
+import {
|
|
|
+ api_teacherChapterLessonCoursewareDetail,
|
|
|
+ courseScheduleUpdate,
|
|
|
+ lessonCoursewareDetail,
|
|
|
+ lessonPreTrainingPage,
|
|
|
+ queryCourseware
|
|
|
+} from '../prepare-lessons/api';
|
|
|
+import { vaildUrl } from '/src/utils/urlUtils';
|
|
|
+import TimerMeter from '/src/components/timerMeter';
|
|
|
+import Metronome from '/src/components/Metronome';
|
|
|
+import { iframeDislableKeyboard, px2vw } from '/src/utils';
|
|
|
+import PlaceholderTone from '/src/components/layout/modals/placeholderTone';
|
|
|
+import { state as globalState } from '/src/state';
|
|
|
+import Chapter from './model/chapter';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import { useUserStore } from '@/store/modules/users';
|
|
|
+import iconNote from './new-image/icon-note.png';
|
|
|
+import iconWhite from './new-image/icon-white.png';
|
|
|
+import timerMeterClose from './image/close.png';
|
|
|
+import rightIconEnd from './image/right_icon1.png';
|
|
|
+import rightIconArrange from './image/right_icon2.png';
|
|
|
+import rightIconPostil from './image/right_icon3.png';
|
|
|
+import rightIconWhiteboard from './image/right_icon4.png';
|
|
|
+import rightIconMetronome from './image/right_icon5.png';
|
|
|
+import rightIconTuner from './image/right_icon6.png';
|
|
|
+import rightIconTimer from './image/right_icon7.png';
|
|
|
+import rightIconCall from './image/right_icon10.png';
|
|
|
+import rightIconPackUp from './image/right_icon11.png';
|
|
|
+import leftIconPackUp from './image/right_icon8.png';
|
|
|
+import rightIconMusic from './image/right_icon9.png';
|
|
|
+import bottomIconSwitch from './image/bottom_icon1.png';
|
|
|
+import bottomIconResource from './image/bottom_icon2.png';
|
|
|
+import bottomIconPre from './image/bottom_icon3.png';
|
|
|
+import bottomIconNext from './image/bottom_icon4.png';
|
|
|
+import rightIconTool from './image/right_icon12.png';
|
|
|
+import rightHideIcon from './image/right_hide_icon.png';
|
|
|
+import leftHideIcon from './image/left_hide_icon.png';
|
|
|
+import SelectResources from '../prepare-lessons/model/select-resources';
|
|
|
+import { getStudentAfterWork, getStudentList } from '../studentList/api';
|
|
|
+import TheNoticeBar from '/src/components/TheNoticeBar';
|
|
|
+import ClassWork from './model/class-work';
|
|
|
+import SelectClass from './model/select-class';
|
|
|
+import SourceList from './model/source-list';
|
|
|
+import RhythmModal from './component/rhythm-modal';
|
|
|
+import InstruemntDetail from '/src/views/prepare-lessons/model/source-instrument/detail';
|
|
|
+import TheotyDetail from '/src/views/prepare-lessons/model/source-knowledge/detail';
|
|
|
+import MusicDetail from '/src/views/prepare-lessons/model/source-music/detail';
|
|
|
+import ListenModal from '/src/components/card-preview/listen-modal';
|
|
|
+import Train from '../prepare-lessons/components/lesson-main/train';
|
|
|
+import ResourceMain from '../prepare-lessons/components/resource-main';
|
|
|
+import { useResizeObserver } from '@vueuse/core';
|
|
|
+import { storage } from '/src/utils/storage';
|
|
|
+import { ACCESS_TOKEN_ADMIN } from '/src/store/mutation-types';
|
|
|
+import useDrag from '@/hooks/useDrag';
|
|
|
+import { getGuidanceShow } from '@/hooks/useDrag/useDragGuidance';
|
|
|
+import Dragbom from '@/hooks/useDrag/dragbom';
|
|
|
+import { api_cousseScheduleDetail } from '/src/api/user';
|
|
|
+
|
|
|
+export type ToolType = 'init' | 'pen' | 'whiteboard' | 'call';
|
|
|
+export type ToolItem = {
|
|
|
+ type: ToolType;
|
|
|
+ name: string;
|
|
|
+ icon: string;
|
|
|
+};
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'CoursewarePlay',
|
|
|
+ props: {
|
|
|
+ type: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ courseId: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ instrumentId: {
|
|
|
+ type: [String, Number],
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ // 教材编号
|
|
|
+ lessonCourseId: {
|
|
|
+ type: [String, Number],
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ detailId: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ // 班级编号
|
|
|
+ classGroupId: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ // 上课记录编号
|
|
|
+ classId: {
|
|
|
+ type: String,
|
|
|
+ defaault: ''
|
|
|
+ },
|
|
|
+ preStudentNum: {
|
|
|
+ type: [String, Number],
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ emits: ['close'],
|
|
|
+ setup(props, { emit }) {
|
|
|
+ const message = useMessage();
|
|
|
+ const route = useRoute();
|
|
|
+ const router = useRouter();
|
|
|
+ const users = useUserStore();
|
|
|
+ /** 设置播放容器 16:9 */
|
|
|
+ const parentContainer = reactive({
|
|
|
+ width: '100vw'
|
|
|
+ });
|
|
|
+ // const NPopoverRef = ref();
|
|
|
+ // const setContainer = () => {
|
|
|
+ // const min = Math.min(screen.width, screen.height);
|
|
|
+ // const max = Math.max(screen.width, screen.height);
|
|
|
+ // const width = min * (16 / 9);
|
|
|
+ // if (width > max) {
|
|
|
+ // parentContainer.width = '100vw';
|
|
|
+ // return;
|
|
|
+ // } else {
|
|
|
+ // parentContainer.width = width + 'px';
|
|
|
+ // }
|
|
|
+ // };
|
|
|
+ const handleInit = (type = 0) => {
|
|
|
+ //设置容器16:9
|
|
|
+ // setContainer();
|
|
|
+ };
|
|
|
+ handleInit();
|
|
|
+ onUnmounted(() => {
|
|
|
+ handleInit(1);
|
|
|
+ window.removeEventListener('online', handleOnline);
|
|
|
+ window.removeEventListener('offline', handleOffline);
|
|
|
+ });
|
|
|
+
|
|
|
+ const data = reactive({
|
|
|
+ type: 'class' as '' | 'preview' | 'class', // 预览类型
|
|
|
+ courseId: '' as any, // 课件编号
|
|
|
+ instrumentId: '' as any, // 声部编号
|
|
|
+ lessonCourseId: '' as any, // 教材编号
|
|
|
+ lessonCoursewareDetailId: '' as any, // 章节
|
|
|
+ lessonCoursewareSubjectList: [] as any, // 教材上的声部
|
|
|
+ detailId: '' as any, // 编号 - 课程编号
|
|
|
+ classGroupId: '' as any, // 上课时需要 班级编号
|
|
|
+ classId: '' as any, // 上课编号
|
|
|
+ preStudentNum: '' as any, // 班上学生
|
|
|
+ // detail: null,
|
|
|
+ knowledgePointList: [] as any,
|
|
|
+ itemList: [] as any,
|
|
|
+ // showHead: true,
|
|
|
+ // isCourse: false,
|
|
|
+ // isRecordPlay: false,
|
|
|
+ videoRefs: {} as any[],
|
|
|
+ audioRefs: {} as any[],
|
|
|
+ modelAttendStatus: false, // 布置作业提示弹窗
|
|
|
+ modalAttendMessage: '本节课未设置课后作业,是否继续?',
|
|
|
+ modelTrainStatus: false, // 训练设置
|
|
|
+ selectClassStatus: false, // 选择课件
|
|
|
+ homeworkStatus: true, // 布置作业完成时
|
|
|
+ removeVisiable: false,
|
|
|
+ nextEndShow: false,
|
|
|
+ removeTitle: '',
|
|
|
+ removeContent: '',
|
|
|
+ removeCourseStatus: false, // 是否布置作业
|
|
|
+
|
|
|
+ teacherChapterName: '',
|
|
|
+ lessonPreTrainingId: null,
|
|
|
+ selectResourceStatus: false,
|
|
|
+ videoState: 'init' as 'init' | 'play',
|
|
|
+ videoItemRef: null as any,
|
|
|
+ animationState: 'start' as 'start' | 'end'
|
|
|
+ });
|
|
|
+ const activeData = reactive({
|
|
|
+ isAutoPlay: false, // 是否自动播放
|
|
|
+ nowTime: 0,
|
|
|
+ model: true, // 遮罩
|
|
|
+ isAnimation: true, // 是否动画
|
|
|
+ // videoBtns: true, // 视频
|
|
|
+ // currentTime: 0,
|
|
|
+ // duration: 0,
|
|
|
+ timer: null as any,
|
|
|
+ item: null as any
|
|
|
+ });
|
|
|
+
|
|
|
+ // 键盘事件监听状态
|
|
|
+ const listenerKeyUpState = ref(false);
|
|
|
+
|
|
|
+ const getDetail = async () => {
|
|
|
+ try {
|
|
|
+ const res = await api_teacherChapterLessonCoursewareDetail(
|
|
|
+ data.courseId
|
|
|
+ );
|
|
|
+
|
|
|
+ data.teacherChapterName = res.data.name || '';
|
|
|
+ // 布置的作业编号
|
|
|
+ data.lessonPreTrainingId = res.data.lessonPreTrainingId;
|
|
|
+ // activeData.isAutoPlay = res.data.autoPlay || false; // 自动播放
|
|
|
+ const tempRows = res.data.chapterKnowledgeList || [];
|
|
|
+ const temp: any = [];
|
|
|
+ const allItem: any = [];
|
|
|
+ tempRows.forEach((row: any, index: number) => {
|
|
|
+ if (!Array.isArray(row.chapterKnowledgeMaterialList)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const childList: any[] = [];
|
|
|
+ row.chapterKnowledgeMaterialList.forEach((child: any) => {
|
|
|
+ if (!child.removeFlag) {
|
|
|
+ childList.push({
|
|
|
+ id: child.id,
|
|
|
+ materialId: child.bizId,
|
|
|
+ coverImg: child.bizInfo.coverImg,
|
|
|
+ type: child.type,
|
|
|
+ title: child.bizInfo.name,
|
|
|
+ dataJson: child.dataJson,
|
|
|
+ isCollect: !!child.favoriteFlag,
|
|
|
+ isSelected: child.source === 'PLATFORM' ? true : false,
|
|
|
+ content: child.bizInfo.content,
|
|
|
+ parentIndex: index
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ temp.push({
|
|
|
+ title: row.name,
|
|
|
+ list: childList
|
|
|
+ });
|
|
|
+ allItem.push(...childList);
|
|
|
+ });
|
|
|
+
|
|
|
+ data.knowledgePointList = temp;
|
|
|
+ data.itemList = allItem?.map((m: any) => {
|
|
|
+ return {
|
|
|
+ ...m,
|
|
|
+ iframeRef: null,
|
|
|
+ videoEle: null,
|
|
|
+ audioEle: null,
|
|
|
+ autoPlay: res.data.autoPlay || false, //加载完成是否自动播放
|
|
|
+ isprepare: false, // 视频是否加载完成
|
|
|
+ isRender: false // 是否渲染了
|
|
|
+ };
|
|
|
+ });
|
|
|
+ setTimeout(() => {
|
|
|
+ data.animationState = 'end';
|
|
|
+ }, 500);
|
|
|
+ } catch (e) {
|
|
|
+ //
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const showModalBeat = ref(false);
|
|
|
+ const showModalTone = ref(false);
|
|
|
+ const showModalTime = ref(false);
|
|
|
+ // ifram事件处理
|
|
|
+ const iframeHandle = (ev: MessageEvent) => {
|
|
|
+ // console.log(ev.data?.api, ev.data, 'ev.data');
|
|
|
+ if (ev.data?.api === 'headerTogge') {
|
|
|
+ activeData.model =
|
|
|
+ ev.data.show || (ev.data.playState == 'play' ? false : true);
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ if (ev.data?.api === 'onAttendToggleMenu') {
|
|
|
+ activeData.model = !activeData.model;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ev.data?.api === 'api_fingerPreView') {
|
|
|
+ clearInterval(activeData.timer);
|
|
|
+ activeData.model = !ev.data.state;
|
|
|
+ }
|
|
|
+ //
|
|
|
+ if (ev.data?.api === 'documentBodyKeyup') {
|
|
|
+ if (ev.data?.code === 'ArrowUp') {
|
|
|
+ setModalOpen();
|
|
|
+ handlePreAndNext('up');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ev.data?.code === 'ArrowDown') {
|
|
|
+ setModalOpen();
|
|
|
+ handlePreAndNext('down');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 点名返回
|
|
|
+ if (ev.data?.api === 'callBack') {
|
|
|
+ closeStudyTool();
|
|
|
+ studyData.callShow = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ev.data?.api === 'onLogin') {
|
|
|
+ const documentDom: any = document;
|
|
|
+ documentDom.exitFullscreen
|
|
|
+ ? documentDom.exitFullscreen()
|
|
|
+ : documentDom.mozCancelFullScreen
|
|
|
+ ? documentDom.mozCancelFullScreen()
|
|
|
+ : documentDom.webkitExitFullscreen
|
|
|
+ ? documentDom.webkitExitFullscreen()
|
|
|
+ : '';
|
|
|
+ users.logout();
|
|
|
+ router.replace('/login');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ onMounted(async () => {
|
|
|
+ // initMoveable();
|
|
|
+ const query = route.query;
|
|
|
+ // console.log(query, props.preStudentNum, '学生人数');
|
|
|
+ // 先取参数,
|
|
|
+ data.type = props.type || (query.type as any);
|
|
|
+ data.courseId = props.courseId || query.courseId;
|
|
|
+ data.instrumentId = props.instrumentId || query.instrumentId;
|
|
|
+ data.detailId = props.detailId || query.detailId;
|
|
|
+ data.lessonCourseId = props.lessonCourseId || query.lessonCourseId;
|
|
|
+ data.classGroupId = props.classGroupId || query.classGroupId;
|
|
|
+ data.classId = props.classId || query.classId;
|
|
|
+ data.preStudentNum = props.preStudentNum || query.preStudentNum;
|
|
|
+ window.addEventListener('message', iframeHandle);
|
|
|
+
|
|
|
+ if (data.classId) {
|
|
|
+ const res = await api_cousseScheduleDetail(data.classId);
|
|
|
+ data.courseId = res.data.useChapterLessonCoursewareId;
|
|
|
+ }
|
|
|
+
|
|
|
+ getDetail();
|
|
|
+ getLessonCoursewareDetail();
|
|
|
+ if (data.type === 'preview') {
|
|
|
+ // 预览隐藏点名和布置作业
|
|
|
+ const hideListIds = [2, 10];
|
|
|
+ let index = rightList.length - 1;
|
|
|
+ while (index >= 0) {
|
|
|
+ if (hideListIds.includes(rightList[index].id)) {
|
|
|
+ console.log(index);
|
|
|
+ rightList.splice(index, 1);
|
|
|
+ }
|
|
|
+ index--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rollCallStudentList();
|
|
|
+
|
|
|
+ window.addEventListener('online', handleOnline);
|
|
|
+ window.addEventListener('offline', handleOffline);
|
|
|
+ });
|
|
|
+ const lineTimer = ref();
|
|
|
+ const handleOnline = () => {
|
|
|
+ clearTimeout(lineTimer.value);
|
|
|
+ };
|
|
|
+ const handleOffline = () => {
|
|
|
+ lineTimer.value = setTimeout(() => {
|
|
|
+ message.info('请检查网络', {
|
|
|
+ showIcon: false,
|
|
|
+ render: (props: any) => {
|
|
|
+ return (
|
|
|
+ <div style="background: rgba(0,0,0,.6); color: #fff; border-radius: 8px; padding: 6px 16px;">
|
|
|
+ {props.content}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }, 3000);
|
|
|
+ };
|
|
|
+
|
|
|
+ // const onFullScreen = () => {
|
|
|
+ // if (data.type === 'preview') {
|
|
|
+ // const el: any = document.querySelector('#app');
|
|
|
+
|
|
|
+ // if (el.mozRequestFullScreen) {
|
|
|
+ // el.mozRequestFullScreen();
|
|
|
+ // } else if (el.webkitRequestFullscreen) {
|
|
|
+ // el.webkitRequestFullscreen();
|
|
|
+ // } else if (el.requestFullScreen) {
|
|
|
+ // el.requestFullscreen();
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // };
|
|
|
+
|
|
|
+ const popupData = reactive({
|
|
|
+ open: false,
|
|
|
+ activeIndex: 0,
|
|
|
+ courseActiveIndex: 0, // 课件选择的第几个
|
|
|
+ toolOpen: false, // 工具弹窗控制
|
|
|
+ chapterOpen: false, // 切换章节
|
|
|
+ chapterDetails: [] as any,
|
|
|
+ courseId: null as any, // 章节编号
|
|
|
+ chapterLoading: false // 加载数据
|
|
|
+ });
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => [popupData.open, popupData.chapterOpen],
|
|
|
+ val => {
|
|
|
+ // 为了处理window电脑滑动时的问题 - pointr-events
|
|
|
+ setTimeout(() => {
|
|
|
+ const drawers = document.querySelectorAll('.n-drawer-container');
|
|
|
+ if (val[0] || val[1]) {
|
|
|
+ drawers?.forEach(drawer => {
|
|
|
+ drawer.classList.remove('n-drawer-container-relative');
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ drawers?.forEach(drawer => {
|
|
|
+ drawer.classList.add('n-drawer-container-relative');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
+ );
|
|
|
+ const formatParentId = (id: any, list: any, ids = [] as any) => {
|
|
|
+ for (const item of list) {
|
|
|
+ if (item.knowledgeList && item.knowledgeList.length > 0) {
|
|
|
+ const cIds: any = formatParentId(id, item.knowledgeList, [
|
|
|
+ ...ids,
|
|
|
+ item.id
|
|
|
+ ]);
|
|
|
+ if (cIds.includes(id)) {
|
|
|
+ return cIds;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (item.id === id) {
|
|
|
+ return [...ids, id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ids;
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 获取章节 */
|
|
|
+ const getLessonCoursewareDetail = async () => {
|
|
|
+ try {
|
|
|
+ const res = await lessonCoursewareDetail({
|
|
|
+ id: data.lessonCourseId,
|
|
|
+ instrumentId: data.instrumentId
|
|
|
+ });
|
|
|
+
|
|
|
+ popupData.chapterDetails = res.data.lessonList || [];
|
|
|
+
|
|
|
+ const ids = formatParentId(data.detailId, popupData.chapterDetails);
|
|
|
+ data.lessonCoursewareDetailId = ids[0];
|
|
|
+ console.log(res.data, 'data');
|
|
|
+ data.lessonCoursewareSubjectList = res.data.instrumentList || [];
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /** 更新上课记录 */
|
|
|
+ const classCourseScheduleUpdate = async () => {
|
|
|
+ try {
|
|
|
+ if (!data.classId) return;
|
|
|
+ await courseScheduleUpdate({
|
|
|
+ lessonCoursewareKnowledgeDetailId: data.detailId,
|
|
|
+ id: data.classId
|
|
|
+ });
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const activeName = computed(() => {
|
|
|
+ let name = '';
|
|
|
+ popupData.chapterDetails.forEach((chapter: any) => {
|
|
|
+ if (chapter.id === data.lessonCoursewareDetailId) {
|
|
|
+ // name = chapter.name;
|
|
|
+ chapter.knowledgeList?.forEach((know: any) => {
|
|
|
+ if (know.id === data.detailId) {
|
|
|
+ name = know.name;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return name;
|
|
|
+ });
|
|
|
+
|
|
|
+ /**停止所有的播放 */
|
|
|
+ const handleStop = (isStop = true) => {
|
|
|
+ // console.log(isStop, 'stop');
|
|
|
+ for (let i = 0; i < data.itemList.length; i++) {
|
|
|
+ const activeItem = data.itemList[i];
|
|
|
+ if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
|
|
|
+ try {
|
|
|
+ if (isStop) {
|
|
|
+ activeItem.videoEle?.currentTime(0);
|
|
|
+ }
|
|
|
+ activeItem.videoEle?.pause();
|
|
|
+ } catch (e: any) {
|
|
|
+ // console.log(e, 'e');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (activeItem.type === 'SONG' && activeItem.audioEle) {
|
|
|
+ activeItem.audioEle?.stop();
|
|
|
+ }
|
|
|
+ // console.log('🚀 ~ activeItem:', activeItem)
|
|
|
+ // 停止曲谱的播放
|
|
|
+ if (activeItem.type === 'MUSIC') {
|
|
|
+ activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
+ { api: 'setPlayState' },
|
|
|
+ '*'
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (
|
|
|
+ activeItem.type === 'INSTRUMENT' ||
|
|
|
+ activeItem.type === 'MUSICIAN' ||
|
|
|
+ activeItem.type === 'MUSIC_WIKI'
|
|
|
+ ) {
|
|
|
+ activeItem.iframeRef?.handleChangeAudio('pause');
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log(activeItem.type, 'activeItem.type');
|
|
|
+ if (activeItem.type === 'RHYTHM') {
|
|
|
+ activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
+ { api: 'setPlayState', data: false },
|
|
|
+ '*'
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (activeItem.type === 'LISTEN') {
|
|
|
+ activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
+ { api: 'setPlayState' },
|
|
|
+ '*'
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 切换素材
|
|
|
+ const toggleMaterial = (itemActive: any) => {
|
|
|
+ const index = data.itemList.findIndex((n: any) => n.id == itemActive);
|
|
|
+ if (index > -1) {
|
|
|
+ handleSwipeChange(index);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /** 延迟收起模态框 */
|
|
|
+ const setModelOpen = () => {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ message.destroyAll();
|
|
|
+ activeData.timer = setTimeout(() => {
|
|
|
+ activeData.model = false;
|
|
|
+ Object.values(data.videoRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(false)
|
|
|
+ );
|
|
|
+
|
|
|
+ Object.values(data.audioRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(false)
|
|
|
+ );
|
|
|
+ }, 4000);
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 立即收起所有的模态框 */
|
|
|
+ const clearModel = () => {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ message.destroyAll();
|
|
|
+ activeData.model = false;
|
|
|
+ Object.values(data.videoRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(false)
|
|
|
+ );
|
|
|
+ Object.values(data.audioRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(false)
|
|
|
+ );
|
|
|
+ };
|
|
|
+ const toggleModel = (type = true) => {
|
|
|
+ activeData.model = type;
|
|
|
+ Object.values(data.videoRefs).map((n: any) => n?.toggleHideControl(type));
|
|
|
+ Object.values(data.audioRefs).map((n: any) => n?.toggleHideControl(type));
|
|
|
+ };
|
|
|
+
|
|
|
+ // 双击
|
|
|
+ const handleDbClick = (item: any) => {
|
|
|
+ if (item && item.type === 'VIDEO') {
|
|
|
+ const videoEle: HTMLVideoElement = item.videoEle;
|
|
|
+ if (videoEle) {
|
|
|
+ if (videoEle.paused) {
|
|
|
+ message.destroyAll();
|
|
|
+ videoEle.play();
|
|
|
+ } else {
|
|
|
+ message.warning('已暂停');
|
|
|
+ videoEle.pause();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // ppt iframe 点击事件
|
|
|
+ // const iframeClick = () => {
|
|
|
+ // if(document.all) {
|
|
|
+ // document.getElementById("iframe-ppt")?.attachEvent("click", () => {
|
|
|
+ // activeData.model = !activeData.model
|
|
|
+ // });
|
|
|
+ // } else {
|
|
|
+ // document.getElementById("iframe-ppt")?.contentWindow?.postMessage({
|
|
|
+ // api: 'onAttendToggleMenu'
|
|
|
+ // }, '*');
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 切换播放
|
|
|
+ // const togglePlay = (m: any, isPlay: boolean) => {
|
|
|
+ // if (isPlay) {
|
|
|
+ // m.videoEle?.play();
|
|
|
+ // } else {
|
|
|
+ // m.videoEle?.pause();
|
|
|
+ // }
|
|
|
+ // };
|
|
|
+
|
|
|
+ // const showIndex = ref(-4);
|
|
|
+ const effectIndex = ref(3);
|
|
|
+ const effects = [
|
|
|
+ {
|
|
|
+ prev: {
|
|
|
+ transform: 'translate3d(0, 0, -800px) rotateX(180deg)'
|
|
|
+ },
|
|
|
+ next: {
|
|
|
+ transform: 'translate3d(0, 0, -800px) rotateX(-180deg)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prev: {
|
|
|
+ transform: 'translate3d(-100%, 0, -800px)'
|
|
|
+ },
|
|
|
+ next: {
|
|
|
+ transform: 'translate3d(100%, 0, -800px)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prev: {
|
|
|
+ transform: 'translate3d(-50%, 0, -800px) rotateY(80deg)'
|
|
|
+ },
|
|
|
+ next: {
|
|
|
+ transform: 'translate3d(50%, 0, -800px) rotateY(-80deg)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prev: {
|
|
|
+ transform: 'translate3d(-100%, 0, -800px) rotateY(-120deg)'
|
|
|
+ },
|
|
|
+ next: {
|
|
|
+ transform: 'translate3d(100%, 0, -800px) rotateY(120deg)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 风车4
|
|
|
+ {
|
|
|
+ prev: {
|
|
|
+ transform: 'translate3d(-50%, 50%, -800px) rotateZ(-14deg)',
|
|
|
+ opacity: 0
|
|
|
+ },
|
|
|
+ next: {
|
|
|
+ transform: 'translate3d(50%, 50%, -800px) rotateZ(14deg)',
|
|
|
+ opacity: 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 翻页5
|
|
|
+ {
|
|
|
+ prev: {
|
|
|
+ transform: 'translateZ(-800px) rotate3d(0, -1, 0, 90deg)',
|
|
|
+ opacity: 0
|
|
|
+ },
|
|
|
+ next: {
|
|
|
+ transform: 'translateZ(-800px) rotate3d(0, 1, 0, 90deg)',
|
|
|
+ opacity: 0
|
|
|
+ },
|
|
|
+ current: { transitionDelay: '700ms' }
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ const acitveTimer = ref();
|
|
|
+ // 轮播切换
|
|
|
+ const handleSwipeChange = (index: number) => {
|
|
|
+ // 如果是当前正在播放 或者是视频最后一个
|
|
|
+ if (popupData.activeIndex == index) return;
|
|
|
+ data.animationState = 'start';
|
|
|
+ data.videoState = 'init';
|
|
|
+ handleStop();
|
|
|
+ clearTimeout(acitveTimer.value);
|
|
|
+ activeData.model = true;
|
|
|
+ checkedAnimation(popupData.activeIndex, index);
|
|
|
+ popupData.activeIndex = index;
|
|
|
+
|
|
|
+ // 处理资源列表滚动
|
|
|
+ nextTick(() => {
|
|
|
+ scrollResourceSection();
|
|
|
+ });
|
|
|
+
|
|
|
+ acitveTimer.value = setTimeout(
|
|
|
+ () => {
|
|
|
+ const item = data.itemList[index];
|
|
|
+
|
|
|
+ if (item) {
|
|
|
+ if (item.type == 'MUSIC') {
|
|
|
+ activeData.model = true;
|
|
|
+ }
|
|
|
+ if (item.type === 'SONG') {
|
|
|
+ // 自动播放下一个音频
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ message.destroyAll();
|
|
|
+ // item.autoPlay = false;
|
|
|
+ // nextTick(() => {
|
|
|
+ // item.audioEle?.onPlay();
|
|
|
+ // });
|
|
|
+ }
|
|
|
+ if (item.type === 'VIDEO') {
|
|
|
+ // 自动播放下一个视频
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ message.destroyAll();
|
|
|
+ nextTick(() => {
|
|
|
+ if (item.error) {
|
|
|
+ // console.log(item, 'item error');
|
|
|
+ item.videoEle?.src(item.content);
|
|
|
+ item.error = false;
|
|
|
+ // item.videoEle?.onPlay();
|
|
|
+ }
|
|
|
+ data.animationState = 'end';
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (item.type === 'PPT') {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ activeData.isAnimation ? 800 : 0
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 是否有转场动画 */
|
|
|
+ const checkedAnimation = (index: number, nextIndex?: number) => {
|
|
|
+ const item = data.itemList[index];
|
|
|
+ const nextItem = data.itemList[nextIndex!];
|
|
|
+ if (nextItem) {
|
|
|
+ if (nextItem.knowledgePointId != item.knowledgePointId) {
|
|
|
+ activeData.isAnimation = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const videoEle = item.videoEle;
|
|
|
+ const nextVideo = nextItem.videoEle;
|
|
|
+ if (videoEle && videoEle.duration < 8 && index < nextIndex!) {
|
|
|
+ activeData.isAnimation = false;
|
|
|
+ } else if (nextVideo && nextVideo.duration < 8 && index > nextIndex!) {
|
|
|
+ activeData.isAnimation = false;
|
|
|
+ } else {
|
|
|
+ activeData.isAnimation = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ activeData.isAnimation = item?.adviseStudyTimeSecond < 8 ? false : true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 上一个知识点, 下一个知识点
|
|
|
+ const handlePreAndNext = async (type: string) => {
|
|
|
+ if (type === 'up') {
|
|
|
+ // 判断上面是否还有章节
|
|
|
+ if (popupData.activeIndex > 0) {
|
|
|
+ handleSwipeChange(popupData.activeIndex - 1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前是哪个章节
|
|
|
+ let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
+ (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
+ );
|
|
|
+ const detailItem =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let lessonIndex = detailItem.findIndex(
|
|
|
+ (item: any) => item.id == data.detailId
|
|
|
+ );
|
|
|
+
|
|
|
+ let lessonStatus = false; // 当前章节上面是否有内容
|
|
|
+ let lessonCoursewareDetailId = '';
|
|
|
+ let coursewareDetailKnowledgeId = '';
|
|
|
+ while (lessonIndex >= 0) {
|
|
|
+ lessonIndex--;
|
|
|
+
|
|
|
+ if (lessonIndex >= 0) {
|
|
|
+ if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
+ lessonStatus = true;
|
|
|
+ lessonCoursewareDetailId =
|
|
|
+ detailItem[lessonIndex].lessonCoursewareDetailId;
|
|
|
+ coursewareDetailKnowledgeId = detailItem[lessonIndex].id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lessonStatus) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
+ if (lessonStatus) {
|
|
|
+ popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
+ data.selectClassStatus = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let prevLessonStatus = false;
|
|
|
+ while (detailIndex >= 0) {
|
|
|
+ detailIndex--;
|
|
|
+ const tempDetail =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let tempLessonLength = tempDetail.length;
|
|
|
+ while (tempLessonLength > 0) {
|
|
|
+ if (tempDetail[tempLessonLength - 1].coursewareNum > 0) {
|
|
|
+ prevLessonStatus = true;
|
|
|
+ lessonCoursewareDetailId =
|
|
|
+ tempDetail[tempLessonLength - 1].lessonCoursewareDetailId;
|
|
|
+ coursewareDetailKnowledgeId = tempDetail[tempLessonLength - 1].id;
|
|
|
+ }
|
|
|
+ tempLessonLength--;
|
|
|
+ if (prevLessonStatus) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (prevLessonStatus) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
+ if (prevLessonStatus) {
|
|
|
+ popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
+ data.selectClassStatus = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (popupData.activeIndex < data.itemList.length - 1) {
|
|
|
+ handleSwipeChange(popupData.activeIndex + 1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!isDownArrow.value) return;
|
|
|
+ data.nextEndShow = true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 当前课件结束之后选择下一个课件
|
|
|
+ function handleNextEnd() {
|
|
|
+ // 获取当前是哪个章节
|
|
|
+ let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
+ (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
+ );
|
|
|
+ const detailItem =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let lessonIndex = detailItem.findIndex(
|
|
|
+ (item: any) => item.id == data.detailId
|
|
|
+ );
|
|
|
+
|
|
|
+ let lessonStatus = false; // 当前章节下面是否有内容
|
|
|
+ let lessonCoursewareDetailId = '';
|
|
|
+ let coursewareDetailKnowledgeId = '';
|
|
|
+ while (lessonIndex < detailItem.length - 1) {
|
|
|
+ lessonIndex++;
|
|
|
+ if (lessonIndex >= 0) {
|
|
|
+ if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
+ lessonStatus = true;
|
|
|
+ lessonCoursewareDetailId =
|
|
|
+ detailItem[lessonIndex].lessonCoursewareDetailId;
|
|
|
+ coursewareDetailKnowledgeId = detailItem[lessonIndex].id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (lessonStatus) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 判断当前章节下面课程是否有内容,否则往下一个章节走
|
|
|
+ if (lessonStatus) {
|
|
|
+ popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
+ data.selectClassStatus = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let nextLessonStatus = false;
|
|
|
+ while (detailIndex <= popupData.chapterDetails.length - 1) {
|
|
|
+ detailIndex++;
|
|
|
+ const tempDetail =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let tempLessonLength = 0;
|
|
|
+ while (tempLessonLength <= tempDetail.length - 1) {
|
|
|
+ if (tempDetail[tempLessonLength].coursewareNum > 0) {
|
|
|
+ nextLessonStatus = true;
|
|
|
+ lessonCoursewareDetailId =
|
|
|
+ tempDetail[tempLessonLength].lessonCoursewareDetailId;
|
|
|
+ coursewareDetailKnowledgeId = tempDetail[tempLessonLength].id;
|
|
|
+ }
|
|
|
+ tempLessonLength++;
|
|
|
+ if (nextLessonStatus) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nextLessonStatus) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
+ if (nextLessonStatus) {
|
|
|
+ popupData.courseId = coursewareDetailKnowledgeId;
|
|
|
+ data.selectClassStatus = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /** 弹窗关闭 */
|
|
|
+ const handleClosePopup = () => {
|
|
|
+ const item = data.itemList[popupData.activeIndex];
|
|
|
+ if (item?.type == 'VIDEO' && !item.videoEle?.paused) {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (item?.type == 'SONG' && !item.audioEle?.paused) {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ document.body.addEventListener('keyup', (e: KeyboardEvent) => {
|
|
|
+ if (e.code === 'ArrowUp') {
|
|
|
+ // if (popupData.activeIndex === 0) return;
|
|
|
+ setModalOpen();
|
|
|
+ handlePreAndNext('up');
|
|
|
+ } else if (e.code === 'ArrowDown') {
|
|
|
+ // if (popupData.activeIndex === data.itemList.length - 1) return;
|
|
|
+ setModalOpen();
|
|
|
+ handlePreAndNext('down');
|
|
|
+ } else if (e.code === 'Space') {
|
|
|
+ // const activeItem = data.itemList[popupData.activeIndex];
|
|
|
+ // console.log(activeItem, activeItem.videoEle);
|
|
|
+ // // 暂停视频和曲谱的播放
|
|
|
+ // if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
|
|
|
+ // activeItem.videoEle?.play();
|
|
|
+ // }
|
|
|
+ // if (activeItem.type === 'SONG' && activeItem.audioEle) {
|
|
|
+ // activeItem.audioEle?.play();
|
|
|
+ // }
|
|
|
+ // if (activeItem.type === 'MUSIC') {
|
|
|
+ // activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
+ // { api: 'setPlayState' },
|
|
|
+ // '*'
|
|
|
+ // );
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // const toggleListenerKeyUp = (type: string) => {
|
|
|
+ // if (type === 'remove') {
|
|
|
+ // document.body.removeEventListener('keyup', () => {
|
|
|
+ // listenerKeyUpState.value = false;
|
|
|
+ // });
|
|
|
+ // } else {
|
|
|
+ // // 监听页面键盘事件 - 上下切换
|
|
|
+ // document.body.addEventListener('keyup', (e: KeyboardEvent) => {
|
|
|
+ // // console.log(e, 'e');
|
|
|
+ // if (e.code === 'ArrowLeft') {
|
|
|
+ // // if (popupData.activeIndex === 0) return;
|
|
|
+ // setModalOpen();
|
|
|
+ // handlePreAndNext('up');
|
|
|
+ // } else if (e.code === 'ArrowRight') {
|
|
|
+ // // if (popupData.activeIndex === data.itemList.length - 1) return;
|
|
|
+ // setModalOpen();
|
|
|
+ // handlePreAndNext('down');
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // listenerKeyUpState.value = true;
|
|
|
+ // }
|
|
|
+ // };
|
|
|
+
|
|
|
+ // 监听切换到ppt课件时,手动移除键盘监听器
|
|
|
+ // watch(() => popupData.activeIndex, () => {
|
|
|
+ // const activeItem = data.itemList[popupData.activeIndex];
|
|
|
+ // if (activeItem?.type === 'PPT') {
|
|
|
+ // toggleListenerKeyUp('remove')
|
|
|
+ // } else {
|
|
|
+ // !listenerKeyUpState.value && toggleListenerKeyUp('add')
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ watch(
|
|
|
+ () => popupData.activeIndex,
|
|
|
+ () => {
|
|
|
+ const item = data.itemList[popupData.activeIndex];
|
|
|
+ popupData.courseActiveIndex = item.parentIndex;
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const setModalOpen = (status = true) => {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ activeData.model = status;
|
|
|
+ Object.values(data.videoRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(status)
|
|
|
+ );
|
|
|
+ Object.values(data.audioRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(status)
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 教学数据 */
|
|
|
+ const studyData = reactive({
|
|
|
+ type: '' as ToolType,
|
|
|
+ penShow: false,
|
|
|
+ whiteboardShow: false,
|
|
|
+ callShow: false,
|
|
|
+ callStudentList: [] as any // 学生列表
|
|
|
+ });
|
|
|
+
|
|
|
+ /** 打开教学工具 */
|
|
|
+ const openStudyTool = (item: ToolItem) => {
|
|
|
+ handleStop(false);
|
|
|
+ clearModel();
|
|
|
+ popupData.toolOpen = false;
|
|
|
+ studyData.type = item.type;
|
|
|
+
|
|
|
+ switch (item.type) {
|
|
|
+ case 'pen':
|
|
|
+ studyData.penShow = true;
|
|
|
+ break;
|
|
|
+ case 'whiteboard':
|
|
|
+ studyData.whiteboardShow = true;
|
|
|
+ break;
|
|
|
+ case 'call':
|
|
|
+ studyData.callShow = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 关闭教学工具 */
|
|
|
+ const closeStudyTool = () => {
|
|
|
+ studyData.type = 'init';
|
|
|
+ toggleModel();
|
|
|
+ setModelOpen();
|
|
|
+ };
|
|
|
+
|
|
|
+ const startShowModal = (
|
|
|
+ val: 'setTimeIcon' | 'beatIcon' | 'toneIcon' | 'iconNote2'
|
|
|
+ ) => {
|
|
|
+ if (val == 'setTimeIcon') {
|
|
|
+ showModalTime.value = true;
|
|
|
+ }
|
|
|
+ if (val == 'beatIcon') {
|
|
|
+ showModalBeat.value = true;
|
|
|
+ }
|
|
|
+ if (val == 'toneIcon') {
|
|
|
+ showModalTone.value = true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 是否允许上一页
|
|
|
+ const isUpArrow = computed(() => {
|
|
|
+ /**
|
|
|
+ * 1,判断当前课程中是否处在第一个资源;
|
|
|
+ * 2,判断当前课程是否在当前章节的第一个;
|
|
|
+ * 3,判断当前章节,当前课程上面还没有其它课程,是否有资源;
|
|
|
+ * 4,判断当前章节上面还没有其它章节;
|
|
|
+ * 5,判断上面章节里面课程是否有资源;
|
|
|
+ */
|
|
|
+ if (popupData.activeIndex > 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前是哪个章节
|
|
|
+ let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
+ (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
+ );
|
|
|
+ const detailItem =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let lessonIndex = detailItem.findIndex(
|
|
|
+ (item: any) => item.id == data.detailId
|
|
|
+ );
|
|
|
+
|
|
|
+ // 说明已经是第一单元,第一课
|
|
|
+ if (detailIndex <= 0 && lessonIndex <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ let lessonStatus = false; // 当前章节上面是否有内容
|
|
|
+ while (lessonIndex >= 0) {
|
|
|
+ lessonIndex--;
|
|
|
+
|
|
|
+ if (lessonIndex >= 0) {
|
|
|
+ if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
+ lessonStatus = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 判断当前章节下面课程是否有内容,否则往上一个章节走
|
|
|
+ if (lessonStatus) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 已经是第一个章节了
|
|
|
+ if (detailIndex <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ let prevLessonStatus = false;
|
|
|
+ while (detailIndex >= 0) {
|
|
|
+ detailIndex--;
|
|
|
+ const tempDetail =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let tempLessonLength = tempDetail.length;
|
|
|
+ while (tempLessonLength > 0) {
|
|
|
+ if (tempDetail[tempLessonLength - 1].coursewareNum > 0) {
|
|
|
+ prevLessonStatus = true;
|
|
|
+ }
|
|
|
+ tempLessonLength--;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (prevLessonStatus) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 是否允许下一页
|
|
|
+ const isDownArrow = computed(() => {
|
|
|
+ if (popupData.activeIndex < data.itemList.length - 1) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前是哪个章节
|
|
|
+ let detailIndex = popupData.chapterDetails.findIndex(
|
|
|
+ (item: any) => item.id == data.lessonCoursewareDetailId
|
|
|
+ );
|
|
|
+
|
|
|
+ const detailItem =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let lessonIndex = detailItem.findIndex(
|
|
|
+ (item: any) => item.id == data.detailId
|
|
|
+ );
|
|
|
+
|
|
|
+ // 说明已经是最后-单元,最后一课
|
|
|
+ if (
|
|
|
+ detailIndex >= popupData.chapterDetails.length - 1 &&
|
|
|
+ lessonIndex >= detailItem.length - 1
|
|
|
+ ) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ let lessonStatus = false; // 当前章节下面是否有内容
|
|
|
+ while (lessonIndex < detailItem.length - 1) {
|
|
|
+ lessonIndex++;
|
|
|
+ if (lessonIndex >= 0) {
|
|
|
+ if (detailItem[lessonIndex].coursewareNum > 0) {
|
|
|
+ lessonStatus = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 判断当前章节下面课程是否有内容,否则往下一个章节走
|
|
|
+ if (lessonStatus) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 已经是最后一个章节了
|
|
|
+ if (detailIndex >= popupData.chapterDetails.length - 1) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ let nextLessonStatus = false;
|
|
|
+ while (detailIndex < popupData.chapterDetails.length - 1) {
|
|
|
+ detailIndex++;
|
|
|
+ const tempDetail =
|
|
|
+ popupData.chapterDetails[detailIndex]?.knowledgeList || [];
|
|
|
+ let tempLessonLength = 0;
|
|
|
+ while (tempLessonLength <= tempDetail.length - 1) {
|
|
|
+ if (tempDetail[tempLessonLength].coursewareNum > 0) {
|
|
|
+ nextLessonStatus = true;
|
|
|
+ }
|
|
|
+ tempLessonLength++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nextLessonStatus) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+ const activeVideoItem = computed(() => {
|
|
|
+ const item = data.itemList[popupData.activeIndex];
|
|
|
+ if (item && item.type && item.type.toLocaleUpperCase() === 'VIDEO') {
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ return {};
|
|
|
+ });
|
|
|
+
|
|
|
+ // 右侧菜单栏
|
|
|
+ const rightList = reactive([
|
|
|
+ {
|
|
|
+ name: '上一个',
|
|
|
+ icon: bottomIconPre,
|
|
|
+ id: 11
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '下一个',
|
|
|
+ icon: bottomIconNext,
|
|
|
+ id: 12
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '切换章节',
|
|
|
+ icon: bottomIconSwitch,
|
|
|
+ id: 13
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '资源列表',
|
|
|
+ icon: bottomIconResource,
|
|
|
+ id: 14
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '曲目资源',
|
|
|
+ icon: rightIconMusic,
|
|
|
+ id: 9
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '点名',
|
|
|
+ icon: rightIconCall,
|
|
|
+ id: 10
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '布置作业',
|
|
|
+ icon: rightIconArrange,
|
|
|
+ id: 2
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '工具箱',
|
|
|
+ icon: rightIconTool,
|
|
|
+ id: 15
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '结束课程',
|
|
|
+ name2: '结束预览',
|
|
|
+ icon: rightIconEnd,
|
|
|
+ id: 1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '收起',
|
|
|
+ icon: leftIconPackUp,
|
|
|
+ id: 8
|
|
|
+ }
|
|
|
+ ]);
|
|
|
+ const tooltipList = [
|
|
|
+ {
|
|
|
+ name: '节拍器',
|
|
|
+ icon: rightIconMetronome,
|
|
|
+ id: 5
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '计时器',
|
|
|
+ icon: rightIconTimer,
|
|
|
+ id: 7
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '批注',
|
|
|
+ icon: rightIconPostil,
|
|
|
+ id: 3
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '白板',
|
|
|
+ icon: rightIconWhiteboard,
|
|
|
+ id: 4
|
|
|
+ }
|
|
|
+ // {
|
|
|
+ // name: '调音器',
|
|
|
+ // icon: rightIconTuner,
|
|
|
+ // id: 6
|
|
|
+ // }
|
|
|
+ ];
|
|
|
+ // 默认收起菜单
|
|
|
+ const columnShow = ref(true);
|
|
|
+ // 菜单位置
|
|
|
+ const columnPos = ref<'left' | 'right'>('left');
|
|
|
+ watch(columnPos, () => {
|
|
|
+ for (let i = 0; i < data.itemList.length; i++) {
|
|
|
+ const activeItem = data.itemList[i];
|
|
|
+ if (['RHYTHM', 'MUSIC'].includes(activeItem.type)) {
|
|
|
+ activeItem.iframeRef?.contentWindow?.postMessage(
|
|
|
+ { api: 'imagePos', data: columnPos.value },
|
|
|
+ '*'
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 右边栏操作
|
|
|
+ const operateRightBtn = async (id: number) => {
|
|
|
+ if (![8, 11, 12, 13, 14].includes(id)) {
|
|
|
+ handleStop(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (id) {
|
|
|
+ case 1:
|
|
|
+ if (data.type === 'preview') {
|
|
|
+ data.removeVisiable = true;
|
|
|
+ data.removeTitle = '结束预览';
|
|
|
+ data.removeContent = '请确认是否结束预览?';
|
|
|
+ } else {
|
|
|
+ const res = await getStudentAfterWork({
|
|
|
+ courseScheduleId: data.classId,
|
|
|
+ page: 1,
|
|
|
+ rows: 99
|
|
|
+ });
|
|
|
+ if (res.data.rows && res.data.rows.length) {
|
|
|
+ data.removeContent = '请确认是否结束课程?';
|
|
|
+ data.removeCourseStatus = false;
|
|
|
+ } else {
|
|
|
+ data.removeContent = '本次课堂尚未布置作业,是否结束课程?';
|
|
|
+ data.removeCourseStatus = true;
|
|
|
+ }
|
|
|
+ data.removeVisiable = true;
|
|
|
+ data.removeTitle = '结束课程';
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ // 学生人数必须大于0,才可以布置作业
|
|
|
+ if (data.preStudentNum <= 0) return;
|
|
|
+ // const res = await lessonPreTrainingPage({
|
|
|
+ // coursewareKnowledgeDetailId: data.detailId,
|
|
|
+ // instrumentId: data.instrumentId,
|
|
|
+ // page: 1,
|
|
|
+ // rows: 99
|
|
|
+ // });
|
|
|
+ // if (res.data.rows && res.data.rows.length) {
|
|
|
+ // data.modalAttendMessage = '本节课已设置课后作业,是否布置?';
|
|
|
+ // }
|
|
|
+ // data.modelAttendStatus = true;
|
|
|
+ const res = await getStudentAfterWork({
|
|
|
+ courseScheduleId: data.classId,
|
|
|
+ page: 1,
|
|
|
+ rows: 99
|
|
|
+ });
|
|
|
+ if (res.data.rows && res.data.rows.length) {
|
|
|
+ // data.modalAttendMessage = '请确认是否结束课程?';
|
|
|
+ data.modalAttendMessage = '本次课程已布置作业,是否继续?';
|
|
|
+ data.modelAttendStatus = true;
|
|
|
+ } else {
|
|
|
+ data.modelTrainStatus = true;
|
|
|
+ nextTick(() => {
|
|
|
+ getModalHeight();
|
|
|
+ });
|
|
|
+ data.modelAttendStatus = false;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ openStudyTool({
|
|
|
+ type: 'pen',
|
|
|
+ icon: iconNote,
|
|
|
+ name: '批注'
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ openStudyTool({
|
|
|
+ type: 'whiteboard',
|
|
|
+ icon: iconWhite,
|
|
|
+ name: '白板'
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ case 5:
|
|
|
+ startShowModal('beatIcon');
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ startShowModal('toneIcon');
|
|
|
+ break;
|
|
|
+ case 7:
|
|
|
+ startShowModal('setTimeIcon');
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ columnShow.value = false;
|
|
|
+ break;
|
|
|
+ case 9:
|
|
|
+ // 选择曲目时需要暂停所有播放
|
|
|
+ handleStop(false);
|
|
|
+ data.selectResourceStatus = true;
|
|
|
+ break;
|
|
|
+ case 10:
|
|
|
+ // 点名
|
|
|
+ // await rollCallStudentList();
|
|
|
+ if (studyData.callStudentList.length > 0) {
|
|
|
+ openStudyTool({
|
|
|
+ type: 'call',
|
|
|
+ icon: iconWhite,
|
|
|
+ name: '点名'
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 11:
|
|
|
+ if (!isUpArrow.value) return;
|
|
|
+ handlePreAndNext('up');
|
|
|
+ break;
|
|
|
+ case 12:
|
|
|
+ if (!isDownArrow.value) return;
|
|
|
+ handlePreAndNext('down');
|
|
|
+ break;
|
|
|
+ case 13:
|
|
|
+ popupData.chapterOpen = true;
|
|
|
+ break;
|
|
|
+ case 14:
|
|
|
+ popupData.open = true;
|
|
|
+ nextTick(() => {
|
|
|
+ scrollResourceSection();
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 点名学生列表
|
|
|
+ const rollCallStudentList = async () => {
|
|
|
+ //
|
|
|
+ if (!data.classId) return;
|
|
|
+ try {
|
|
|
+ const res = await getStudentList({
|
|
|
+ classGroupId: data.classGroupId,
|
|
|
+ page: 1,
|
|
|
+ rows: 999
|
|
|
+ });
|
|
|
+ const result = res.data || {};
|
|
|
+ if (Array.isArray(result.rows) && result.rows.length > 0) {
|
|
|
+ const tempStudents: any = [];
|
|
|
+ result.rows.forEach((row: any) => {
|
|
|
+ tempStudents.push({
|
|
|
+ name: row.nickname,
|
|
|
+ img: row.avatar
|
|
|
+ });
|
|
|
+ });
|
|
|
+ studyData.callStudentList = [...tempStudents];
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 滚动到某个元素的位置
|
|
|
+ const scrollResourceSection = () => {
|
|
|
+ const drawerCardItemRefs =
|
|
|
+ document.querySelectorAll('.drawerCardItemRef');
|
|
|
+ if (
|
|
|
+ popupData.activeIndex >= 0 &&
|
|
|
+ drawerCardItemRefs[popupData.activeIndex]
|
|
|
+ ) {
|
|
|
+ drawerCardItemRefs[popupData.activeIndex].scrollIntoView();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const getModalHeight = () => {
|
|
|
+ const dom: any = document.querySelector('#model-homework-height');
|
|
|
+ if (dom) {
|
|
|
+ useResizeObserver(dom as HTMLElement, (entries: any) => {
|
|
|
+ const entry = entries[0];
|
|
|
+ const { height } = entry.contentRect;
|
|
|
+ dom.style.setProperty('--window-page-lesson-height', height + 'px');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /* 弹窗加拖动 */
|
|
|
+ // 引导页
|
|
|
+ getGuidanceShow();
|
|
|
+ // 选择课件弹窗
|
|
|
+ const selCourBoxClass = 'selCourBoxClass_drag';
|
|
|
+ const selCourDragData = useDrag(
|
|
|
+ [`${selCourBoxClass}>.n-card-header`, `${selCourBoxClass} .bom_drag`],
|
|
|
+ selCourBoxClass,
|
|
|
+ toRef(data, 'selectClassStatus'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 选择资源弹窗
|
|
|
+ const selResourBoxClass = 'selResourBoxClass_drag';
|
|
|
+ const selResourDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${selResourBoxClass} .select-resource>.n-tabs>.n-tabs-nav--top.n-tabs-nav`,
|
|
|
+ `${selResourBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ selResourBoxClass,
|
|
|
+ toRef(data, 'selectResourceStatus'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 结束预览 结束课程确认弹窗
|
|
|
+ const removeResourBoxClass = 'removeResourBoxClass_drag';
|
|
|
+ const removeResourDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${removeResourBoxClass}>.n-card-header`,
|
|
|
+ `${removeResourBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ removeResourBoxClass,
|
|
|
+ toRef(data, 'removeVisiable'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 章节next弹窗
|
|
|
+ const nextEndBoxClass = 'nextEndBoxClass_drag';
|
|
|
+ const nextEndBoxDragData = useDrag(
|
|
|
+ [`${nextEndBoxClass}>.n-card-header`, `${nextEndBoxClass} .bom_drag`],
|
|
|
+ nextEndBoxClass,
|
|
|
+ toRef(data, 'nextEndShow'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 章节切换弹窗
|
|
|
+ const chapterConBoxClass = 'chapterConBoxClass_drag';
|
|
|
+ const chapterConBoxDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${chapterConBoxClass}>.n-card-header`,
|
|
|
+ `${chapterConBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ chapterConBoxClass,
|
|
|
+ toRef(popupData, 'chapterOpen'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 资源列表弹窗
|
|
|
+ const resourcesConBoxClass = 'resourcesConBoxClass_drag';
|
|
|
+ const resourcesConDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${resourcesConBoxClass}>.n-card-header`,
|
|
|
+ `${resourcesConBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ resourcesConBoxClass,
|
|
|
+ toRef(popupData, 'open'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 计时器
|
|
|
+ const timerMeterConBoxClass = 'timerMeterConBoxClass_drag';
|
|
|
+ const timerMeterConDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${timerMeterConBoxClass} .timeBomCon .bom_drag`,
|
|
|
+ `${timerMeterConBoxClass} .topDragDom`
|
|
|
+ ],
|
|
|
+ timerMeterConBoxClass,
|
|
|
+ showModalTime,
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 节拍器
|
|
|
+ const metronomeConBoxClass = 'metronomeConBoxClass_drag';
|
|
|
+ const metronomeConBoxDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${metronomeConBoxClass} .topDragDom`,
|
|
|
+ `${metronomeConBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ metronomeConBoxClass,
|
|
|
+ showModalBeat,
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 布置作业弹窗
|
|
|
+ const modelTrainStatusConBoxClass = 'modelTrainStatusConBoxClass_drag';
|
|
|
+ const modelTrainStatusConBoxDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${modelTrainStatusConBoxClass}>.n-card-header`,
|
|
|
+ `${modelTrainStatusConBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ modelTrainStatusConBoxClass,
|
|
|
+ toRef(data, 'modelTrainStatus'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ // 布置作业课后作业
|
|
|
+ const modelTrainHomeWordConBoxClass =
|
|
|
+ 'modelTrainHomeWordConBoxClassBoxClass_drag';
|
|
|
+ const modelTrainHomeWordConBoxDragData = useDrag(
|
|
|
+ [
|
|
|
+ `${modelTrainHomeWordConBoxClass}>.n-card-header`,
|
|
|
+ `${modelTrainHomeWordConBoxClass} .bom_drag`
|
|
|
+ ],
|
|
|
+ modelTrainHomeWordConBoxClass,
|
|
|
+ toRef(data, 'modelAttendStatus'),
|
|
|
+ users.info.id
|
|
|
+ );
|
|
|
+ return () => (
|
|
|
+ <div id="playContent" class={[styles.playContent, 'wrap']}>
|
|
|
+ <div
|
|
|
+ onClick={() => {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ activeData.model = !activeData.model;
|
|
|
+ Object.values(data.videoRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(activeData.model)
|
|
|
+ );
|
|
|
+ Object.values(data.audioRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(activeData.model)
|
|
|
+ );
|
|
|
+ }}>
|
|
|
+ <div
|
|
|
+ class={styles.coursewarePlay}
|
|
|
+ style={{ width: parentContainer.width }}>
|
|
|
+ {!popupData.chapterLoading ? (
|
|
|
+ <div class={styles.wraps}>
|
|
|
+ <div
|
|
|
+ style={
|
|
|
+ activeVideoItem.value.type &&
|
|
|
+ data.animationState === 'end' &&
|
|
|
+ data.videoState === 'play'
|
|
|
+ ? {
|
|
|
+ zIndex: 15,
|
|
|
+ opacity: 1
|
|
|
+ }
|
|
|
+ : { opacity: 0, zIndex: -1 }
|
|
|
+ }
|
|
|
+ class={styles.itemDiv}>
|
|
|
+ <VideoPlay
|
|
|
+ imagePos={columnPos.value}
|
|
|
+ ref={(el: any) => (data.videoItemRef = el)}
|
|
|
+ item={activeVideoItem.value}
|
|
|
+ showModel={activeData.model}
|
|
|
+ onClose={setModelOpen}
|
|
|
+ onLoadedmetadata={(videoItem: any) => {
|
|
|
+ if (data.itemList[popupData.activeIndex]) {
|
|
|
+ data.itemList[popupData.activeIndex].videoEle =
|
|
|
+ videoItem;
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onCanplay={() => {
|
|
|
+ data.videoState = 'play';
|
|
|
+ // activeVideoItem.value.videoEle = videoItem;
|
|
|
+ }}
|
|
|
+ onPause={() => {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ activeData.model = true;
|
|
|
+ }}
|
|
|
+ onEnded={() => {
|
|
|
+ // const _index = popupData.activeIndex + 1;
|
|
|
+ // if (_index < data.itemList.length) {
|
|
|
+ // handleSwipeChange(_index);
|
|
|
+ // }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ {data.itemList.map((m: any, mIndex: number) => {
|
|
|
+ const isRender = Math.abs(popupData.activeIndex - mIndex) < 2;
|
|
|
+ const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
|
|
|
+ // if (isRender && m.type === 'PPT') {
|
|
|
+ // setTimeout(() => iframeClick() ,500)
|
|
|
+ // }
|
|
|
+ // if (isRender) {
|
|
|
+ // m.isRender = true;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // const isRender =
|
|
|
+ // m.isRender || Math.abs(popupData.activeIndex - mIndex) < 2;
|
|
|
+ // const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
|
|
|
+ // if (isRender) {
|
|
|
+ // m.isRender = true;
|
|
|
+ // }
|
|
|
+
|
|
|
+ return isRender ? (
|
|
|
+ <div
|
|
|
+ key={'index' + mIndex}
|
|
|
+ class={[
|
|
|
+ styles.itemDiv,
|
|
|
+ popupData.activeIndex === mIndex && styles.itemActive,
|
|
|
+ activeData.isAnimation && styles.acitveAnimation,
|
|
|
+ Math.abs(popupData.activeIndex - mIndex) < 2
|
|
|
+ ? styles.show
|
|
|
+ : styles.hide
|
|
|
+ ]}
|
|
|
+ style={
|
|
|
+ mIndex < popupData.activeIndex
|
|
|
+ ? effects[effectIndex.value].prev
|
|
|
+ : mIndex > popupData.activeIndex
|
|
|
+ ? effects[effectIndex.value].next
|
|
|
+ : {}
|
|
|
+ }
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ if (Date.now() - activeData.nowTime < 300) {
|
|
|
+ handleDbClick(m);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ activeData.nowTime = Date.now();
|
|
|
+ activeData.timer = setTimeout(() => {
|
|
|
+ activeData.model = !activeData.model;
|
|
|
+ Object.values(data.videoRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(activeData.model)
|
|
|
+ );
|
|
|
+ Object.values(data.audioRefs).map((n: any) =>
|
|
|
+ n?.toggleHideControl(activeData.model)
|
|
|
+ );
|
|
|
+ if (activeData.model) {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+ }, 300);
|
|
|
+ }}>
|
|
|
+ {m.type === 'VIDEO' ? (
|
|
|
+ <>
|
|
|
+ <img
|
|
|
+ src={m.coverImg}
|
|
|
+ onLoad={() => {
|
|
|
+ m.isprepare = true;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ {/* <VideoPlay
|
|
|
+ ref={(v: any) => (data.videoRefs[mIndex] = v)}
|
|
|
+ item={m}
|
|
|
+ isEmtry={isEmtry}
|
|
|
+ onLoadedmetadata={(videoItem: any) => {
|
|
|
+ m.videoEle = videoItem;
|
|
|
+ m.isprepare = true;
|
|
|
+ }}
|
|
|
+ onTogglePlay={(paused: boolean) => {
|
|
|
+ m.autoPlay = false;
|
|
|
+ if (paused || popupData.open) {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ } else {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onReset={() => {
|
|
|
+ if (!m.videoEle?.paused) {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onError={() => {
|
|
|
+ console.log('video error');
|
|
|
+ m.error = true;
|
|
|
+ }}
|
|
|
+ /> */}
|
|
|
+ <Transition name="van-fade">
|
|
|
+ {
|
|
|
+ <div class={styles.loadWrap}>
|
|
|
+ <Vue3Lottie
|
|
|
+ animationData={playLoadData}></Vue3Lottie>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </Transition>
|
|
|
+ </>
|
|
|
+ ) : m.type === 'IMG' ? (
|
|
|
+ <img src={m.content} />
|
|
|
+ ) : m.type === 'SONG' ? (
|
|
|
+ <AudioPay
|
|
|
+ imagePos={columnPos.value}
|
|
|
+ item={m}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ ref={(v: any) => (data.audioRefs[mIndex] = v)}
|
|
|
+ onLoadedmetadata={(audioItem: any) => {
|
|
|
+ m.audioEle = audioItem;
|
|
|
+ m.isprepare = true;
|
|
|
+ }}
|
|
|
+ onTogglePlay={(paused: boolean) => {
|
|
|
+ // m.autoPlay = false;
|
|
|
+ if (paused || popupData.open) {
|
|
|
+ clearTimeout(activeData.timer);
|
|
|
+ } else {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onEnded={() => {
|
|
|
+ // const _index = popupData.activeIndex + 1;
|
|
|
+ // if (_index < data.itemList.length) {
|
|
|
+ // handleSwipeChange(_index);
|
|
|
+ // }
|
|
|
+ }}
|
|
|
+ onReset={() => {
|
|
|
+ if (!m.audioEle?.paused) {
|
|
|
+ setModelOpen();
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ) : // : m.type === 'PPT' ? <div class={styles.iframePpt}>
|
|
|
+ // <div class={styles.pptBox}></div>
|
|
|
+ // <iframe src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(m.content)}`} width='100%' height='100%' frameborder='1'></iframe>
|
|
|
+ // </div>
|
|
|
+ m.type === 'PPT' ? (
|
|
|
+ <iframe
|
|
|
+ src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(
|
|
|
+ m.content
|
|
|
+ )}`}
|
|
|
+ width="100%"
|
|
|
+ height="100%"
|
|
|
+ frameborder="1"></iframe>
|
|
|
+ ) : m.type === 'RHYTHM' ? (
|
|
|
+ <RhythmModal
|
|
|
+ item={m}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ imagePos={columnPos.value}
|
|
|
+ onSetIframe={(el: any) => {
|
|
|
+ m.iframeRef = el;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ) : m.type === 'LISTEN' ? (
|
|
|
+ <ListenModal
|
|
|
+ item={m}
|
|
|
+ data-vid={m.id}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ onSetIframe={(el: any) => {
|
|
|
+ m.iframeRef = el;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ) : m.type === 'INSTRUMENT' || m.type === 'MUSICIAN' ? (
|
|
|
+ <InstruemntDetail
|
|
|
+ type="preview"
|
|
|
+ id={m.content}
|
|
|
+ contentType={m.type}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ ref={(el: any) => (m.iframeRef = el)}
|
|
|
+ />
|
|
|
+ ) : m.type === 'MUSIC_WIKI' ? (
|
|
|
+ <MusicDetail
|
|
|
+ type="preview"
|
|
|
+ id={m.content}
|
|
|
+ contentType={m.type}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ ref={(el: any) => (m.iframeRef = el)}
|
|
|
+ />
|
|
|
+ ) : m.type === 'THEORY' ? (
|
|
|
+ <TheotyDetail
|
|
|
+ type="preview"
|
|
|
+ id={m.content}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ ref={(el: any) => (m.iframeRef = el)}
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <MusicScore
|
|
|
+ activeModel={activeData.model}
|
|
|
+ activeStatus={popupData.activeIndex === mIndex}
|
|
|
+ data-vid={m.id}
|
|
|
+ music={m}
|
|
|
+ imagePos={columnPos.value}
|
|
|
+ onSetIframe={(el: any) => {
|
|
|
+ m.iframeRef = el;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ ) : null;
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ ''
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 右边操作栏 */}
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.rightColumn,
|
|
|
+ columnShow.value && columnPos.value === 'right'
|
|
|
+ ? ''
|
|
|
+ : styles.rightColumnHide
|
|
|
+ ]}>
|
|
|
+ {rightList.map((item: any) => (
|
|
|
+ <div class={styles.columnItemBox}>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.columnItem,
|
|
|
+ (item.id === 2 && data.preStudentNum <= 0) ||
|
|
|
+ (item.id === 10 && studyData.callStudentList.length <= 0) ||
|
|
|
+ (item.id === 11 && !isUpArrow.value) ||
|
|
|
+ (item.id === 12 && !isDownArrow.value)
|
|
|
+ ? styles.itemDisabled
|
|
|
+ : ''
|
|
|
+ ]}
|
|
|
+ onClick={() => operateRightBtn(item.id)}>
|
|
|
+ <NTooltip
|
|
|
+ showArrow={false}
|
|
|
+ placement="left"
|
|
|
+ class={[
|
|
|
+ item.id === 15
|
|
|
+ ? 'columnItemTooltip rightColumnItemTooltip'
|
|
|
+ : ''
|
|
|
+ ]}>
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <img src={item.id === 8 ? rightIconPackUp : item.icon} />
|
|
|
+ ),
|
|
|
+ default: () =>
|
|
|
+ item.id === 15 ? (
|
|
|
+ <div class="tools">
|
|
|
+ {tooltipList.map(i => (
|
|
|
+ <div onClick={() => operateRightBtn(i.id)}>
|
|
|
+ <img src={i.icon} />
|
|
|
+ <div class="tit">{i.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ ) : item.id === 1 && data.type === 'preview' ? (
|
|
|
+ item.name2
|
|
|
+ ) : (
|
|
|
+ item.name
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </NTooltip>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ <NTooltip showArrow={false} placement="left">
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.rightHideIcon,
|
|
|
+ !(columnShow.value && columnPos.value === 'right')
|
|
|
+ ? styles.rightIconShow
|
|
|
+ : ''
|
|
|
+ ]}
|
|
|
+ onClick={() => {
|
|
|
+ columnPos.value = 'right';
|
|
|
+ columnShow.value = true;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ default: () => '按钮镜像'
|
|
|
+ }}
|
|
|
+ </NTooltip>
|
|
|
+ {/* 左边操作栏 */}
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.leftColumn,
|
|
|
+ columnShow.value && columnPos.value === 'left'
|
|
|
+ ? ''
|
|
|
+ : styles.leftColumnHide
|
|
|
+ ]}>
|
|
|
+ {rightList.map((item: any) => (
|
|
|
+ <div class={styles.columnItemBox}>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.columnItem,
|
|
|
+ (item.id === 2 && data.preStudentNum <= 0) ||
|
|
|
+ (item.id === 10 && studyData.callStudentList.length <= 0) ||
|
|
|
+ (item.id === 11 && !isUpArrow.value) ||
|
|
|
+ (item.id === 12 && !isDownArrow.value)
|
|
|
+ ? styles.itemDisabled
|
|
|
+ : ''
|
|
|
+ ]}
|
|
|
+ onClick={() => operateRightBtn(item.id)}>
|
|
|
+ <NTooltip
|
|
|
+ showArrow={false}
|
|
|
+ placement="right"
|
|
|
+ class={[item.id === 15 ? 'columnItemTooltip' : '']}>
|
|
|
+ {{
|
|
|
+ trigger: () => <img src={item.icon} />,
|
|
|
+ default: () =>
|
|
|
+ item.id === 15 ? (
|
|
|
+ <div class="tools">
|
|
|
+ {tooltipList.map(i => (
|
|
|
+ <div onClick={() => operateRightBtn(i.id)}>
|
|
|
+ <img src={i.icon} />
|
|
|
+ <div class="tit">{i.name}</div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ ) : item.id === 1 && data.type === 'preview' ? (
|
|
|
+ item.name2
|
|
|
+ ) : (
|
|
|
+ item.name
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </NTooltip>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ <NTooltip showArrow={false} placement="right">
|
|
|
+ {{
|
|
|
+ trigger: () => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.leftHideIcon,
|
|
|
+ !(columnShow.value && columnPos.value === 'left')
|
|
|
+ ? styles.leftIconShow
|
|
|
+ : ''
|
|
|
+ ]}
|
|
|
+ onClick={() => {
|
|
|
+ columnPos.value = 'left';
|
|
|
+ columnShow.value = true;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ default: () => '按钮镜像'
|
|
|
+ }}
|
|
|
+ </NTooltip>
|
|
|
+
|
|
|
+ {/* 显示列表 */}
|
|
|
+ {/* <NDrawer
|
|
|
+ v-model:show={popupData.open}
|
|
|
+ class={[styles.drawerContainer, styles.drawerContainerSource]}
|
|
|
+ onAfterLeave={handleClosePopup}
|
|
|
+ showMask={false}
|
|
|
+ blockScroll={false}
|
|
|
+ trapFocus={false}>
|
|
|
+ <NDrawerContent closable>
|
|
|
+ {{
|
|
|
+ header: () => (
|
|
|
+ <TheNoticeBar text={activeName.value || '资源列表'} />
|
|
|
+ ),
|
|
|
+ default: () => (
|
|
|
+ <SourceList
|
|
|
+ teacherChapterName={data.teacherChapterName}
|
|
|
+ knowledgePointList={data.knowledgePointList}
|
|
|
+ courseActiveIndex={popupData.courseActiveIndex}
|
|
|
+ activeItem={data.itemList[popupData.activeIndex]}
|
|
|
+ onConfirm={(item: any) => {
|
|
|
+ popupData.open = false;
|
|
|
+ toggleMaterial(item.id);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </NDrawerContent>
|
|
|
+ </NDrawer> */}
|
|
|
+ <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={popupData.open}
|
|
|
+ preset="card"
|
|
|
+ class={[
|
|
|
+ 'modalTitle background',
|
|
|
+ styles.drawerContainer,
|
|
|
+ resourcesConBoxClass
|
|
|
+ ]}
|
|
|
+ style={resourcesConDragData.styleDrag.value}
|
|
|
+ title={activeName.value || '资源列表'}>
|
|
|
+ <SourceList
|
|
|
+ teacherChapterName={data.teacherChapterName}
|
|
|
+ knowledgePointList={data.knowledgePointList}
|
|
|
+ courseActiveIndex={popupData.courseActiveIndex}
|
|
|
+ activeItem={data.itemList[popupData.activeIndex]}
|
|
|
+ onConfirm={(item: any) => {
|
|
|
+ popupData.open = false;
|
|
|
+ toggleMaterial(item.id);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </NModal>
|
|
|
+ {/* 章节切换 */}
|
|
|
+ {/* <NDrawer
|
|
|
+ v-model:show={popupData.chapterOpen}
|
|
|
+ class={styles.drawerContainer}
|
|
|
+ onAfterLeave={handleClosePopup}
|
|
|
+ showMask={false}
|
|
|
+ maskClosable={data.selectClassStatus ? false : true}
|
|
|
+ blockScroll={false}
|
|
|
+ trapFocus={false}>
|
|
|
+ <NDrawerContent title="切换章节" closable>
|
|
|
+ <Chapter
|
|
|
+ treeList={popupData.chapterDetails}
|
|
|
+ itemActive={data.detailId as any}
|
|
|
+ onHandleSelect={async (val: any) => {
|
|
|
+ // itemActive: child.id,
|
|
|
+ // itemName: child.name
|
|
|
+ popupData.courseId = val.itemActive;
|
|
|
+ data.selectClassStatus = true;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </NDrawerContent>
|
|
|
+ </NDrawer> */}
|
|
|
+ <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={popupData.chapterOpen}
|
|
|
+ preset="card"
|
|
|
+ class={[
|
|
|
+ 'modalTitle background',
|
|
|
+ styles.drawerContainer,
|
|
|
+ chapterConBoxClass
|
|
|
+ ]}
|
|
|
+ style={chapterConBoxDragData.styleDrag.value}
|
|
|
+ title={'切换章节'}>
|
|
|
+ <Chapter
|
|
|
+ treeList={popupData.chapterDetails}
|
|
|
+ itemActive={data.detailId as any}
|
|
|
+ onHandleSelect={async (val: any) => {
|
|
|
+ // itemActive: child.id,
|
|
|
+ // itemName: child.name
|
|
|
+ popupData.courseId = val.itemActive;
|
|
|
+ data.selectClassStatus = true;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </NModal>
|
|
|
+ {/* 批注 */}
|
|
|
+ {studyData.penShow && (
|
|
|
+ <Pen
|
|
|
+ isDrag={true}
|
|
|
+ show={studyData.type === 'pen'}
|
|
|
+ type={studyData.type}
|
|
|
+ close={() => closeStudyTool()}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {studyData.whiteboardShow && (
|
|
|
+ <Pen
|
|
|
+ isDrag={true}
|
|
|
+ show={studyData.type === 'whiteboard'}
|
|
|
+ type={studyData.type}
|
|
|
+ close={() => closeStudyTool()}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {studyData.callShow && (
|
|
|
+ <Pen
|
|
|
+ isDrag={true}
|
|
|
+ imagePos={columnPos.value}
|
|
|
+ callStudents={studyData.callStudentList}
|
|
|
+ show={studyData.type === 'call'}
|
|
|
+ type={studyData.type}
|
|
|
+ close={() => {
|
|
|
+ closeStudyTool();
|
|
|
+ studyData.callShow = false;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 选择课件 */}
|
|
|
+ <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={data.selectClassStatus}
|
|
|
+ preset="card"
|
|
|
+ class={[
|
|
|
+ 'modalTitle background',
|
|
|
+ // styles.attendClassModal,
|
|
|
+ styles.selectClassModal,
|
|
|
+ selCourBoxClass
|
|
|
+ ]}
|
|
|
+ style={selCourDragData.styleDrag.value}
|
|
|
+ title={'选择课件'}>
|
|
|
+ <SelectClass
|
|
|
+ classId={data.classId}
|
|
|
+ courseId={popupData.courseId}
|
|
|
+ instrumentId={data.instrumentId}
|
|
|
+ lessonCoursewareSubjectList={data.lessonCoursewareSubjectList}
|
|
|
+ onConfirm={async (val: any) => {
|
|
|
+ popupData.chapterLoading = true;
|
|
|
+ try {
|
|
|
+ data.selectClassStatus = false;
|
|
|
+ data.detailId = val.itemActive;
|
|
|
+ data.courseId = val.chapterId;
|
|
|
+ const ids = formatParentId(
|
|
|
+ val.itemActive,
|
|
|
+ popupData.chapterDetails
|
|
|
+ );
|
|
|
+ data.lessonCoursewareDetailId = ids[0];
|
|
|
+ // 更新上课记录 上课的时候才更新
|
|
|
+ if (data.type !== 'preview') {
|
|
|
+ await classCourseScheduleUpdate();
|
|
|
+ }
|
|
|
+ await getDetail();
|
|
|
+ popupData.activeIndex = 0;
|
|
|
+ popupData.chapterOpen = false;
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ popupData.chapterLoading = false;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </NModal>
|
|
|
+
|
|
|
+ {/* 布置作业 */}
|
|
|
+ <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={data.modelAttendStatus}
|
|
|
+ preset="card"
|
|
|
+ title={'课后作业'}
|
|
|
+ style={modelTrainHomeWordConBoxDragData.styleDrag.value}
|
|
|
+ class={[
|
|
|
+ 'modalTitle',
|
|
|
+ styles.removeVisiable,
|
|
|
+ modelTrainHomeWordConBoxClass
|
|
|
+ ]}>
|
|
|
+ <div class={styles.studentRemove}>
|
|
|
+ <p>{data.modalAttendMessage}</p>
|
|
|
+ <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
+ <NButton
|
|
|
+ type="default"
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ data.modelTrainStatus = true;
|
|
|
+ nextTick(() => {
|
|
|
+ getModalHeight();
|
|
|
+ });
|
|
|
+ data.modelAttendStatus = false;
|
|
|
+ }}>
|
|
|
+ 布置作业
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ type="primary"
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ handleStop();
|
|
|
+ data.modelAttendStatus = false;
|
|
|
+ }}>
|
|
|
+ 取消
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+ </div>
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </NModal>
|
|
|
+
|
|
|
+ {/* 训练设置 */}
|
|
|
+ {/* <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={data.modelTrainStatus}
|
|
|
+ preset="card"
|
|
|
+ class={[styles.attendClassModal, styles.trainClassModal]}
|
|
|
+ title={'作业设置'}>
|
|
|
+ <ClassWork
|
|
|
+ detailId={data.detailId}
|
|
|
+ instrumentId={data.instrumentId}
|
|
|
+ courseScheduleId={data.classId}
|
|
|
+ activeName={activeName.value}
|
|
|
+ classGroupId={data.classGroupId}
|
|
|
+ onClose={() => (data.modelTrainStatus = false)}
|
|
|
+ />
|
|
|
+ </NModal> */}
|
|
|
+ <NModal
|
|
|
+ v-model:show={data.modelTrainStatus}
|
|
|
+ preset="card"
|
|
|
+ class={[
|
|
|
+ 'modalTitle background',
|
|
|
+ styles.workVisiable,
|
|
|
+ modelTrainStatusConBoxClass
|
|
|
+ ]}
|
|
|
+ style={modelTrainStatusConBoxDragData.styleDrag.value}
|
|
|
+ title={'布置作业'}>
|
|
|
+ <div id="model-homework-height" class={styles.workContainer}>
|
|
|
+ <div class={styles.workTrain}>
|
|
|
+ <Train
|
|
|
+ from={'class'}
|
|
|
+ cardType="homeworkRecord"
|
|
|
+ lessonPreTraining={{
|
|
|
+ title: data.lessonPreTrainingId
|
|
|
+ ? ''
|
|
|
+ : data.teacherChapterName + '-课后作业',
|
|
|
+ chapterId: data.courseId, // 课件编号
|
|
|
+ id: data.lessonPreTrainingId // 作业编号
|
|
|
+ }}
|
|
|
+ coursewareKnowledgeDetailId={data.detailId}
|
|
|
+ classGroupId={data.classGroupId}
|
|
|
+ courseScheduleId={data.classId}
|
|
|
+ onChange={async (val: any) => {
|
|
|
+ data.modelTrainStatus = val.status;
|
|
|
+ // getCoursewareList();
|
|
|
+ if (val.saveWork && data.classId) {
|
|
|
+ data.lessonPreTrainingId = val.lessonPreTrainingId;
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class={styles.resourceMain}>
|
|
|
+ <ResourceMain from={'class'} cardType="homerowk-record" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </NModal>
|
|
|
+
|
|
|
+ {/* <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ class={['modalTitle background', metronomeConBoxClass]}
|
|
|
+ title={'节拍器'}
|
|
|
+ preset="card"
|
|
|
+ v-model:show={showModalBeat.value}
|
|
|
+ style={{
|
|
|
+ width: '687px',
|
|
|
+ ...metronomeConBoxDragData.styleDrag.value
|
|
|
+ }}>
|
|
|
+ <div class={styles.modeWrap}>
|
|
|
+ <iframe
|
|
|
+ src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
|
|
|
+ scrolling="no"
|
|
|
+ frameborder="0"
|
|
|
+ width="100%"
|
|
|
+ onLoad={(val: any) => {
|
|
|
+ iframeDislableKeyboard(val.target);
|
|
|
+ }}
|
|
|
+ height={'650px'}></iframe>
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </div>
|
|
|
+ </NModal> */}
|
|
|
+ <Metronome
|
|
|
+ v-model={showModalBeat.value}
|
|
|
+ dragClass={metronomeConBoxClass}
|
|
|
+ dragStyle={metronomeConBoxDragData.styleDrag.value}></Metronome>
|
|
|
+ <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ class={['background']}
|
|
|
+ v-model:show={showModalTone.value}>
|
|
|
+ <div>
|
|
|
+ <PlaceholderTone
|
|
|
+ onClose={() => {
|
|
|
+ showModalTone.value = false;
|
|
|
+ }}></PlaceholderTone>
|
|
|
+ </div>
|
|
|
+ </NModal>
|
|
|
+ <NModal
|
|
|
+ v-model:show={showModalTime.value}
|
|
|
+ class={timerMeterConBoxClass}
|
|
|
+ style={timerMeterConDragData.styleDrag.value}>
|
|
|
+ <div>
|
|
|
+ <img
|
|
|
+ class={styles.timerMeterClose}
|
|
|
+ src={timerMeterClose}
|
|
|
+ onClick={() => {
|
|
|
+ showModalTime.value = false;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <div class="topDragDom"></div>
|
|
|
+ <TimerMeter></TimerMeter>
|
|
|
+ </div>
|
|
|
+ </NModal>
|
|
|
+
|
|
|
+ <NModal
|
|
|
+ v-model:show={data.selectResourceStatus}
|
|
|
+ class={['modalTitle', styles.selectMusicModal, selResourBoxClass]}
|
|
|
+ style={selResourDragData.styleDrag.value}
|
|
|
+ preset="card"
|
|
|
+ title={'选择资源'}>
|
|
|
+ <SelectResources from="class" />
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </NModal>
|
|
|
+ <NModal
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={data.removeVisiable}
|
|
|
+ preset="card"
|
|
|
+ class={['modalTitle', styles.removeVisiable, removeResourBoxClass]}
|
|
|
+ style={removeResourDragData.styleDrag.value}
|
|
|
+ title={data.removeTitle}>
|
|
|
+ <div class={styles.studentRemove}>
|
|
|
+ <p>{data.removeContent}</p>
|
|
|
+
|
|
|
+ <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
+ <NButton
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ if (data.removeCourseStatus) {
|
|
|
+ if (globalState.application) {
|
|
|
+ document.exitFullscreen
|
|
|
+ ? document.exitFullscreen()
|
|
|
+ : document.mozCancelFullScreen
|
|
|
+ ? document.mozCancelFullScreen()
|
|
|
+ : document.webkitExitFullscreen
|
|
|
+ ? document.webkitExitFullscreen()
|
|
|
+ : '';
|
|
|
+ emit('close');
|
|
|
+ } else {
|
|
|
+ window.close();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ data.removeVisiable = false;
|
|
|
+ }
|
|
|
+ }}>
|
|
|
+ {data.removeCourseStatus ? '结束课程' : '取消'}
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ round
|
|
|
+ type="primary"
|
|
|
+ onClick={() => {
|
|
|
+ //
|
|
|
+ if (data.removeCourseStatus) {
|
|
|
+ data.modelTrainStatus = true;
|
|
|
+ data.removeVisiable = false;
|
|
|
+ nextTick(() => {
|
|
|
+ getModalHeight();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ if (globalState.application) {
|
|
|
+ document.exitFullscreen
|
|
|
+ ? document.exitFullscreen()
|
|
|
+ : document.mozCancelFullScreen
|
|
|
+ ? document.mozCancelFullScreen()
|
|
|
+ : document.webkitExitFullscreen
|
|
|
+ ? document.webkitExitFullscreen()
|
|
|
+ : '';
|
|
|
+ emit('close');
|
|
|
+ } else {
|
|
|
+ window.close();
|
|
|
+
|
|
|
+ if (route.query.source === 'admin') {
|
|
|
+ storage.remove(ACCESS_TOKEN_ADMIN);
|
|
|
+ window.parent.postMessage(
|
|
|
+ {
|
|
|
+ api: 'iframe_exit'
|
|
|
+ },
|
|
|
+ '*'
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }}>
|
|
|
+ {data.removeCourseStatus ? '布置作业' : '确定'}
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </div>
|
|
|
+ </NModal>
|
|
|
+ <NModal
|
|
|
+ style={nextEndBoxDragData.styleDrag.value}
|
|
|
+ z-index={3000}
|
|
|
+ transformOrigin="center"
|
|
|
+ v-model:show={data.nextEndShow}
|
|
|
+ preset="card"
|
|
|
+ title={'提示'}
|
|
|
+ class={['modalTitle', styles.removeVisiable, nextEndBoxClass]}>
|
|
|
+ <div class={styles.studentRemove}>
|
|
|
+ <p>当前课件已结束,是否进入下一章节</p>
|
|
|
+ <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
+ <NButton
|
|
|
+ type="default"
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ data.nextEndShow = false;
|
|
|
+ }}>
|
|
|
+ 取消
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ type="primary"
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ data.nextEndShow = false;
|
|
|
+ handleNextEnd();
|
|
|
+ }}>
|
|
|
+ 确认
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+ <Dragbom></Dragbom>
|
|
|
+ </div>
|
|
|
+ </NModal>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|