mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-09 02:46:44 +08:00
2473 lines
87 KiB
Vue
2473 lines
87 KiB
Vue
<template>
|
||
<div>
|
||
<div class="xpage-coures-banner">
|
||
<portal-header current="course" textColor="#fff" :goSearch="1"></portal-header>
|
||
<div style="margin: 0px 80px;">
|
||
<div class="banner-crumbs">
|
||
<router-link to="/course"><span class="crumbs-first">课程列表</span></router-link>
|
||
<span class="crumbs-line"> > </span>
|
||
<span class="crumbs-last">课程详情</span>
|
||
</div>
|
||
<div class="bcourse-title">
|
||
<span>{{courseInfo.name}}</span>
|
||
<!-- <span>{{courseInfo.summary}}</span> -->
|
||
<!--
|
||
<span class="bcourse-score" v-if="courseInfo.score>0">{{toScore(courseInfo.score)}} 分</span>
|
||
<span class="bcourse-score" v-else>无评分</span>
|
||
-->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="course-content xcontent">
|
||
<div class="course-playbox" ref="coursePlayerBox" id="id_course_player_box">
|
||
<div class="course-player" ref="coursePlayer" id="id_course_player">
|
||
<div>
|
||
<div v-if="resType == null || resType == 0">
|
||
<!--先显示视频图片-->
|
||
<course-image v-if="courseInfo.id != ''" :course="courseInfo"></course-image>
|
||
</div>
|
||
<div v-if="resType == 10" style="position: relative;">
|
||
<videoPlayer ref="myVideoPlayer" id="myVideoPlayer" @progress="progress" :src="blobUrl" :blobId="blobId" @onPlayerPlaying="onPlayerPlaying"
|
||
:initTime="contentData.lastStudyTime" :notePlay="notePlay" @onPlayerPlay="onPlayerPlay"
|
||
:isDrag="curriculumData.isDrag" @onFullscreen="onFullscreen" @onPlayerPause="onPlayerPause"
|
||
@onPlayerEnded="onPlayerEnded" :isCrowd="isCrowd" @onTimeUpdate="handleAudioTimeUpdate"></videoPlayer>
|
||
<div class="player-box" v-if="playerBoxShow">
|
||
<div class="player-praise" style="cursor: pointer;">
|
||
<div @click="praiseContent">
|
||
<img class="icon-small" v-if="isPraise" :src="require('@/assets/images/icon/praise-active.png')" />
|
||
<img class="icon-small" v-else :src="require('@/assets/images/icon/zhan.png')" />
|
||
<!-- {{ courseInfo.praises }} -->
|
||
<div style="color:#fff;cursor: pointer;">赞</div>
|
||
</div>
|
||
<div style="margin-left: 15px;cursor: pointer;" @click="treadContent">
|
||
<img class="icon-small" v-if="isTrample"
|
||
:src="require('@/assets/images/icon/trample-active.png')" />
|
||
<img class="icon-small" v-else :src="require('@/assets/images/icon/cai.png')" />
|
||
<!-- {{ courseInfo.trampleCount }} -->
|
||
<div style="color:#fff;cursor: pointer;">踩</div>
|
||
</div>
|
||
</div>
|
||
<div v-if="!scoreInfo.has" class="player-rate">
|
||
|
||
<el-rate v-model="scoreInfo.score" text-color="#ff9900" score-template="{value}" void-color="#fff" @change="addScore"></el-rate>
|
||
</div>
|
||
<div v-if="scoreInfo.has" style="padding-top: 5px;display: flex;">
|
||
<div class="player-rate" style="padding-left: 35px;">
|
||
<el-rate disabled v-model="courseInfo.score" :allow-half="true"></el-rate>
|
||
</div>
|
||
<span class="score-text" style="margin-top:35px">
|
||
<span style="color:#ffb30f;">{{ toScore(courseInfo.score) }}</span>
|
||
<span style="font-size: 12px;color: #fff">分</span>
|
||
</span>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div v-if="resType == 20">
|
||
<div class="con-audio">
|
||
<div class="con-audio-title">{{ contentData.contentName }}</div>
|
||
<div class="con-audio-player">
|
||
<audioPlayer v-if="resType == 20" :url="blobUrl" :name="contentData.contentName" @onPlaying="audioPlaying" :isDrag="curriculumData.isDrag"
|
||
@onPlay="audioPlay" @onPause="audioPause" @onPlayEnd="audioEnd"></audioPlayer>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div v-if="resType == 40">
|
||
<div style="padding: 10px;color: #ed0000; " v-if="curCFile.converStatus < 2 && !contentData.content">
|
||
<div>此课程内容无法预览,请联系管理员</div>
|
||
</div>
|
||
<div style="padding: 10px;color: #ed0000;" v-if="curCFile.converStatus == 3 && !contentData.content">
|
||
此课程内容无法预览,请联系管理员
|
||
</div>
|
||
<pdfPreview :autoScroll="true" v-if="resType == 40" :filePath="fileBaseUrl + contentData.content">
|
||
</pdfPreview>
|
||
</div>
|
||
<div v-if="resType == 41">
|
||
<div style="padding: 20px;" v-html="contentData.content"></div>
|
||
</div>
|
||
<div v-if="resType == 50" style="min-height: 500px;">
|
||
<iframe v-if="scormUrl" :src="scormUrl" frameborder="0" border="0px" style="width:100%;height:500px;border:0px;"></iframe>
|
||
</div>
|
||
<div v-if="resType == 52">
|
||
<div v-if="contentData.content != ''">
|
||
<div class="hyper-link" v-if="conLink.openType == 2">
|
||
<div class="hyper-link-row">{{ contentData.contentName }}</div>
|
||
<div class="hyper-link-row">{{ conLink.url }}</div>
|
||
</div>
|
||
<div v-if="conLink.openType == 1"><iframe :src="conLink.url"
|
||
style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe></div>
|
||
</div>
|
||
</div>
|
||
<div v-if="resType == 60">
|
||
<homework @submit="homeWorkSubmit" v-if="resType == 60 && studyId != ''" :studyId="studyId" :content="contentData"></homework>
|
||
</div>
|
||
<div v-if="resType == 61">
|
||
<exam @startTest="startTest" v-if="resType == 61 && studyId != '' " :studyId="studyId" :content="contentData"></exam>
|
||
</div>
|
||
<div v-if="resType == 62" style="padding:5px">
|
||
<assess v-if="resType == 62 && studyId != '' && contentData.id" :studyId="studyId" :content="contentData">
|
||
</assess>
|
||
</div>
|
||
</div>
|
||
<!--交互部分-->
|
||
<div>
|
||
<div class="course-interact">
|
||
<div class="score" style="display: flex;">
|
||
<div v-if="!scoreInfo.has" style="margin-left:10px;cursor: pointer;padding-top:18px">
|
||
<!-- <el-popover placement="top" width="300" trigger="hover"> -->
|
||
<!-- <div style="text-align:center;line-height:50px;padding:20px 0px">
|
||
|
||
<div style="padding-top:30px"><el-button @click="addScore">提交评分</el-button></div>
|
||
</div> -->
|
||
<el-rate v-model="scoreInfo.score" @change="addScore"></el-rate>
|
||
<!-- <el-tag class="ref-score" slot="reference">去评分</el-tag> -->
|
||
<!-- </el-popover> -->
|
||
</div>
|
||
<div v-if="scoreInfo.has" style="padding-top: 5px;display: flex;">
|
||
<div style="padding-top: 16px;">
|
||
<el-rate disabled v-model="courseInfo.score" :allow-half="true" ></el-rate>
|
||
</div>
|
||
<div>
|
||
<span class="score-text">{{ toScore(courseInfo.score) }}</span>
|
||
<span style="font-size: 18px;">分</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="display: flex;justify-content: flex-end;cursor: pointer;padding-top: 5px;">
|
||
<div @click="praiseContent">
|
||
<el-tooltip class="item" effect="light" :content="isPraise?'取消点赞':'点赞'" placement="top-start" :visible-arrow="false" popper-class="text-tooltip">
|
||
<img class="icon-small" v-if="isPraise" :src="require('@/assets/images/icon/praise-active.png')" />
|
||
<img class="icon-small" v-else :src="require('@/assets/images/icon/praise.png')" />
|
||
</el-tooltip>
|
||
{{ courseInfo.praises }}
|
||
</div>
|
||
<div style="margin-left: 20px;" @click="treadContent">
|
||
<el-tooltip class="item" effect="light" :content="isTrample?'取消踩':'踩'" placement="top-start" :visible-arrow="false" popper-class="text-tooltip">
|
||
<img class="icon-small" v-if="isTrample" :src="require('@/assets/images/icon/trample-active.png')" />
|
||
<img class="icon-small" v-else :src="require('@/assets/images/icon/trample.png')" />
|
||
</el-tooltip>
|
||
{{ courseInfo.trampleCount }}
|
||
</div>
|
||
<div style="margin-left: 6px;">
|
||
<interactBar :size="16" :type="1" :aid="courseInfo.sysCreateAid" :data="courseInfo" :praises="false" :favorites="true" :shares="true" :comments="false" :views="false"></interactBar>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="course-control">
|
||
<div class="control-tab" v-if="contentList.length>0" >
|
||
<div v-if="contentList.length>1" @click="heartabone" :class="tab == 1 ? 'control-tab-active' : ' '">
|
||
<i class="el-icon-reading" style="margin-right:9px;margin-left:9px"></i>课程单元
|
||
</div>
|
||
<div @click="heartabtwo" :class="tab == 2 ? 'control-tab-active' : ' '">
|
||
<i class="el-icon-edit" style="margin-right:9px;margin-left:9px"></i>我的笔记
|
||
</div>
|
||
</div>
|
||
<!-- 课程单元 -->
|
||
<div class="course-units" v-if="tab == 1">
|
||
<div :style="`height: ${controlHeight}px;overflow-y: auto;`">
|
||
<div class="catalog" v-if="courseInfo.type == 20">
|
||
<div v-for="(item, index) in catalogTree" :key="index" :name="index">
|
||
<el-menu
|
||
ref="menu"
|
||
:default-openeds="defaultOpeneds"
|
||
:default-active="activeId"
|
||
:unique-opened="true"
|
||
class="el-menu-vertical-demo"
|
||
@open="handleOpen"
|
||
@close="handleClose">
|
||
<el-submenu :index="item.section.id">
|
||
<template slot="title">
|
||
<div style="display: flex;justify-content: space-between;">
|
||
<div style="width: 240px;font-weight: 700;font-size: 16px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;" :title="item.section.name">{{item.section.name}}</div>
|
||
<div style="margin-right: 23px;font-weight: 700;font-size: 16px;">({{ item.children.filter(item=>item.status == 9).length }}/{{ item.children.length }})</div>
|
||
</div>
|
||
</template>
|
||
<el-menu-item-group v-for="(ele, i) in item.children" :key="i">
|
||
<div class="units-info" :class="{'units-active':contentData.id == ele.id}" @click="showRes(ele,i,index,item)">
|
||
<el-menu-item :index="ele.id" style="padding: 0;padding-left: 10px;">
|
||
<div style="display: flex;justify-content: space-between;">
|
||
<div style="width: 200px;font-size: 16px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;" :title="ele.contentName">{{i+1}}. {{ ele.contentName }}</div>
|
||
<div>
|
||
<span v-if="contentData.id == ele.id" style="color: #387DF7;font-size: 14px;margin-right: 4px;">学习中</span>
|
||
<!-- <img v-if="contentData.id == ele.id" :src="`${webBaseUrl}/images/playicon.png`" alt=""> -->
|
||
<img v-if="contentData.id == ele.id && ele.status == 9" style="width: 16px;height: 16px;" src="@/assets/images/over.png" alt="">
|
||
<img v-if="contentData.id == ele.id && ele.status == 0" style="width: 16px;height: 16px;" src="@/assets/images/nowNot.png" alt="">
|
||
<img v-if="contentData.id == ele.id && (ele.status != 9&&ele.status != 0)" style="width: 16px;height: 16px;" src="@/assets/images/ban1.png" alt="">
|
||
<img v-if="contentData.id != ele.id && ele.status == 9" style="width: 16px;height: 16px;" src="@/assets/images/notNew.png" alt="">
|
||
<img v-if="contentData.id != ele.id && ele.status == 0" style="width: 16px;height: 16px;" src="@/assets/images/not.png" alt="">
|
||
<img v-if="contentData.id != ele.id && (ele.status != 9&&ele.status != 0)" style="width: 16px;height: 16px;" src="@/assets/images/newBan.png" alt="">
|
||
</div>
|
||
</div>
|
||
</el-menu-item>
|
||
</div>
|
||
</el-menu-item-group>
|
||
</el-submenu>
|
||
</el-menu>
|
||
</div>
|
||
<!-- <div v-for="(item, index) in catalogTree" :key="index" :name="index">
|
||
<div style="margin: 10px 0px;font-weight: 700;">{{item.section.name}}</div>
|
||
<div class="units-info" :class="{'units-active':contentData.id == ele.id}" v-for="(ele, i) in item.children" :key="i" @click="showRes(ele,i,index)">
|
||
<img v-if="contentData.id == ele.id" :src="`${webBaseUrl}/images/playicon.png`" alt=""> {{i+1}}.
|
||
<span>{{ ele.contentName }}</span>
|
||
</div>
|
||
</div> -->
|
||
</div>
|
||
<div v-else class="catalog">
|
||
<!-- contentList -->
|
||
<div class="units-info" style="display: flex;justify-content: space-between" v-for="(list, index) in contentList" :key="index" :name="index" @click="showRes(list,-1,index)" :class="{'units-active':contentData.id == list.id}">
|
||
<!-- <div class="units-info" :class="{'units-active':contentData.id == ele.id}" @click="showRes(ele,i,index)" v-for="(ele, i) in item.children" :key="i"> -->
|
||
<!-- <img v-if="contentData.id == list.id" :src="`${webBaseUrl}/images/playicon.png`" alt=""> -->
|
||
<div style="max-width: 193px;;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
|
||
{{index+1}}.{{ list.contentName }}
|
||
</div>
|
||
<div style="margin-left: 5px">
|
||
<span v-if="contentData.id == list.id" style="color: #387DF7;font-size: 14px;margin-right: 4px;">学习中</span>
|
||
<img v-if="contentData.id == list.id && list.status == 9" style="width: 16px;height: 16px;" src="@/assets/images/over.png" alt="">
|
||
<img v-if="contentData.id == list.id && list.status == 0" style="width: 16px;height: 16px;" src="@/assets/images/nowNot.png" alt="">
|
||
<img v-if="contentData.id == list.id && (list.status != 9&&list.status != 0)" style="width: 16px;height: 16px;" src="@/assets/images/ban1.png" alt="">
|
||
<img v-if="contentData.id != list.id && list.status == 9" style="width: 16px;height: 16px;" src="@/assets/images/notNew.png" alt="">
|
||
<img v-if="contentData.id != list.id && list.status == 0" style="width: 16px;height: 16px;" src="@/assets/images/not.png" alt="">
|
||
<img v-if="contentData.id != list.id && (list.status != 9&&list.status != 0)" style="width: 16px;height: 16px;" src="@/assets/images/newBan.png" alt="">
|
||
</div>
|
||
<!-- </div> -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 我的笔记 -->
|
||
<div class="mynote" v-show="tab == 2">
|
||
<my-note ref="mynote" :height="controlHeight" @change="noteChange" :data="courseInfo" @videoLocation="videoLocation" @onPlayVideo="onPlayVideo"
|
||
:score="courseInfo.score"></my-note>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="course-infobox">
|
||
<div class="course-info">
|
||
<div style="background-color: #fff;">
|
||
<div class="course-info-tab">
|
||
<div @click="coutab(1)" :class="courestab == 1? 'course-info-tab-active' : ''">内容简介<span class=""></span> </div>
|
||
<div @click="coutab(2)" :class="courestab == 2? 'course-info-tab-active' : ''">课程评论<span class=""></span> </div>
|
||
<div @click="coutab(3)" :class="courestab == 3? 'course-info-tab-active' : ''">课程笔记<span class=""></span> </div>
|
||
</div>
|
||
<div v-show="courestab==1" style="margin-left:17px;padding-top: 20px;">
|
||
<div style="padding: 30px;">
|
||
<div class="course-info-row"><img src="@/assets/images/icon/remark-iocn.png" alt="" srcset=""> 目标人群:<div class="course-info-text">{{courseInfo.forUsers}}</div></div>
|
||
<div class="course-info-row"><img src="@/assets/images/icon/remark-iocn.png" alt="" srcset=""> 课程价值:<div class="course-info-text">{{courseInfo.value}}</div></div>
|
||
<div class="course-info-row"><img src="@/assets/images/icon/remark-iocn.png" alt="" srcset=""> 详细介绍:<div class="course-info-text" v-html="courseInfo.summary"></div></div>
|
||
</div>
|
||
</div>
|
||
<div v-show="courestab==2" class="coures-comments" style="margin-left:17px">
|
||
<comments v-if="courseInfo.id && courseInfo.id != ''" :obj-type="1" :obj-id="courseInfo.id" :toUsers="toUsers"></comments>
|
||
</div>
|
||
<div v-show="courestab==3" class="coures-note">
|
||
<note-comments :key="timer" v-if="courseInfo.id && courseInfo.id != ''" :obj-type="6" :obj-id="courseInfo.id" :name="courseInfo.name"></note-comments>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="course-teacher">
|
||
<div class="cteacher-top">
|
||
<div class="cteacher-top"><img width="100%" style="vertical-align: top;" height="10px" src="../../../public/images/tearch-top.png" alt=""></div>
|
||
<div class="cteacher-top-title">课程讲师</div>
|
||
</div>
|
||
|
||
<div class="cteacher-list">
|
||
<div class="teacher" v-for="(item, idx) in teachers" :key="idx">
|
||
<div class="teacher-avator" @click="toUserHome(item)" title="点击进入他的主页">
|
||
<!-- <div class="teacher-text" v-if="item.authorInfo.avatar == ''">{{userAvatarText(item.teacherName)}}</div> -->
|
||
<div v-if="item.authorInfo.avatar !== ''">
|
||
<el-avatar :src="fileBaseUrl + item.authorInfo.avatar" shape="circle" :size="50"></el-avatar>
|
||
</div>
|
||
<div v-else class="teacher-text">
|
||
<div v-if="item.authorInfo.sex === 1 "><img src="../../../public/images/Avatarman.png" alt=""></div>
|
||
<div v-else><img src="../../../public/images/Avatarwoman.png" alt=""></div>
|
||
</div>
|
||
</div>
|
||
<div class="teacher-info">
|
||
<div class="teacher-name">
|
||
<span> {{ item.teacherName }}</span>
|
||
<!-- <span style="font-size: 12px; color:#666666 ;">( {{cutOrgNamePath(item.authorInfo.orgInfo)}} )</span> -->
|
||
</div>
|
||
<!-- <div class="teacher-remark" v-html="item.authorInfo.sign"></div> -->
|
||
<div v-if="item.teacherType === 1 " class="teacher-remark">{{cutOrgNamePath(item.authorInfo.orgInfo)}}</div>
|
||
<div v-else>{{item.supplier}}</div>
|
||
</div>
|
||
<div style="padding-top:15px;width:70px;">
|
||
<followButton v-if="item.teacherName!=='BOE教师'" :auto="true" size="small" :aid="item.teacherId"></followButton>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- <div><portal-footer></portal-footer></div> -->
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import { mapGetters } from 'vuex';
|
||
import followButton from "@/components/Follow/button.vue";
|
||
import portalHeader from "@/components/PortalHeader.vue";
|
||
import portalFooter from "@/components/PortalFooter.vue";
|
||
import comments from "@/components/Portal/comments.vue";
|
||
import noteComments from "@/components/Portal/noteComment.vue";
|
||
import interactBar from "@/components/Portal/interactBar.vue";
|
||
import audioPlayer from '@/components/AudioPlayer/index.vue';
|
||
import videoPlayer from '@/components/VideoPlayer/index.vue';
|
||
import hyperLink from '@/components/Course/hyperLink.vue';
|
||
import studyUtil from '@/utils/study.js';
|
||
import { encrypt } from '@/utils/jsencrypt.js';
|
||
import cookies from 'vue-cookies';
|
||
import apiStat from '@/api/phase2/stat.js';
|
||
import apiStudy from '@/api/modules/courseStudy.js';
|
||
import apiVideoStudy from "@/api/modules/videoStudy.js";
|
||
import apiCourseGrade from '@/api/modules/courseGrade.js';
|
||
import apiPraises from '@/api/modules/praises.js';
|
||
import apiTrample from '@/api/modules/trample.js';
|
||
import apiCoursePortal from '@/api/modules/coursePortal.js';
|
||
import apiUser from '@/api/system/user.js';
|
||
import apiCourseFile from '@/api/modules/courseFile.js';
|
||
import {
|
||
resListMap,
|
||
resOwnerListMap,
|
||
courseType,
|
||
getType,
|
||
toScore,
|
||
cutOrgNamePath,
|
||
userAvatarText
|
||
} from '@/utils/tools.js';
|
||
import pdfPreview from '@/components/PdfPreview/index.vue';
|
||
import courseImage from '@/components/Course/courseImage.vue';
|
||
import exam from '@/components/Course/exam';
|
||
import homework from '@/components/Course/homework';
|
||
import assess from '@/components/Course/assess';
|
||
import myNote from '../../components/Course/myNote.vue';
|
||
import apiFollow from "@/api/phase2/userfollow.js";
|
||
import apiMessage from '@/api/system/message.js'
|
||
// import Vue from 'vue';
|
||
// Vue.forceUpdate();
|
||
export default {
|
||
name: "atticle",
|
||
components: {
|
||
courseImage,
|
||
portalHeader,
|
||
hyperLink,
|
||
comments,
|
||
homework,
|
||
exam,
|
||
interactBar,
|
||
assess,
|
||
pdfPreview,
|
||
audioPlayer,
|
||
videoPlayer,
|
||
myNote,
|
||
noteComments,
|
||
portalFooter,
|
||
followButton
|
||
},
|
||
data() {
|
||
return {
|
||
tentative: false,
|
||
isContentTypeTwo: null,
|
||
isContentType: null,
|
||
activeId: '',
|
||
isFalse: false,
|
||
defaultOpeneds: [],
|
||
sendEventProgress: 0,
|
||
trueFalse: true,
|
||
audiences:'',
|
||
isCrowd:false,
|
||
cutOrgNamePath,
|
||
scormUrl:'',//当前播放的scormUrl
|
||
loading:false,
|
||
controlHeight:400,//左边控制区域的内容高度
|
||
timer: '',
|
||
notePlay: null,
|
||
intTimeNote: '',
|
||
courestab: 2,//默认是课程评论
|
||
curCFile: {
|
||
converStatus: 4,
|
||
},
|
||
radio: '',
|
||
interactRuning: false,
|
||
playerBoxShow: false,
|
||
userAvatarText,
|
||
publicPath: process.env.VUE_APP_PUBLIC_PATH,
|
||
showiframe: false,
|
||
toScore,
|
||
courseId: '', //当前课程的id
|
||
studyId: '', //当前学习的id
|
||
initContentId: '', //初始化当前学习的内容节
|
||
blobUrl: '', //播放的文件地址,新添加,采用blob方式
|
||
contentData: {
|
||
studyItemId: '',
|
||
status: 1
|
||
}, //当前的显示的内容
|
||
conLink: {
|
||
openType: 1,
|
||
url: ''
|
||
}, //对于超连接的内容
|
||
curriculumData: {
|
||
url: '',
|
||
isDrag: true,
|
||
completeSetup: 0,
|
||
setupTage: 0,
|
||
second: 0
|
||
}, // 课件内容
|
||
courseInfo: {
|
||
id: '',
|
||
name: ''
|
||
}, //课程信息
|
||
totalContent: 0, //课程内容数量
|
||
pageCount: 0,
|
||
currentPage: 0,
|
||
fileBaseUrl: this.$xpage.constants.fileBaseUrl,//使用动态的路径 ,不使用配置的路径了process.env.VUE_APP_FILE_BASE_URL,
|
||
contentList: [],
|
||
sectionList: [],
|
||
teachers: [],
|
||
toUsers: [], //对于@教师的处理
|
||
getType: getType,
|
||
ctabName: 'catalog',
|
||
resType: null,
|
||
activeNames: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||
scoreInfo: {
|
||
dlgShow: false,
|
||
score: 5,
|
||
has: false
|
||
},
|
||
isPraise: false,
|
||
isTrample: false,
|
||
appendStartTime: null, //记录追加的开始时间
|
||
appendHandle: null, //追加学习时长的timeout句柄
|
||
isAppendTime: false, //是否追加学习时长
|
||
appentId: '', //当前追加的学习时长的id,此字段已经不再使用
|
||
appentInterval: 15, //追加学习时间的间隔 5秒加一次
|
||
handleTimeout: null,
|
||
completed: [],
|
||
tab: 1,
|
||
notetab: 1,
|
||
localTimeKey:'boeu-study-time' ,//本地存储的学习时长的key json格式
|
||
localTimeValue:0,//计算的时间
|
||
appendStudyOtherHandle:null,
|
||
cumulativeDuration:0, //非音频累计时长
|
||
maxDuration:0, //非音频最大时长
|
||
defaultMaxTime:1800, //非音频默认最大时间
|
||
}
|
||
},
|
||
mounted() {
|
||
// 增加的用户受众id
|
||
let localKey = "user_" + this.userInfo.sysId + "_gids";
|
||
let hasIds = sessionStorage.getItem(localKey);
|
||
this.audiences = hasIds ?? ''
|
||
this.$watermark.set(this.userInfo.name + this.userInfo.loginName);
|
||
this.courseId = this.$route.query.id;
|
||
this.initContentId = this.$route.query.contentId;
|
||
this.stopStudyTime();//先关闭
|
||
this.cleanAppendTime();//
|
||
this.loadData();
|
||
//console.log(this.$xpage.constants.fileBaseUrl,'this.$xpage.constants.fileBaseUrl');
|
||
},
|
||
computed: {
|
||
...mapGetters(['userInfo']),
|
||
catalogTree(){
|
||
let treeList = [];
|
||
this.completed = [];
|
||
let $this = this;
|
||
$this.sectionList.forEach(sec => {
|
||
let treeNode = {
|
||
section: sec,
|
||
children: []
|
||
};
|
||
sec.status = 1;
|
||
let finishCount = 0;
|
||
$this.contentList.forEach(c => {
|
||
if (c.csectionId == sec.id) {
|
||
if (c.status > 1) {
|
||
sec.status = 2;
|
||
if (c.status == 9) {
|
||
finishCount++;
|
||
}
|
||
}
|
||
if (c.status == 9) {
|
||
$this.completed.push(c.id);
|
||
}
|
||
treeNode.children.push(c);
|
||
}
|
||
});
|
||
if (finishCount == treeNode.children.length) {
|
||
sec.status = 9;
|
||
}
|
||
treeList.push(treeNode);
|
||
});
|
||
// console.log(treeList,'treeList')
|
||
return treeList;
|
||
}
|
||
},
|
||
destroyed(){
|
||
this.cleanAppendTime();
|
||
this.stopStudyTime();
|
||
},
|
||
methods: {
|
||
handleOpen(key,path){
|
||
// console.log(key,path,'handleOpen')
|
||
if(this.isFalse){
|
||
this.defaultOpeneds = [key]
|
||
}
|
||
this.isFalse = false
|
||
},
|
||
handleClose(key,path){
|
||
// console.log(key,path,'handleClose')
|
||
},
|
||
toUserHome(tea){
|
||
this.$router.push({path:this.$xpage.getHomePath(tea.teacherId)})
|
||
},
|
||
noteChange(){
|
||
//视频点定位,直接到播放的视频位置
|
||
this.timer = new Date().getTime()
|
||
},
|
||
//清空追加学习时长事件
|
||
cleanAppendTime(){
|
||
if(this.appendStudyOtherHandle){
|
||
window.clearTimeout(this.appendStudyOtherHandle);
|
||
}
|
||
},
|
||
//非音视频课学习时长的增加,每一分钟保存一次
|
||
appendStudyOtherTime() {
|
||
//console.log('开始追加学习时长',this.isAppendTime);
|
||
if (this.studyId == '') {
|
||
return;
|
||
}
|
||
if (!this.contentData.id) {
|
||
return;
|
||
}
|
||
//每一分钟保存一次
|
||
// 取消阅读的每分钟六十秒的计时,最多是设置的时间或默认时间
|
||
let $this=this;
|
||
let startTime = new Date().getTime();
|
||
this.appendStudyOtherHandle = setTimeout(function() {
|
||
let endTime = new Date().getTime();
|
||
let totalTime = Math.round((endTime - startTime) / 1000);
|
||
$this.cumulativeDuration += totalTime;
|
||
if($this.cumulativeDuration <= $this.maxDuration){
|
||
//发送时长
|
||
$this.sendStudyOtherTime(totalTime);
|
||
//递归调用
|
||
$this.appendStudyOtherTime();
|
||
}else{
|
||
clearTimeout(this.appendStudyOtherHandle);
|
||
$this.cumulativeDuration = 0;
|
||
$this.maxDuration = 0;
|
||
}
|
||
}, 1000*60);
|
||
|
||
},
|
||
sendStudyOtherTime(totalTime){
|
||
//静默处理
|
||
apiStat.sendEvent({
|
||
"key": "StudyCourseOther",//课程学习的key
|
||
"title": "非音视频课内容",//事件的标题
|
||
"parameters":"second:" + totalTime,//second:value 本次的学习时长
|
||
"content": "学习课程",//事件的内容
|
||
"objId": this.courseInfo.id,//课程的id
|
||
"objType": "1",//类型
|
||
"source":"page",
|
||
"objInfo": ""+this.courseInfo.name,
|
||
"aid":this.userInfo.aid, //当前登录人的id
|
||
"aname":this.userInfo.name,//当前人的姓名
|
||
"status": 1 //状态
|
||
}).then(rs=>{
|
||
if(rs.status != 200) {
|
||
console.log(rs.message);
|
||
}
|
||
});
|
||
},
|
||
//笔记组件触发,播放指定时间
|
||
onPlayVideo(contentId,time){
|
||
//这里需要根据contentId,是否切换到对应的内容的视频的时间
|
||
//如果 contentId已经不存在,需要提示
|
||
console.log(contentId,this.contentData.id,'两个内容id');
|
||
let $this=this;
|
||
if(this.contentData.id==contentId){
|
||
this.onPlayerPause()
|
||
//this.audioPause();
|
||
this.contentData.lastStudyTime=time;
|
||
//this.onPlayerPlay();
|
||
setTimeout(() => {
|
||
$this.$refs.myVideoPlayer.startPlay(time);
|
||
}, 10)
|
||
console.log('开始播放1');
|
||
}else{
|
||
//通过contentId
|
||
let toResContent=null;
|
||
this.contentList.forEach(c => {
|
||
if(c.id==contentId){
|
||
c.lastStudyTime=time;
|
||
toResContent=c;
|
||
}
|
||
});
|
||
if(toResContent){
|
||
|
||
this.changePlayRes(toResContent);
|
||
//this.onPlayerPlay();
|
||
setTimeout(() => {
|
||
$this.$refs.myVideoPlayer.startPlay(time);
|
||
}, 10)
|
||
|
||
console.log('开始播放2');
|
||
}else{
|
||
this.$message.error('资源已不存在或更换过,已无法定位');
|
||
}
|
||
}
|
||
this.playerBoxShow = false;
|
||
//this.changePlayRes(r);
|
||
// this.playerBoxShow = false;
|
||
// this.notePlay = null;
|
||
// let $this=this;
|
||
// setTimeout(() => {
|
||
// $this.notePlay = time;
|
||
// }, 500)
|
||
},
|
||
//笔记组件触发,记录当前播放时间
|
||
videoLocation() {
|
||
//this.$store.dispatch("SetIntTimeNote", this.intTimeNote);
|
||
//console.log(this.contentData.id+'='+this.intTimeNote,'设置视频播放时间')
|
||
this.$refs.mynote.setVideoTime(this.contentData.id,this.intTimeNote);
|
||
},
|
||
coutab(n) {
|
||
this.courestab =n;
|
||
},
|
||
createPlayUrl(fid, u) {
|
||
let nowDate = new Date();
|
||
let ctime = parseInt(nowDate.getTime() / 1000);
|
||
let beforeUrl = parseInt(nowDate.getTime() / 1000) + '/' + fid;
|
||
//console.log(beforeUrl,'beforeUrl');
|
||
let urlSign = encodeURIComponent(encrypt(beforeUrl));
|
||
//console.log(urlSign,'urlSign');
|
||
cookies.set('PLAYSIGN_TIME', ctime); //写客户端的cookie保存
|
||
//以下判断是为了区分本地环境和服务器环境
|
||
if (process.env.NODE_ENV == 'development') {
|
||
this.blobUrl = process.env.VUE_APP_FILE_BASE_URL + u;
|
||
} else {
|
||
this.blobUrl = process.env.VUE_APP_BASE_API + '/xboe/m/course/cware/resource?sign=' + urlSign;
|
||
}
|
||
// console.log('this.contentData.id:',this.contentData.id)
|
||
this.blobId = this.contentData.id
|
||
//console.log(this.blobUrl,'this.blobUrl');
|
||
},
|
||
widthOpen(url) {
|
||
window.open(url, '_blank');
|
||
},
|
||
//替换播放区域
|
||
changePlayRes(r,item){
|
||
this.tentative = false;
|
||
if(this.appendStudyOtherHandle!=null){
|
||
window.clearTimeout(this.appendStudyOtherHandle);
|
||
}
|
||
this.playerBoxShow = false;
|
||
//显示内容部分
|
||
this.$refs.mynote.showVideoTimeBtn(false);
|
||
let $this = this;
|
||
this.resType = r.contentType;
|
||
this.contentData = r;
|
||
this.activeId = this.contentData.id
|
||
if(item){
|
||
this.isFalse = true
|
||
this.handleOpen(item.section.id,[item.section.id])
|
||
}
|
||
this.contentData.name = this.courseInfo.name;
|
||
this.saveStudyDuration();
|
||
|
||
if (r.contentType == 10 || r.contentType == 20) {
|
||
this.trueFalse = true
|
||
if (r.content.startsWith('\{')) {
|
||
this.curriculumData = JSON.parse(r.content);
|
||
} else {
|
||
this.curriculumData.url = r.content;
|
||
}
|
||
this.$refs.mynote.showVideoTimeBtn(true);
|
||
//let url=process.env.VUE_APP_BASE_API+'/xboe/m/course/file/show?cf='+this.curriculumData.url;
|
||
//let url=this.fileBaseUrl+this.curriculumData.url;
|
||
this.createPlayUrl(r.contentRefId, this.curriculumData.url);
|
||
} else if (r.contentType == 40) {
|
||
// if (r.content != '' && r.content.indexOf('.pdf') == -1) {
|
||
apiCourseFile.detail(r.contentRefId).then(cfrs => {
|
||
if (cfrs.status == 200) {
|
||
r.content = cfrs.result.previewFilePath;
|
||
this.curCFile = cfrs.result;
|
||
if (cfrs.result.previewFilePath == '' && cfrs.result.filePath.indexOf('pdf') > -1) {
|
||
r.content = cfrs.result.filePath;
|
||
this.curCFile.converStatus = 2;
|
||
}
|
||
if (r.content && r.content.indexOf('.pdf') > -1) {
|
||
this.curCFile.converStatus = 2;
|
||
}
|
||
} else {
|
||
$this.$message.error('加载pdf课件文件失败');
|
||
}
|
||
});
|
||
// }
|
||
}else if(r.contentType==50){ //scorm
|
||
this.scormUrl='';
|
||
apiCourseFile.detail(r.contentRefId).then(cfrs => {
|
||
if(cfrs.status==200){
|
||
this.curCFile = cfrs.result;
|
||
//this.scormUrl=cfrs
|
||
let pars='?mode=normal&r='+Math.random();
|
||
pars+='&scormId='+this.curCFile.id;
|
||
pars+='&courseId='+this.courseId;
|
||
pars+='&contentId='+r.id;
|
||
pars+='&studentId='+this.userInfo.aid;
|
||
pars+='&studentName='+encodeURIComponent(this.userInfo.name);
|
||
pars+='&lmsId='+this.studyId;
|
||
pars+='&scoId=';//不指定,scorm模块自动根据学习记录定位
|
||
let urlPre=window.location.protocol;
|
||
let configUrl=process.env.VUE_APP_SCORM_URL;
|
||
configUrl=urlPre+configUrl.substring(configUrl.indexOf(':')+1);
|
||
|
||
this.scormUrl=configUrl+pars;//播放的首页
|
||
}
|
||
});
|
||
|
||
}else if (r.contentType == 52) {
|
||
this.isAppendTime = false;
|
||
if (r.content.startsWith('\{')) {
|
||
this.conLink = JSON.parse(r.content);
|
||
} else {
|
||
this.conLink.url = r.content;
|
||
this.conLink.openType = 1;
|
||
}
|
||
if (this.conLink.openType == 2) {
|
||
//直接设置完成状态
|
||
this.widthOpen(this.conLink.url);
|
||
}
|
||
//this.conLink=
|
||
} else if (r.contentType == 61) {
|
||
// 考试
|
||
} else if (r.contentType == 60) {
|
||
// 作业
|
||
} else if (r.contentType == 62) {
|
||
// 评估
|
||
//评估不需要查找,因为内容就是content中
|
||
//console.log('评估处理');
|
||
}
|
||
if (this.contentData.status < 2) {
|
||
// this.contentData.status = 2; //进行中
|
||
if(r.contentType != 61&&r.contentType != 20 && r.contentType != 10){
|
||
setTimeout(() => {
|
||
this.isContentTypeTwo = r.contentType
|
||
$this.isShowTime()
|
||
}, 2000);
|
||
}
|
||
}
|
||
//以下是学习记录,50是scorm项目
|
||
if (this.contentData.contentType > 20 && this.contentData.contentType !== 50) { //非视频类的
|
||
//用户的学习时长,非音视频课程学习,单独的处理
|
||
this.isAppendTime = false;
|
||
|
||
this.appendStudyOtherHandle = setTimeout(function() {
|
||
// 开始之前把响应式清空
|
||
$this.maxDuration = 0;
|
||
$this.cumulativeDuration = 0;
|
||
// 没有设置默认时长三十分钟,
|
||
$this.maxDuration = r.duration !== 0 ? r.duration * 2 : $this.defaultMaxTime;
|
||
$this.$store.dispatch("userTrigger", {
|
||
"key": "StudyCourseOther",//课程学习的key
|
||
"title": "非音视频课内容",//事件的标题
|
||
"parameters":"second:15",//second:value 本次的学习时长
|
||
"content": "学习课程",//事件的内容
|
||
"objId": $this.courseInfo.id,//课程的id
|
||
"objType": "1",//类型
|
||
"source":"page",
|
||
"objInfo": ""+$this.courseInfo.name,
|
||
"aid":$this.userInfo.aid, //当前登录人的id
|
||
"aname":$this.userInfo.name,//当前人的姓名
|
||
"status": 1 //状态
|
||
});
|
||
$this.appendStudyOtherTime();
|
||
}, 15000); //非音视频课程学习,十五秒后记录
|
||
//this.appendStudyTime();
|
||
this.isContentType = this.contentData.contentType
|
||
if (this.contentData.contentType != 50) {
|
||
this.handleTimeout = setTimeout(function(){
|
||
$this.saveStudyInfo();
|
||
}, 5000); //5秒后记录学习完成
|
||
}else{
|
||
//scorm课件不记录完成情况,由播放回调记录完成情况
|
||
//当前先保存学习记录,未学习状态
|
||
this.saveScormStudy();
|
||
}
|
||
}
|
||
|
||
|
||
this.$nextTick(function(){
|
||
if(this.contentData.progressVideo){
|
||
this.$refs.myVideoPlayer.updateProgressByClickBar2(this.contentData.lastStudyTime,this.contentData.progressVideo);
|
||
// $this.notePlay = this.contentData.lastStudyTime;
|
||
}
|
||
|
||
//let h0=document.getElementById('id_course_player').offsetHeight;
|
||
let h=$this.$refs.coursePlayer.offsetHeight;
|
||
//let h1=$this.$refs.coursePlayer.clientHeight;
|
||
///console.log(h0,h,$this.controlHeight,'$this.controlHeight');
|
||
//解决获取高度不正的问题
|
||
if(h>400 && h<500){
|
||
h=h+40;
|
||
}else if(h>500){
|
||
h=h+60;
|
||
}
|
||
//$this.controlHeight=h-99;
|
||
$this.controlHeight=h-95;
|
||
//console.log(h,$this.controlHeight,'$this.controlHeight');
|
||
})
|
||
|
||
|
||
//console.log('this.contentData11:',this.contentData,this.curriculumData)
|
||
// 视频设置禁用处理逻辑,如果用户已全部观看完该视频,则设置为能全部拖动的逻辑,把isDrag设置为true即可,同时删除本地存储的数据
|
||
if(this.contentData.progressVideo ===1){
|
||
var obj = JSON.parse(this.contentData.content)
|
||
obj.isDrag = true
|
||
this.contentData.content = JSON.stringify(obj)
|
||
this.curriculumData.isDrag = true
|
||
var time = localStorage.getItem('videoProgressData')
|
||
var arr = time&&JSON.parse(time) || {}
|
||
//alert(con.progressVideo+'--'+con.id + '--'+JSON.stringify(arr))
|
||
delete arr[this.contentData.id];
|
||
localStorage.setItem('videoProgressData',JSON.stringify(arr))
|
||
}
|
||
if(this.contentData.progressVideo>0 && this.contentData.progressVideo !==1){
|
||
var time = localStorage.getItem('videoProgressData')
|
||
var arr = time&&JSON.parse(time) || {}
|
||
arr[this.contentData.id] = this.contentData.progressVideo
|
||
localStorage.setItem('videoProgressData',JSON.stringify(arr))
|
||
}
|
||
|
||
},
|
||
isShowTime(){
|
||
if(this.isContentTypeTwo != this.contentData.contentType){
|
||
return
|
||
}
|
||
this.contentData.status = 2;
|
||
},
|
||
showRes(r, i, index,item) { //i:子节下标,index:章下标
|
||
// 无权限查看不能点击
|
||
if(!this.isCrowd){
|
||
return
|
||
}
|
||
if (i != undefined && i!=-1 && index != undefined && r.status < 9) {
|
||
if (this.courseInfo.orderStudy) {
|
||
//判断上个是否学完
|
||
if (i == 0) {
|
||
if (index > 0) { //第一章 第一节
|
||
let preCatalog = this.catalogTree[index - 1];
|
||
let last = preCatalog.children[preCatalog.children.length - 1];
|
||
if (last.status != 9) {
|
||
this.$message.warning('请按顺序学习!');
|
||
return;
|
||
}
|
||
}
|
||
} else {
|
||
let pre = this.catalogTree[index].children[i - 1];
|
||
if (pre.status != 9) {
|
||
this.$message.warning('请按顺序学习!');
|
||
return;
|
||
}
|
||
}
|
||
//判断是否是第一个未学完的
|
||
let isAllow = false;
|
||
let has = this.catalogTree.some(treeNode => {
|
||
let hasNo = treeNode.children.some(child => {
|
||
if (child.status < 9) {
|
||
if (child.id == r.id) {
|
||
isAllow = true;
|
||
}
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
});
|
||
return hasNo;
|
||
});
|
||
if (has) {
|
||
if (!isAllow) {
|
||
this.$message.warning('请按顺序学习!');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
this.changePlayRes(r,item);
|
||
},
|
||
loadScorePraiseAndTrample() {
|
||
//加载是否请过分
|
||
apiCourseGrade.has(this.courseId).then(rs => {
|
||
if (rs.status == 200 && rs.result) {
|
||
this.scoreInfo.has = true;
|
||
}
|
||
});
|
||
apiPraises.has(1, this.courseId).then(rs => {
|
||
if (rs.status == 200 && rs.result) {
|
||
this.isPraise = true;
|
||
}
|
||
});
|
||
apiTrample.has(this.courseId).then(rs => {
|
||
if (rs.status == 200 && rs.result) {
|
||
this.isTrample = true;
|
||
}
|
||
});
|
||
},
|
||
addScore() {
|
||
let that = this;
|
||
let postData = {
|
||
courseId: this.courseInfo.id,
|
||
studyId: this.studyId,
|
||
score: this.scoreInfo.score
|
||
};
|
||
if (this.scoreInfo.score > 0) {
|
||
apiCourseGrade.grade(postData).then(rs => {
|
||
if (rs.status == 200) {
|
||
this.$message.success('打分成功,谢谢您的打分');
|
||
that.scoreInfo.has = true;
|
||
that.courseInfo.score = rs.result;
|
||
let event = {
|
||
key: "ScoreCourse", //后台的事件key 发布文章且审核通过
|
||
title: "完成课程评分", //事件的标题
|
||
parameters: "", //用户自定义参数 name:value,name:value
|
||
content: "给课程评分", //事件的内容
|
||
objId: this.courseInfo.id, //关联的id
|
||
objType: 1, //关联的类型
|
||
objInfo: this.courseInfo.name,
|
||
aid: this.userInfo.aid, //当前登录人的id
|
||
aname: this.userInfo.name, //当前人的姓名
|
||
status: 1 //状态,直接写1
|
||
}
|
||
this.$store.dispatch("userTrigger", event);
|
||
|
||
} else {
|
||
this.$message.error('打分处理失败,请稍后再试');
|
||
}
|
||
});
|
||
}
|
||
},
|
||
praiseContent() {
|
||
if(this.isTrample) {
|
||
this.$message.error('您已踩过了,不能再赞了');
|
||
return;
|
||
}
|
||
if(this.interactRuning) {
|
||
return;
|
||
}
|
||
this.interactRuning = true;
|
||
let teacherId='';
|
||
if(this.teachers.length>0){
|
||
teacherId=this.teachers[0].teacherId;
|
||
}else{
|
||
teacherId=this.courseInfo.sysCreateAid
|
||
}
|
||
let postData = {
|
||
objType: 1,
|
||
objId: this.courseId,
|
||
title: this.courseInfo.name
|
||
};
|
||
if (this.isPraise) {
|
||
apiPraises.remove(1, this.courseInfo.id).then(res => {
|
||
this.interactRuning = false;
|
||
if (res.status == 200) {
|
||
this.$message.info('已取消点赞');
|
||
this.isPraise = false;
|
||
this.courseInfo.praises--;
|
||
let event = {
|
||
key: "CancelPraise",//点赞
|
||
title: "取消点赞",//事件的标题
|
||
parameters:"author:"+teacherId,//用户自定义参数 name:value,name:value
|
||
content: "取消点赞课程",//事件的内容
|
||
objId: this.courseId,//关联的id
|
||
objType: "1",//关联的类型
|
||
objInfo: this.courseInfo.name,
|
||
aid: this.userInfo.aid, //当前登录人的id
|
||
aname: this.userInfo.name,//当前人的姓名
|
||
status: 1 //状态,直接写1
|
||
}
|
||
this.$store.dispatch("userTrigger", event);
|
||
} else {
|
||
this.$message.error('取消点赞失败,请稍后再试');
|
||
}
|
||
});
|
||
} else {
|
||
apiPraises.save(postData).then(rs => {
|
||
this.interactRuning = false;
|
||
if (rs.status == 200) {
|
||
this.$message.success('点赞成功');
|
||
this.isPraise = true;
|
||
this.courseInfo.praises++;
|
||
let event = {
|
||
key: "Praise",//点赞
|
||
title: "点赞",//事件的标题
|
||
parameters:"author:"+teacherId,//用户自定义参数 name:value,name:value
|
||
content: "点赞了课程",//事件的内容
|
||
objId: this.courseId,//关联的id
|
||
objType: "1",//关联的类型
|
||
objInfo: this.courseInfo.name,
|
||
aid: this.userInfo.aid, //当前登录人的id
|
||
aname: this.userInfo.name,//当前人的姓名
|
||
status: 1 //状态,直接写1
|
||
}
|
||
this.$store.dispatch("userTrigger", event);
|
||
//发送点赞消息
|
||
let firstTeacher=this.teachers[0];
|
||
let message={
|
||
content:this.userInfo.name+'点赞了我的课程-'+this.courseInfo.name,
|
||
refId:this.courseInfo.id,
|
||
refType:1,
|
||
source:1,
|
||
pageType:1,
|
||
pageParams:this.courseInfo.id,
|
||
pageUrl:location.href,
|
||
sendAid:this.userInfo.aid,
|
||
sendName:this.userInfo.name,
|
||
acceptName:firstTeacher.teacherName,
|
||
acceptId:firstTeacher.teacherId,
|
||
title:'系统消息',
|
||
sendType:1,
|
||
conType:this.courseInfo.type,
|
||
}
|
||
apiMessage.save(message).then(res=>{
|
||
if(res.status!=200){ console.log('发送消息失败') }
|
||
})
|
||
} else {
|
||
this.$message.error('点赞失败,请稍后再试');
|
||
}
|
||
});
|
||
}
|
||
},
|
||
treadContent() {
|
||
if (this.isPraise) {
|
||
this.$message.error('您已赞过了,不能再踩了');
|
||
return;
|
||
}
|
||
if (this.interactRuning) {
|
||
return;
|
||
}
|
||
this.interactRuning = true;
|
||
if (this.isTrample) {
|
||
apiTrample.remove(this.courseInfo.id).then(rs => {
|
||
this.interactRuning = false;
|
||
if (rs.status == 200) {
|
||
this.$message.info('已取消踩');
|
||
this.isTrample = false;
|
||
this.courseInfo.trampleCount--;
|
||
} else {
|
||
this.$message.error('取消失败,请稍后再试');
|
||
}
|
||
});
|
||
} else {
|
||
apiTrample.trample(this.courseInfo.id).then(rs => {
|
||
this.interactRuning = false;
|
||
if (rs.status == 200) {
|
||
this.$message.success('已踩');
|
||
this.isTrample = true;
|
||
this.courseInfo.trampleCount++;
|
||
} else {
|
||
this.$message.error('踩失败,请稍后再试');
|
||
}
|
||
});
|
||
}
|
||
},
|
||
statusToContent(status) {
|
||
let data = null;
|
||
switch (status) {
|
||
case 1: {
|
||
data = {
|
||
text: '未开始',
|
||
class: 'catalog-cell-state1'
|
||
};
|
||
break;
|
||
}
|
||
case 2: {
|
||
data = {
|
||
text: '进行中',
|
||
class: 'catalog-cell-state2'
|
||
};
|
||
break;
|
||
}
|
||
case 9: {
|
||
data = {
|
||
text: '已完成',
|
||
class: 'catalog-cell-state9'
|
||
};
|
||
break;
|
||
}
|
||
default: {
|
||
data = {
|
||
text: '未开始',
|
||
class: 'catalog-cell-state1'
|
||
};
|
||
}
|
||
break;
|
||
}
|
||
return data;
|
||
},
|
||
loadAuthorInfo(list, ids) {
|
||
//加载作者信息,头像,机构信息
|
||
if (ids.length == 0) {
|
||
return;
|
||
}
|
||
apiUser.getByIds(ids).then(res => {
|
||
if (res.status == 200) {
|
||
list.forEach((item, index) => {
|
||
res.result.some(author => {
|
||
if (author.aid == item.teacherId) {
|
||
item.authorInfo = author;
|
||
if(author.avatar){
|
||
item.avatar=this.fileBaseUrl + author.avatar;
|
||
}
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
});
|
||
|
||
});
|
||
} else {
|
||
//console.log('加载课程信息失败:'+res.error);
|
||
//this.$message.error(res.message);
|
||
}
|
||
});
|
||
},
|
||
|
||
onPlayerPlay() {
|
||
//console.log("开始播放");
|
||
// if(this.contentData.contentType == 10){
|
||
// if(this.contentData.status<2){
|
||
// this.contentData.status = 2;
|
||
// }
|
||
// }
|
||
this.playerBoxShow = false;
|
||
// this.onPlayerPlayFullscreen()
|
||
// this.$watermark.set(this.userInfo.name + this.userInfo.loginName);
|
||
let $this = this;
|
||
//这里有些不准备,如果文件未能加载,这个事件就是错误的
|
||
this.isAppendTime=true;
|
||
this.appendStudyTime();//启动追加学习时长
|
||
//console.log(this.contentData.status,'this.contentData.status');
|
||
// if(this.contentData.status<9){
|
||
// let completeType=this.curriculumData.completeSetup;
|
||
// //console.log(completeType,'completeType');
|
||
// if(completeType==0){
|
||
// //默认5秒后学习完成.
|
||
// $this.handleTimeout= setTimeout(function() {$this.saveStudyInfo();}, 5000); //5秒后记录学习完成
|
||
// }else{
|
||
// //先记录进行中的学习内容
|
||
// this.saveStudyItem();
|
||
// }
|
||
// }
|
||
},
|
||
|
||
onFullscreen(full) {
|
||
let divId = 'videowatermark';
|
||
var div = document.getElementById('myVideoPlayer')
|
||
if (full) {
|
||
var div3 = document.createElement("div");
|
||
div3.id = divId;
|
||
div3.setAttribute("class", "fullmark");
|
||
div3.innerHTML = '';
|
||
//从父组件传过来的水印内容
|
||
//div3.innerText =this.userInfo.name+this.userInfo.code;
|
||
for (var i = 0; i < 8; i++) {
|
||
div3.innerHTML +=
|
||
'<div style="color:#ffffff;width: 40%;height: 155px;padding-left:60px;padding-top:50px; display: flex;justify-content: center; transform: rotate(-36deg);font-size:20px;">' +
|
||
this.userInfo.name + this.userInfo.loginName + '</div>';
|
||
}
|
||
div3.style.cssText =
|
||
"position:absolute;pointer-events: none; width: 100%;height: 100%;top:0;left:0;bottom: 0;right: 0; display: flex;justify-content: center;flex-wrap: wrap;overflow: hidden; opacity:0.3;padding-top:10px";
|
||
div.appendChild(div3);
|
||
} else {
|
||
console.log("去除水印 ---- gx ----");
|
||
var markDiv = div.querySelector("#" + divId);
|
||
console.log("去除水印 ---- gx markDiv ----",markDiv);
|
||
if (markDiv) {
|
||
console.log("执行去除水印 ---- gx markDiv ----",markDiv);
|
||
div.removeChild(markDiv);
|
||
}
|
||
}
|
||
},
|
||
onPlayerPause() {
|
||
//console.log("暂停");
|
||
this.stopStudyTime();
|
||
},
|
||
onPlayerEnded() {
|
||
this.playerBoxShow = true;
|
||
this.stopStudyTime();
|
||
if(this.contentData.status < 9) {
|
||
this.finishStudyItem();
|
||
}
|
||
},
|
||
onPlayerPlaying(itme) {
|
||
this.isAppendTime = true;//可以追加学习时长
|
||
this.intTimeNote = parseInt(itme);
|
||
//console.log("当前播放"+itme);
|
||
//console.log("当前播放11"+itme);
|
||
if (this.contentData.contentType && this.contentData.contentType == 10) {
|
||
let intTime = parseInt(itme);
|
||
//判断是否完成
|
||
let completeType = this.curriculumData.completeSetup;
|
||
let completeSecond = this.curriculumData.second;
|
||
if (!completeSecond || completeType == 0) {
|
||
completeSecond = 5; //如果没有就采用默认的时间了
|
||
}
|
||
if (this.contentData.status < 9) { //因为1按进度,2按时长都是计算时间,所以这里直接大于0处理
|
||
if (completeType == 1) {
|
||
let finishPercent = this.curriculumData.setupTage;
|
||
let videDuration = this.contentData.duration;
|
||
let percent = intTime * 100 / videDuration;
|
||
if (percent >= finishPercent) {
|
||
this.finishStudyItem();
|
||
}
|
||
} else {
|
||
if (intTime >= completeSecond) {
|
||
this.finishStudyItem();
|
||
}
|
||
}
|
||
}
|
||
//下面是每隔10秒记录一下次
|
||
let saveTime = Math.floor(intTime % 10);
|
||
if (intTime > 10 && intTime != this.contentData.lastStudyTime && saveTime == 0 && this.contentData
|
||
.studyItemId != '') {
|
||
this.contentData.lastStudyTime = intTime;
|
||
let postData = {
|
||
itemId: this.contentData.studyItemId,
|
||
videoTime: intTime
|
||
};
|
||
//console.log('this.courseInfo:',this.contentData)
|
||
if(!this.curriculumData.isDrag && this.contentData.progressVideo !=1){
|
||
var time = localStorage.getItem('videoProgressData')
|
||
var arr = time&&JSON.parse(time) || {}
|
||
if(arr[this.blobId] && this.contentData.progressVideo<arr[this.blobId]) {
|
||
postData.progressVideo = arr[this.blobId]
|
||
postData.contentId = this.contentData.id
|
||
postData.courseId = this.contentData.courseId
|
||
}
|
||
}
|
||
//console.log('记录播放时间')
|
||
apiStudy.studyVideoTime(postData).then(rs => {
|
||
if (rs.status != 200) {
|
||
console.log('记录播放时间错误');
|
||
}
|
||
});
|
||
}
|
||
}
|
||
},
|
||
audioPlaying(item, currentTime) {
|
||
//console.log("当前播放"+item);
|
||
let intTime = parseInt(currentTime);
|
||
this.handleAudioTimeUpdate(intTime)
|
||
//判断是否完成
|
||
let completeType = this.curriculumData.completeSetup;
|
||
let completeSecond = this.curriculumData.second;
|
||
if (!completeSecond || completeType == 0) {
|
||
completeSecond = 5; //如果没有就采用默认的时间了
|
||
}
|
||
if (this.contentData.status < 9) { //因为1按进度,2按时长都是计算时间,所以这里直接大于0处理
|
||
if (completeType == 1) {
|
||
let finishPercent = this.curriculumData.setupTage;
|
||
let videDuration = this.contentData.duration;
|
||
let percent = intTime * 100 / videDuration;
|
||
if (percent >= finishPercent) {
|
||
this.finishStudyItem();
|
||
}
|
||
} else {
|
||
if (intTime >= completeSecond) {
|
||
this.finishStudyItem();
|
||
}
|
||
}
|
||
}
|
||
//下面是每隔10秒记录一下次
|
||
let saveTime = Math.floor(intTime % 10);
|
||
if (intTime > 10 && intTime != this.contentData.lastStudyTime && saveTime == 0 && this.contentData
|
||
.studyItemId) {
|
||
this.contentData.lastStudyTime = intTime;
|
||
let postData = {
|
||
itemId: this.contentData.studyItemId,
|
||
videoTime: intTime
|
||
};
|
||
//console.log('this.courseInfo:',this.contentData)
|
||
if(!this.curriculumData.isDrag && this.contentData.progressVideo !=1){
|
||
var time = localStorage.getItem('videoProgressData')
|
||
var arr = time&&JSON.parse(time) || {}
|
||
if(arr[this.blobId] && this.contentData.progressVideo<arr[this.blobId]) {
|
||
postData.progressVideo = arr[this.blobId]
|
||
postData.contentId = this.contentData.id
|
||
postData.courseId = this.contentData.courseId
|
||
}
|
||
}
|
||
//console.log('记录播放时间')
|
||
apiStudy.studyVideoTime(postData).then(rs => {
|
||
if (rs.status != 200) {
|
||
console.log('记录播放时间错误');
|
||
}
|
||
});
|
||
}
|
||
},
|
||
audioPlay() {
|
||
//console.log("开始播放");
|
||
// if(this.contentData.contentType == 20 && this.contentData.status < 2){
|
||
// this.contentData.status = 2;
|
||
// }
|
||
let $this = this;
|
||
this.isAppendTime=true;
|
||
this.appendStudyTime();//启动追加学习时长
|
||
},
|
||
audioPause() {
|
||
//console.log("暂停");
|
||
this.stopStudyTime();//停止追加学习时长
|
||
},
|
||
audioEnd() {
|
||
//console.log("播放结束");
|
||
this.stopStudyTime();//启动追加学习时长
|
||
if (this.contentData.status < 9) {
|
||
this.finishStudyItem();
|
||
}
|
||
},
|
||
// 获取数据信息
|
||
loadData() {
|
||
let $this=this;
|
||
apiStudy.studyIndexPost({
|
||
cid: this.courseId,
|
||
addView:true,
|
||
audiences:this.audiences
|
||
}).then(rs => {
|
||
if (rs.status == 200) {
|
||
if(rs.result.contents.length==0){
|
||
$this.$message.error('课程内容已删除或课程已不再使用');
|
||
return;
|
||
}
|
||
if(!rs.result.course.enabled){
|
||
$this.$message.error('十分抱歉,此课程已停用,如需使用,请联系管理员。');
|
||
return;
|
||
}
|
||
//设置必须的字段
|
||
if(rs.result.contents.length==1){
|
||
$this.tab=2;
|
||
//console.log('内容只有一个');
|
||
}
|
||
if(!rs.result.isCrowd){
|
||
$this.$message.error('您没有查看该课程的权限');
|
||
}
|
||
// 是否播放
|
||
this.isCrowd = rs.result.isCrowd
|
||
if (rs.result.course.type == 20) { //有目录课程
|
||
|
||
rs.result.sections.forEach(sec => {
|
||
sec.status = 0; //加入状态表未开始
|
||
rs.result.contents.forEach(c => {
|
||
c.status = 0; //初始化状态 ,未开始
|
||
c.studyItemId = ''; //初始化字段,学习条目id
|
||
c.lastStudyTime = 0; //初始化上次一学习的时间,作用于视频插放
|
||
});
|
||
});
|
||
this.sectionList = rs.result.sections;
|
||
}else if(rs.result.course.type==10){ //无目录课程
|
||
//如果是多个的话,就需要过滤一下
|
||
let indexNum=0;
|
||
let delIndexs=[];
|
||
rs.result.contents.forEach((c,cidx) => {
|
||
c.status = 0; //
|
||
c.studyItemId = '';
|
||
c.lastStudyTime = 0;
|
||
if(c.sortIndex==1){
|
||
c.contentName=rs.result.course.name;
|
||
indexNum++;
|
||
if(indexNum>1){
|
||
delIndexs.push(cidx);
|
||
}
|
||
}else if(c.sortIndex==2){
|
||
c.contentName='作业';
|
||
}else if(c.sortIndex==3){
|
||
c.contentName='考试';
|
||
}else if(c.sortIndex==4){
|
||
c.contentName='评估';
|
||
}
|
||
});
|
||
if(delIndexs.length>0){
|
||
delIndexs.forEach(delIdx=>{
|
||
rs.result.contents.splice(delIdx,1);
|
||
})
|
||
}
|
||
}
|
||
this.courseInfo = rs.result.course;
|
||
|
||
if (rs.result.teachers && rs.result.teachers.length > 0) {
|
||
let userIds = [];
|
||
let ctoUsers = [];
|
||
rs.result.teachers.forEach(item => {
|
||
item.authorInfo = {
|
||
aid: '',
|
||
name: '',
|
||
orgInfo: '',
|
||
avatar: '',
|
||
code: '',
|
||
sex: null,
|
||
sign:''
|
||
};
|
||
userIds.push(item.teacherId);
|
||
ctoUsers.push({
|
||
aid: item.teacherId,
|
||
name: item.teacherName
|
||
});
|
||
});
|
||
this.toUsers = ctoUsers;
|
||
this.loadAuthorInfo(rs.result.teachers, userIds);
|
||
this.teachers = rs.result.teachers;
|
||
}
|
||
this.contentList = rs.result.contents;
|
||
//处理内容的名称
|
||
this.totalContent = rs.result.contents.length;
|
||
//加载学习的数据
|
||
//this.loadStudyData();
|
||
this.loadStudyData(rs.result);
|
||
|
||
} else {
|
||
this.$message.error(rs.message);
|
||
}
|
||
});
|
||
},
|
||
loadStudyData(result) {
|
||
let $this=this;
|
||
this.loadScorePraiseAndTrample();
|
||
this.studyId = result.studyId;
|
||
//对已学习的内容进行比对,重要的字段, 学习内容id,在后缀的
|
||
let playIndex = -1;
|
||
this.contentList.forEach((con, conIdx) => {
|
||
result.contentStudys.forEach((scon, sconIdx) => {
|
||
if (scon.contentId == con.id) {
|
||
//定位显示的内容
|
||
if ($this.initContentId != '' && $this.initContentId == scon.contentId) {
|
||
//定位当前学习的内容,是上一次学习的内容
|
||
playIndex = conIdx;
|
||
} else {
|
||
if (sconIdx == 0 && con.contentType < 52) {
|
||
playIndex = conIdx;
|
||
}
|
||
}
|
||
//console.log(scon.contentId,con.id);
|
||
con.lastStudyTime = scon.lastStudyTime;
|
||
con.progressVideo = scon.progressVideo;
|
||
//以下判断是为了兼容之前的问题,学习状态
|
||
if (scon.status) {
|
||
con.status = scon.status;
|
||
} else {
|
||
con.status = 9;
|
||
}
|
||
con.studyItemId = scon.id; //这个就是学习内容(条目)的id
|
||
//console.log(scon.id,"scon.id");
|
||
//console.log(con,"scon.id");
|
||
}
|
||
});
|
||
});
|
||
|
||
if (this.courseInfo.type == 10) {
|
||
///console.log(this.contentList[0],'ccccc11111')
|
||
this.showRes(this.contentList[0]);
|
||
} else {
|
||
//如果没有,就定位第一项内容
|
||
if (playIndex === -1) {
|
||
// this.showRes(this.contentList[0]);
|
||
//console.log(this.catalogTree,'ccccc22222')
|
||
this.showRes(this.catalogTree[0].children[0])
|
||
} else {
|
||
//console.log(this.contentList[0],'ccccc3333')
|
||
this.showRes(this.contentList[playIndex]);
|
||
}
|
||
}
|
||
},
|
||
saveScormStudy() {
|
||
//只记录SCORM课件的学习
|
||
if (this.contentData.contentType != 50) {
|
||
return;
|
||
}
|
||
if (this.contentData.status == 9) {
|
||
//已学习完的,不会再记录
|
||
return;
|
||
}
|
||
let params = {
|
||
studyId: this.studyId, //学习id,
|
||
courseId: this.courseId, //课程id,
|
||
contentId: this.contentData.id, //内容id,
|
||
contentType: this.contentData.contentType,
|
||
contentName: this.contentData.contentName, //内容名称
|
||
progress: 1,
|
||
status: 2,
|
||
contentTotal: this.totalContent
|
||
};
|
||
apiStudy.studyContent(params).then(res => {
|
||
if (res.status == 200) {
|
||
this.contentData.status = 2; //进行中
|
||
this.contentData.studyItemId = res.result; //学习记录id
|
||
} else {
|
||
console.log('记录学习失败:' + res.message + ',' + res.error);
|
||
}
|
||
});
|
||
},
|
||
saveStudyInfo() {
|
||
this.tentative = true
|
||
if(this.isContentType){
|
||
if(this.isContentType != this.contentData.contentType){
|
||
//定时器产生的,不记录
|
||
return
|
||
}
|
||
}
|
||
//记录课件学习信息
|
||
if (this.contentData.contentType >= 60) {
|
||
//只有在课件页面停留超过5秒才会记录
|
||
return;
|
||
}
|
||
if (this.contentData.status == 9) {
|
||
//已学习完的,不用再添加
|
||
return;
|
||
}
|
||
let params = {
|
||
studyId: this.studyId, //学习id,
|
||
courseId: this.courseId, //课程id,
|
||
contentId: this.contentData.id, //内容id,
|
||
contentType: this.contentData.contentType,
|
||
contentName: this.contentData.contentName, //内容名称
|
||
progress: 100,
|
||
status: 9,
|
||
contentTotal: this.totalContent
|
||
};
|
||
apiStudy.studyContent(params).then(res => {
|
||
if (res.status == 200) {
|
||
this.contentData.status = 9; //完成
|
||
this.contentData.studyItemId = res.result; //学习记录id
|
||
} else {
|
||
console.log('记录学习失败:' + res.message + ',' + res.error);
|
||
}
|
||
});
|
||
},
|
||
homeWorkSubmit(){
|
||
if(this.contentData.contentType == 60){
|
||
this.contentData.status = 9;
|
||
}
|
||
},
|
||
startTest(val){
|
||
if(this.contentData.contentType == 61){
|
||
if(this.contentData.status < 2){
|
||
this.contentData.status = 2;
|
||
}
|
||
}
|
||
},
|
||
progress(val) {
|
||
const progressValue = parseFloat(val) * 100;
|
||
this.sendEventProgress = Number(progressValue.toFixed(2));
|
||
},
|
||
saveStudyDuration(duration) { //保存本地存储的学习时长
|
||
if (duration > 0) {
|
||
//发送用户学习事件
|
||
//console.log('保存到后台学习时长='+duration);
|
||
let postData={
|
||
"key": "StudyCourse",//课程学习的key
|
||
"title": "学习课程",//事件的标题
|
||
"parameters":"second:"+duration,//second:value,total:value 本次的学习时长
|
||
"content": "学习课程【"+this.courseInfo.name+"】",//事件的内容
|
||
"objId": this.courseInfo.id,//课程的id
|
||
"objType": "1",//类型
|
||
"source":"page",
|
||
"objInfo": ""+this.courseInfo.name,
|
||
"aid":this.userInfo.aid, //当前登录人的id
|
||
"aname":this.userInfo.name,//当前人的姓名
|
||
"status": 1, //状态
|
||
"contentId": this.contentData.id,
|
||
}
|
||
if(this.resType == 10){
|
||
postData.progress = this.sendEventProgress;
|
||
}
|
||
//静默处理
|
||
apiStat.sendEvent(postData).then(rs=>{
|
||
if(rs.status == 200) {
|
||
// this.appendStartTime = new Date();//重新计时
|
||
// studyUtil.clearStudyDuration(); //清除本地存储
|
||
} else {
|
||
console.log(rs.message);
|
||
}
|
||
});
|
||
let postAppendData = {
|
||
id: this.appentId,
|
||
studyId: this.studyId,
|
||
courseId: this.courseInfo.id,
|
||
contentId: this.contentData.id,
|
||
studyInfo: this.courseInfo.name +"-" +this.contentData.contentName,
|
||
duration: duration
|
||
};
|
||
apiStudy.appendStudyTime(postAppendData).then(rs => {
|
||
if (rs.status == 200) {
|
||
this.appentId = rs.result;
|
||
studyUtil.clearStudyDuration(); //清除本地存储
|
||
} else {
|
||
console.log(rs.message);
|
||
}
|
||
});
|
||
}
|
||
},
|
||
//结束追加学习时长
|
||
stopStudyTime(){
|
||
//console.log('停止追加学习时长');
|
||
this.isAppendTime=false;
|
||
//暂停让他为空 从新计时
|
||
this.appendStartTime = null
|
||
if (this.appendHandle != null) {
|
||
window.clearTimeout(this.appendHandle);
|
||
}
|
||
},
|
||
appendStudyTime() {
|
||
// 暂停的时候重新从十五秒开始计时
|
||
if(!this.appendStartTime){
|
||
this.appentInterval = 15
|
||
}
|
||
//重新覆盖时间
|
||
this.appendStartTime = new Date().getTime();
|
||
//console.log('开始追加学习时长',this.isAppendTime);
|
||
if (this.studyId == '') {
|
||
return;
|
||
}
|
||
if (!this.contentData.id) {
|
||
return;
|
||
}
|
||
if (!this.isAppendTime) {
|
||
return;
|
||
}
|
||
this.appendHandle && window.clearTimeout(this.appendHandle);
|
||
//启动下次追加学习时长
|
||
this.appendHandle = setTimeout(() => {
|
||
let endTime = new Date().getTime();
|
||
this.appentInterval = 60
|
||
let totalTime = Math.round((endTime - this.appendStartTime) / 1000);
|
||
this.appendStudyTime();
|
||
this.saveStudyDuration(totalTime)
|
||
}, this.appentInterval * 1000);
|
||
},
|
||
//追加学习时长, flag是否提交到后台
|
||
// appendStudyTime() {
|
||
// //console.log('开始追加学习时长',this.isAppendTime);
|
||
// if (this.studyId == '') {
|
||
// return;
|
||
// }
|
||
// if (!this.contentData.id) {
|
||
// return;
|
||
// }
|
||
// if (!this.isAppendTime) {
|
||
// this.appendStartTime = null;
|
||
// return;
|
||
// }
|
||
|
||
// if (this.appendHandle != null) {
|
||
// window.clearTimeout(this.appendHandle);
|
||
// }
|
||
// //首先从本地读取
|
||
// let duration = studyUtil.getStudyDuration();
|
||
// //console.log('追加学习时长,当前本地积累的学习时长='+duration);
|
||
// //追加学习长
|
||
// let $this = this;
|
||
// if (this.appendStartTime == null) {
|
||
// this.appendStartTime = new Date();
|
||
// this.appendHandle = setTimeout(function() {
|
||
// $this.appendStudyTime();
|
||
// }, $this.appentInterval); //设置定时追加学习时长
|
||
// //保存之前的
|
||
// if (duration >= 60 ) {
|
||
// this.saveStudyDuration(duration);
|
||
// }
|
||
// return;
|
||
// }
|
||
// //如果当前追加开始时间不为空
|
||
// let now = new Date();
|
||
// let m = now.getTime() - this.appendStartTime.getTime(); //相差的毫秒数
|
||
// // console.log(m/1000,'时间');
|
||
|
||
// let sen = Math.round(m / 1000); //计算秒数
|
||
// // console.log('定时器时间',sen);
|
||
// // 每次添加的是定时器计时的时间
|
||
// duration = duration + sen;//追加的是秒
|
||
// if (duration >= 60) { //一分钟保存一次
|
||
// this.saveStudyDuration(duration);
|
||
// } else {
|
||
// studyUtil.setStudyDuration(duration); //添加到本地存储中
|
||
// }
|
||
// //重新覆盖时间
|
||
// this.appendStartTime = new Date();
|
||
// //启动下次追加学习时长
|
||
// this.appendHandle = setTimeout(function() {
|
||
// $this.appendStudyTime();
|
||
// }, $this.appentInterval);
|
||
// },
|
||
|
||
finishStudyItem() { //设置完成学习的内容,针对于音视频的内容
|
||
if (!this.contentData.studyItemId) {
|
||
//这种可能没有,不过这里也是为了万中那个1
|
||
!this.tentative && this.saveStudyInfo();
|
||
} else {
|
||
let params = {
|
||
itemId: this.contentData.studyItemId,
|
||
studyId: this.studyId,
|
||
courseId: this.courseId,
|
||
cnum: this.totalContent
|
||
}
|
||
apiVideoStudy.finishStudyItem(params).then(res => {
|
||
if (res.status == 200) {
|
||
this.contentData.status = 9;
|
||
this.contentData.progress = 100;
|
||
} else {
|
||
console.log("记录完成学习失败:" + res.message + "," + res.error);
|
||
}
|
||
});
|
||
}
|
||
},
|
||
|
||
saveStudyItem() { //先保存学习的内容,针对于音视频的内容
|
||
if (this.contentData.studyItemId) {
|
||
return; //已经有记录的,不需要再保存了
|
||
}
|
||
let params = {
|
||
studyId: this.studyId, //学习id,
|
||
courseId: this.courseId, //课程id,
|
||
contentId: this.contentData.id, //内容id,
|
||
contentType: this.contentData.contentType, //内容id,
|
||
contentName: this.contentData.contentName, //内容名称
|
||
progress: 0,
|
||
lastStudyTime: 0,
|
||
status: 2,
|
||
studyDuration: 0,
|
||
contentTotal: this.totalContent
|
||
};
|
||
apiVideoStudy.saveStudyItem(params).then(res => {
|
||
if (res.status == 200) {
|
||
this.contentData.studyItemId = res.result.id;
|
||
this.contentData.status = 2; //进行中状态
|
||
} else {
|
||
console.log("记录学习失败:" + res.message + "," + res.error);
|
||
}
|
||
});
|
||
},
|
||
formatTime(duration) {
|
||
let min = 0;
|
||
if (duration > 0) {
|
||
min = parseInt(duration / 60);
|
||
}
|
||
return min;
|
||
},
|
||
heartabone() {
|
||
this.tab = 1
|
||
},
|
||
heartabtwo() {
|
||
this.tab = 2
|
||
},
|
||
handleAudioTimeUpdate(currentTime) {
|
||
// if(this.contentStudysLength.length == 0){
|
||
let params = {
|
||
studyId: this.studyId, //学习id,
|
||
courseId: this.courseId, //课程id,
|
||
contentId: this.contentData.id, //内容id,
|
||
contentType: this.contentData.contentType,
|
||
contentName: this.contentData.contentName, //内容名称
|
||
progress: 1,
|
||
status: 2,
|
||
contentTotal: this.totalContent
|
||
};
|
||
if(currentTime > 2 && this.trueFalse){
|
||
apiStudy.studyContent(params).then(()=>{
|
||
if(this.contentData.status<2){
|
||
this.contentData.status = 2;
|
||
}
|
||
})
|
||
this.trueFalse = false
|
||
}
|
||
// }
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
::v-deep .el-icon-arrow-down{
|
||
color: #000;
|
||
font-weight: 900;
|
||
font-size: 16px;
|
||
}
|
||
.el-menu,
|
||
.el-menu-item,
|
||
.el-submenu__title {
|
||
background-color: transparent !important; /* 设置背景色为透明,以移除默认的背景颜色变化 */
|
||
color: inherit !important; /* 确保文字颜色不变,如果需要的话 */
|
||
}
|
||
|
||
/* 取消选中效果 */
|
||
.el-menu-item.is-active,
|
||
.el-submenu__title.is-active {
|
||
background-color: transparent !important; /* 移除选中时的背景色 */
|
||
color: inherit !important; /* 保持文字颜色与未选中时一致,如果需要的话 */
|
||
}
|
||
|
||
/* 如果有特定的 hover 样式,也可以取消 */
|
||
.el-menu-item:hover,
|
||
.el-submenu__title:hover {
|
||
background-color: transparent !important; /* 移除鼠标悬停时的背景色变化 */
|
||
color: inherit !important; /* 保持文字颜色不变 */
|
||
}
|
||
//内容块样式定义
|
||
.course-content {
|
||
min-height: 745px;
|
||
|
||
margin: 20px auto;
|
||
.course-playbox {
|
||
background-color: #fff;
|
||
min-height: 400px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
.course-player{ //内容播放区域
|
||
flex:1;
|
||
min-width: 700px;
|
||
min-height: 400px;
|
||
max-height: 800px;
|
||
//height: 100%;
|
||
border: 1px solid #ffffff;
|
||
padding-right: 20px;
|
||
// overflow: auto;
|
||
}
|
||
.course-control{ //内容控制区域
|
||
width: 420px;
|
||
}
|
||
}
|
||
.course-infobox {
|
||
margin-top: 20px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
.course-info {
|
||
flex:1;
|
||
min-width: 700px;
|
||
|
||
min-height: 710px;
|
||
box-sizing: border-box;
|
||
padding-right: 20px;
|
||
}
|
||
.course-teacher{
|
||
width: 420px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.control-tab {
|
||
margin: 35px 30px 10px 30px;
|
||
|
||
border-bottom: 1px solid #D8D8D8;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding-bottom: 12px;
|
||
div {
|
||
color: #666666;
|
||
cursor: pointer;
|
||
}
|
||
.control-tab-active {
|
||
color: #333333;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
.course-info-tab {
|
||
display: flex;
|
||
padding-top: 30px;
|
||
margin-left: 47px;
|
||
div {
|
||
color: #333333;
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
margin-right: 50px;
|
||
}
|
||
|
||
.course-info-tab-active {
|
||
color: #333333;
|
||
font-weight: 600;
|
||
position: relative;
|
||
span {
|
||
display: inline-block;
|
||
width: 69px;
|
||
height: 4px;
|
||
background: #387DF7;
|
||
border-radius: 5px;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 128%;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
.course-info-row{
|
||
padding: 10px 0;
|
||
font-size: 18px;
|
||
color: #343434;
|
||
img{
|
||
width:18px
|
||
}
|
||
.course-info-text{
|
||
margin: 10px 0;
|
||
font-size: 14px;
|
||
text-indent: 2em;
|
||
color: #666666;
|
||
word-break: break-all;
|
||
}
|
||
}
|
||
//右侧老师部分头部及标题
|
||
.cteacher-top {
|
||
background-color: #fff;
|
||
margin-top: 0px;
|
||
.cteacher-top-bar{
|
||
width: 100%;
|
||
height: 15px;
|
||
}
|
||
.cteacher-top-title{
|
||
padding-left:30px;
|
||
padding-top:10px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
line-height: 50px;
|
||
}
|
||
|
||
}
|
||
//右侧老师部分 老师列表
|
||
.cteacher-list {
|
||
background-color: #fff;
|
||
padding: 10px 30px 30px 30px;
|
||
}
|
||
|
||
//以下是未整理的样式,上面的整理之后的样式
|
||
.coures-note {
|
||
min-height: 500px;
|
||
padding-left: 17px;
|
||
padding-top: 10px;
|
||
|
||
.note-tole {
|
||
color: #333333;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.note-info {}
|
||
}
|
||
|
||
.player-box {
|
||
position: absolute;
|
||
// top: 62px;
|
||
// left: 184px;
|
||
width: 300px;
|
||
left: 50%;
|
||
top: 50%;
|
||
transform: translate(-50%, -50%);
|
||
height: 187px;
|
||
background: rgba(74, 74, 74, .5);
|
||
border-radius: 33px;
|
||
text-align: center;
|
||
padding: 20px;
|
||
box-sizing: border-box;
|
||
|
||
.player-praise {
|
||
margin-top: 25px;
|
||
display: flex;
|
||
// justify-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.player-rate {
|
||
margin-top: 35px;
|
||
}
|
||
}
|
||
|
||
.score-text {
|
||
font-size: 18px;
|
||
color: #ffb30f;
|
||
font-family: 'Arial';
|
||
margin-left: 23px;
|
||
// font-weight: 600;
|
||
}
|
||
|
||
// .score {
|
||
// display: flex;
|
||
// justify-content: center;
|
||
// align-items: center;
|
||
|
||
// .el-rate {
|
||
// display: inline-block;
|
||
// }
|
||
// // margin-bottom: 19px;
|
||
// .score-no {
|
||
// color: #ffb30f;
|
||
// padding: 5px 0;
|
||
// background: #efefef;
|
||
// border-radius: 20px;
|
||
// width: 65px;
|
||
// font-size: 12px;
|
||
// font-weight: 600;
|
||
// text-align: center;
|
||
// }
|
||
// }
|
||
|
||
.portal-content-title {
|
||
font-weight: 600;
|
||
padding: 10px;
|
||
font-size: 22px;
|
||
line-height: 40px;
|
||
color: #333333;
|
||
word-break: break-all;
|
||
}
|
||
|
||
.type-kuang {
|
||
color: #666666;
|
||
border: 1px solid #666666;
|
||
}
|
||
|
||
.type-click {
|
||
color: #ffb30f !important;
|
||
border: 1px solid #ffb30f !important;
|
||
}
|
||
|
||
::v-deep .el-rate__icon {
|
||
font-size: 22px;
|
||
margin-right: 6px;
|
||
color: #ff8e00;
|
||
transition: 0.3s;
|
||
}
|
||
|
||
.ref-score {
|
||
// background: #e4e4e4;
|
||
// width: 64px;
|
||
// height: 32px;
|
||
// border-radius: 17px;
|
||
// line-height: 32px;
|
||
// // opacity: 0.24;
|
||
// color: #000;
|
||
// font-size: 14px;
|
||
// border: none;
|
||
}
|
||
|
||
.icon-small {
|
||
width: 16px;
|
||
height: 16px;
|
||
line-height: 16px;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.con-audio {
|
||
padding: 50px;
|
||
text-align: center;
|
||
|
||
.con-audio-title {
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.con-audio-player {
|
||
min-height: 300px;
|
||
padding: 60px 50px 80px 50px;
|
||
}
|
||
}
|
||
|
||
.hyper-link {
|
||
padding-left: 20px;
|
||
text-align: center;
|
||
padding-top: 100px;
|
||
|
||
.hyper-link-row {
|
||
padding: 20px;
|
||
}
|
||
}
|
||
|
||
.catalog-box {
|
||
background: #fff;
|
||
|
||
// padding: 15px 0px;
|
||
// box-shadow: 1px 1px 2px 2px #ededed;
|
||
.title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
padding-left: 20px;
|
||
}
|
||
}
|
||
|
||
.collapse-title {
|
||
flex: 1 0 90%;
|
||
order: 1;
|
||
}
|
||
|
||
.el-collapse-item__header {
|
||
flex: 1 0 auto;
|
||
order: -1;
|
||
}
|
||
|
||
.course-interact {
|
||
height: 54px;
|
||
// padding-top: 10px;
|
||
// padding-right: 10px;
|
||
padding: 0 20px;
|
||
line-height: 54px;
|
||
background-color: #FFFFFF;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.interact-btn {
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.uc-badge {
|
||
margin-top: 10px;
|
||
margin-right: 40px;
|
||
}
|
||
|
||
.cres-list {
|
||
list-style-type: decimal;
|
||
margin: 0px;
|
||
|
||
li {
|
||
line-height: 30px;
|
||
}
|
||
|
||
.current {
|
||
color: #1ea0fa;
|
||
}
|
||
}
|
||
|
||
.uc-course {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
border: 1px solid #f0f0f0;
|
||
padding: 10px;
|
||
|
||
.uc-course-img {
|
||
width: 200px;
|
||
|
||
img {
|
||
width: 200px;
|
||
border: 1px solid #f4f4f5;
|
||
}
|
||
}
|
||
|
||
.uc-course-info {
|
||
flex: 1;
|
||
line-height: 28px;
|
||
padding: 0px 10px;
|
||
|
||
.uc-course-name {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.uc-course-text {
|
||
color: #747474;
|
||
}
|
||
}
|
||
|
||
.uc-course-btns {
|
||
width: 150px;
|
||
}
|
||
}
|
||
|
||
.catalog-cell-state2 {
|
||
height: 24px;
|
||
width: 58px;
|
||
line-height: 20px;
|
||
border: 0px dotted #bed2f8;
|
||
padding: 3px 10px;
|
||
color: #ff8e00;
|
||
font-size: 12px;
|
||
border-radius: 6px;
|
||
margin-left: 2px;
|
||
background: #ffedd6;
|
||
}
|
||
|
||
.catalog-cell-state9 {
|
||
height: 24px;
|
||
width: 58px;
|
||
line-height: 20px;
|
||
border: 0px dotted #bed2f8;
|
||
padding: 3px 10px;
|
||
color: #3e7fff;
|
||
font-size: 12px;
|
||
border-radius: 6px;
|
||
margin-left: 2px;
|
||
background: #edf2fd;
|
||
// margin-left: 68%;
|
||
// background-color: #BED2F8;
|
||
}
|
||
|
||
.catalog-cell-state1 {
|
||
height: 24px;
|
||
width: 58px;
|
||
line-height: 20px;
|
||
border: 0px dotted #edf2fd;
|
||
border-radius: 6px;
|
||
padding: 3px 10px;
|
||
color: #ff3e3e;
|
||
font-size: 12px;
|
||
margin-left: 2px;
|
||
background: #fff0f0;
|
||
}
|
||
|
||
.catalog {
|
||
height: 100%;
|
||
max-width: 500px;
|
||
overflow: auto;
|
||
|
||
.catalog-row {
|
||
margin: 0px;
|
||
padding: 0px 10px 10px 10px;
|
||
|
||
.title-type {
|
||
width: 36px;
|
||
height: 24px;
|
||
padding: 2px 5px;
|
||
color: #666666;
|
||
border: 1px solid #666666;
|
||
margin-right: 8px;
|
||
}
|
||
|
||
ul {
|
||
padding: 0px;
|
||
margin: 0px;
|
||
|
||
li {
|
||
padding: 6px 0;
|
||
}
|
||
}
|
||
|
||
.catalog-cell {
|
||
line-height: 32px;
|
||
cursor: pointer;
|
||
list-style: none;
|
||
margin: 0px;
|
||
padding-left: 20px;
|
||
color: #5c5c5c;
|
||
}
|
||
}
|
||
}
|
||
|
||
.video-div {
|
||
position: absolute;
|
||
z-index: 999999999;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(101, 101, 101, 0.9);
|
||
|
||
.good {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-top: 200px;
|
||
|
||
div {
|
||
line-height: 1;
|
||
margin: 0 15px;
|
||
|
||
.svg-icon {
|
||
width: 30px;
|
||
height: 30px;
|
||
}
|
||
}
|
||
|
||
div:nth-of-type(2) {
|
||
.svg-icon {
|
||
transform: scaleX(-1);
|
||
transform: rotate(180deg);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
::v-deep .el-tag {
|
||
background-color: #ecf5ff;
|
||
border-color: #409EFF;
|
||
display: inline-block;
|
||
height: 28px;
|
||
padding: 0 10px;
|
||
line-height: 28px;
|
||
font-size: 12px;
|
||
color: #3e7fff;
|
||
border-width: 1px;
|
||
border-style: solid;
|
||
border-radius: 0px;
|
||
box-sizing: border-box;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
::v-deep .teacher .teacher-avator .teacher-text {
|
||
background: none;
|
||
border: none;
|
||
}
|
||
|
||
.teacher {
|
||
background-color: #ffffff;
|
||
display: flex;
|
||
width: 100%;
|
||
border-top: none;
|
||
padding: 10px 0px;
|
||
.teacher-avator {
|
||
cursor: pointer;
|
||
::v-deep .el-avatar {
|
||
width: 60px !important;
|
||
height: 60px !important;
|
||
border-radius: 50%;
|
||
img{
|
||
width: 100% !important;
|
||
}
|
||
}
|
||
.teacher-text {
|
||
width: 68px;
|
||
height: 68px;
|
||
|
||
div {
|
||
img {
|
||
width: 68px;
|
||
height: 68px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.teacher-info {
|
||
flex: 1;
|
||
.teacher-name {
|
||
padding: 5px 5px 10px 10px;
|
||
}
|
||
.teacher-remark {
|
||
padding: 0px 5px 0 10px;
|
||
font-size: 14px;
|
||
color: #666666;
|
||
line-height: 20px;
|
||
overflow:hidden;
|
||
text-overflow:ellipsis;
|
||
// white-space:nowrap;
|
||
word-break:break-all
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
.breadname {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
//目录的样式更改
|
||
::v-deep .el-collapse-item {
|
||
.el-collapse-item__header {
|
||
// position: relative;
|
||
direction: rtl;
|
||
display: flex;
|
||
// justify-content;
|
||
justify-content: space-between;
|
||
|
||
// .el-collapse-item__arrow{
|
||
// float:right;
|
||
// }
|
||
// span{
|
||
// float:right;
|
||
// }
|
||
i {
|
||
display: none
|
||
}
|
||
}
|
||
}
|
||
|
||
.course-units {
|
||
padding: 10px 30px;
|
||
.units-info {
|
||
padding: 0 30px;
|
||
height: 60px;
|
||
line-height: 60px;
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
overflow: hidden;
|
||
white-space:nowrap;
|
||
word-break:break-all;
|
||
text-overflow:ellipsis;
|
||
}
|
||
|
||
.units-active {
|
||
background: #F6F6F6;
|
||
color: #387DF7;
|
||
font-weight: 600;
|
||
cursor: text;
|
||
img {
|
||
width: 18px;
|
||
height: 20px;
|
||
vertical-align: middle;
|
||
// margin-right: 20px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.more {
|
||
float: right;
|
||
}
|
||
|
||
.coures-title {
|
||
margin-left: 82px;
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
color: #FFFFFF;
|
||
margin-top: 25px;
|
||
|
||
div {
|
||
float: left;
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
color: #FFFFFF;
|
||
line-height: 20px;
|
||
|
||
}
|
||
|
||
span {
|
||
float: left;
|
||
font-size: 16px;
|
||
font-weight: 400;
|
||
color: #FFFFFF;
|
||
margin-left: 27px;
|
||
}
|
||
|
||
h6 {
|
||
float: left;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #FFFFFF;
|
||
margin: 0 20px;
|
||
|
||
}
|
||
}
|
||
|
||
::v-deep.el-breadcrumb__item:first-child .el-breadcrumb__inner a,
|
||
.el-breadcrumb__inner .is-link {
|
||
color: #fff !important;
|
||
}
|
||
|
||
::v-deep.el-breadcrumb__item:last-child .el-breadcrumb__inner {
|
||
color: #fff !important;
|
||
}
|
||
|
||
::v-deep.hear-nav {
|
||
color: #fff !important;
|
||
}
|
||
|
||
.breadcrumb-nav {
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.coures-bg {
|
||
width: 100%;
|
||
height: 200px;
|
||
background: url('../../../public/images/couresdetail.png');
|
||
}
|
||
</style>
|