mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-11 11:56:44 +08:00
3264 lines
110 KiB
Vue
3264 lines
110 KiB
Vue
<template>
|
||
<div>
|
||
<div class="xpage-coures-banner">
|
||
<portal-header
|
||
current="course"
|
||
textColor="#fff"
|
||
:goSearch="1"
|
||
></portal-header>
|
||
<div style="margin: 0px 80px">
|
||
<portal-header
|
||
current="course"
|
||
textColor="#fff"
|
||
:goSearch="1"
|
||
></portal-header>
|
||
<div style="margin: 0px 80px">
|
||
<div class="banner-crumbs">
|
||
<router-link :to="newEmployee ? `/new-employee/study` : `/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="renderCourse">
|
||
<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
|
||
v-if="!renderCourse && Internet == 2"
|
||
style="margin: 350px 250px"
|
||
class="jianjie pdftext"
|
||
id="pdfPreview"
|
||
>
|
||
<div
|
||
style="
|
||
margin-top: 40px;
|
||
font-weight: 700;
|
||
font-size: 22px;
|
||
color: #ccc;
|
||
"
|
||
>
|
||
<span
|
||
>十分抱歉,您当前的网络环境不符合观看要求。为了保障课程信息的安全,您需要接入公司内网才能观看。</span
|
||
>
|
||
</div>
|
||
<div
|
||
style="margin-top: 20px; text-align: center"
|
||
@click="refreshPage"
|
||
>
|
||
<el-button type="primary">重新检测</el-button>
|
||
</div>
|
||
</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: 10px;
|
||
display: flex;
|
||
align-items: center;
|
||
"
|
||
>
|
||
<!-- <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> -->
|
||
<p style="margin-right: 10px">告诉我们您的喜欢程度</p>
|
||
<el-rate
|
||
v-model="scoreInfo.score"
|
||
@change="showConfirmScore"
|
||
:allow-half="true"
|
||
></el-rate>
|
||
<div v-if="isShowScoreConfirm">
|
||
<span class="score-text">{{
|
||
toScore(scoreInfo.score)
|
||
}}</span>
|
||
<span style="font-size: 18px">分</span>
|
||
<el-button
|
||
style="margin-left: 10px"
|
||
type="primary"
|
||
size="mini"
|
||
@click="addScore"
|
||
>确定</el-button
|
||
>
|
||
<el-button size="mini" @click="handleCancelScore"
|
||
>取消</el-button
|
||
>
|
||
</div>
|
||
<!-- <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="min-height: 350px; max-height: 650px; 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"
|
||
v-if="catalogTree.length > 1"
|
||
>
|
||
<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>
|
||
<div v-else>
|
||
<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>
|
||
</div>
|
||
</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>
|
||
<!-- ai播放器相关 -->
|
||
<!-- ai文稿 -->
|
||
<div class="ai-script" v-if="contentData.contentType == 10 && tab == 3">
|
||
<ai-script ref="aiscript" :blobId="blobId" :isDrag="curriculumData.isDrag" @changeCurrentTime="changeCurrentTime"></ai-script>
|
||
</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>
|
||
<!-- ai播放器相关 -->
|
||
<div
|
||
@click="coutab(4)"
|
||
v-if="courseInfo.aiAbstract == 1"
|
||
style="position: relative;"
|
||
:class="courestab == 4 ? 'course-info-tab-active' : ''"
|
||
>
|
||
AI摘要<span class=""></span>
|
||
<img style="position: absolute;top: -18px;right: -23px;width: 36px;height: 24px;" src="@/assets/images/course/courseNew.png" alt="">
|
||
</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>
|
||
<!-- ai播放器相关 -->
|
||
<div
|
||
v-show="courestab == 4"
|
||
style="padding-left: 17px; padding-top: 20px;background-color: #fff;"
|
||
>
|
||
<div style="padding: 30px;line-height: 24px;letter-spacing: 0.3px;color: rgba(102, 102, 102, 1);">
|
||
{{ courseInfo.summaryContent || '' }}
|
||
</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 v-if="item.authorInfo && item.authorInfo.avatar">
|
||
<el-avatar
|
||
:src="fileBaseUrl + item.authorInfo.avatar"
|
||
shape="circle"
|
||
:size="50"
|
||
></el-avatar>
|
||
</div>
|
||
<div v-else-if="item.photo">
|
||
<el-avatar
|
||
:src="item.photo"
|
||
shape="circle"
|
||
:size="50"
|
||
></el-avatar>
|
||
</div>
|
||
<div v-else class="teacher-text">
|
||
<div v-if="item.authorInfo && item.authorInfo.sex === 1">
|
||
<img
|
||
src="../../../public/images/Avatarwoman.png"
|
||
alt=""
|
||
/>
|
||
</div>
|
||
<div v-else>
|
||
<img src="../../../public/images/Avatarman.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>
|
||
<el-dialog
|
||
class="protocol"
|
||
:close-on-click-modal="false"
|
||
:visible="protocolDialogVisible"
|
||
width="30%"
|
||
:show-close="false"
|
||
>
|
||
<div class="protocol-title">{{ warnTitle }}</div>
|
||
<div class="protocol-content">  {{ warn }}</div>
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button type="primary" @click="protocolDialogVisible = false"
|
||
>确 定</el-button
|
||
>
|
||
</span>
|
||
</el-dialog>
|
||
<!-- <div><portal-footer></portal-footer></div> -->
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import { mapGetters, mapMutations } 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 aiScript from "../../components/Course/aiScript.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,
|
||
aiScript,
|
||
noteComments,
|
||
portalFooter,
|
||
followButton,
|
||
},
|
||
data() {
|
||
return {
|
||
isShowScoreConfirm: false,
|
||
protocolDialogVisible: false,
|
||
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,
|
||
},
|
||
Internet: 3, //1是成功 2是是失败 3是检测中
|
||
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,
|
||
renderCourse: true,
|
||
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, //非音频默认最大时间
|
||
warn: "测试内容",
|
||
warnTitle: "测试标题",
|
||
isFinishingStudyItem: false, // 防止重复调用完成状态更新接口
|
||
newEmployee: false
|
||
};
|
||
},
|
||
mounted() {
|
||
this.getInternet();
|
||
// 增加的用户受众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();
|
||
},
|
||
computed: {
|
||
// ai播放器相关
|
||
...mapGetters(["userInfo", 'selectableLang']),
|
||
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;
|
||
},
|
||
},
|
||
methods: {
|
||
// ai播放器相关
|
||
// 处理从AI文稿组件传递过来的时间跳转事件
|
||
changeCurrentTime(time) {
|
||
console.log(time,'time')
|
||
this.$refs.myVideoPlayer && this.$refs.myVideoPlayer.seekToTime(time);
|
||
},
|
||
...mapMutations({
|
||
SET_selectableLang: 'video/SET_selectableLang',
|
||
SET_courseInfo: 'video/SET_courseInfo',
|
||
}),
|
||
handleCancelScore() {
|
||
this.isShowScoreConfirm = false;
|
||
this.scoreInfo.score = 5;
|
||
},
|
||
showConfirmScore() {
|
||
this.isShowScoreConfirm = true;
|
||
},
|
||
handleOpen(key, path) {
|
||
if (this.isFalse) {
|
||
this.defaultOpeneds = [key];
|
||
}
|
||
this.isFalse = false;
|
||
},
|
||
handleClose(key, path) {},
|
||
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.contentData.lastStudyTime = time;
|
||
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);
|
||
setTimeout(() => {
|
||
$this.$refs.myVideoPlayer.startPlay(time);
|
||
}, 10);
|
||
|
||
console.log("开始播放2");
|
||
} else {
|
||
this.$message.error("资源已不存在或更换过,已无法定位");
|
||
}
|
||
}
|
||
this.playerBoxShow = false;
|
||
},
|
||
//笔记组件触发,记录当前播放时间
|
||
videoLocation() {
|
||
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;
|
||
let urlSign = encodeURIComponent(encrypt(beforeUrl));
|
||
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;
|
||
}
|
||
this.blobId = this.contentData.id;
|
||
},
|
||
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);
|
||
// ai播放器相关 - 视频类型加载ai相关功能
|
||
if (r.contentType == 10) {
|
||
this.handleAIVideo(r.boeaiSubtitleRspList, r);
|
||
}
|
||
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.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 (r.contentType == 10) {
|
||
console.log("视频处理lastStudyTime", this.contentData.lastStudyTime);
|
||
console.log("视频处理progressVideo", this.contentData.progressVideo);
|
||
this.$refs.myVideoPlayer.updateProgressByClickBar2(
|
||
this.contentData.lastStudyTime,
|
||
this.contentData.progressVideo
|
||
);
|
||
}
|
||
|
||
let h = $this.$refs.coursePlayer.offsetHeight;
|
||
//解决获取高度不正的问题
|
||
if (h > 400 && h < 500) {
|
||
h = h + 40;
|
||
} else if (h > 500) {
|
||
h = h + 60;
|
||
}
|
||
// 移除高度控制 防止内容塌陷
|
||
// $this.controlHeight=h-95;
|
||
});
|
||
|
||
// 视频设置禁用处理逻辑,如果用户已全部观看完该视频,则设置为能全部拖动的逻辑,把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;
|
||
},
|
||
// ai播放器相关 - 视频处理
|
||
handleAIVideo(list = [], r) {
|
||
console.log('触发了-----------list', list);
|
||
this.SET_selectableLang(list);
|
||
this.SET_courseInfo(this.courseInfo);
|
||
if (this.courseInfo.aiSet && this.courseInfo.aiAbstract == 1 && this.courseInfo.summaryContent) {
|
||
this.coutab(4);
|
||
}
|
||
console.log("ai处理", this.selectableLang);
|
||
},
|
||
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 {
|
||
}
|
||
});
|
||
},
|
||
|
||
onPlayerPlay() {
|
||
this.playerBoxShow = false;
|
||
let $this = this;
|
||
//这里有些不准备,如果文件未能加载,这个事件就是错误的
|
||
this.isAppendTime = true;
|
||
this.appendStudyTime(); //启动追加学习时长
|
||
},
|
||
|
||
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() {
|
||
this.stopStudyTime();
|
||
},
|
||
onPlayerEnded() {
|
||
this.playerBoxShow = true;
|
||
this.stopStudyTime();
|
||
if (this.contentData.status < 9) {
|
||
this.finishStudyItem();
|
||
}
|
||
},
|
||
onPlayerPlaying(itme) {
|
||
this.isAppendTime = true; //可以追加学习时长
|
||
this.intTimeNote = parseInt(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,
|
||
id: this.appentId,
|
||
studyId: this.studyId,
|
||
courseId: this.contentData.courseId,
|
||
contentId: this.contentData.id,
|
||
studyInfo:
|
||
this.courseInfo.name + "-" + this.contentData.contentName,
|
||
duration: 10,
|
||
};
|
||
//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.updateStudyVideoTime(postData).then((rs) => {
|
||
if (rs.status != 200) {
|
||
console.log("记录播放时间错误");
|
||
} else {
|
||
studyUtil.clearStudyDuration(); //清除本地存储
|
||
}
|
||
});
|
||
}
|
||
}
|
||
},
|
||
audioPlaying(item, currentTime) {
|
||
let intTime = parseInt(currentTime);
|
||
console.log("======音频播放" + intTime);
|
||
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,
|
||
id: this.appentId,
|
||
studyId: this.studyId,
|
||
courseId: this.contentData.courseId,
|
||
contentId: this.contentData.id,
|
||
studyInfo: this.courseInfo.name + "-" + this.contentData.contentName,
|
||
duration: 10,
|
||
};
|
||
//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.updateStudyVideoTime(postData).then((rs) => {
|
||
if (rs.status != 200) {
|
||
console.log("记录播放时间错误");
|
||
} else {
|
||
studyUtil.clearStudyDuration(); //清除本地存储
|
||
}
|
||
});
|
||
}
|
||
},
|
||
audioPlay() {
|
||
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.isPermission) {
|
||
this.protocolDialogVisible = true;
|
||
}
|
||
if (
|
||
!rs.result.isPermission ||
|
||
(rs.result.isPermission && this.Internet == 1)
|
||
) {
|
||
// this.getInternet()
|
||
this.renderCourse = true;
|
||
} else {
|
||
// this.Internet=1;
|
||
this.renderCourse = false;
|
||
this.protocolDialogVisible = true;
|
||
}
|
||
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;
|
||
this.warn = rs.result.warn;
|
||
this.warnTitle = rs.result.warnTitle;
|
||
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(rs.result);
|
||
} else {
|
||
this.$message.error(rs.message);
|
||
}
|
||
});
|
||
},
|
||
refreshPage() {
|
||
location.reload();
|
||
// this.getInternet();
|
||
// this.loadData();
|
||
},
|
||
getXmlHttpRequest() {
|
||
if (window.XMLHttpRequest) {
|
||
return new XMLHttpRequest();
|
||
} else if (window.ActiveXObject) {
|
||
return new ActiveXObject("Microsoft.XMLHTTP");
|
||
}
|
||
},
|
||
// 检测是否为内网
|
||
getInternet() {
|
||
this.Internet = 3;
|
||
let $this = this;
|
||
let xmlhttp = this.getXmlHttpRequest();
|
||
let timedOut = false;
|
||
let timer = setTimeout(function () {
|
||
timedOut = true;
|
||
xmlhttp.abort();
|
||
}, 1000);
|
||
// 1. 拼接随机参数(时间戳+随机数,确保URL唯一,破缓存)
|
||
const url =
|
||
window.location.protocol +
|
||
"//uapi.boe.com.cn/500.html?t=" +
|
||
Date.now() +
|
||
Math.random();
|
||
// // 2. 打开 HEAD 请求(URL已带随机参数)
|
||
xmlhttp.open("HEAD", url, true);
|
||
// xmlhttp.open(
|
||
// "HEAD",
|
||
// window.location.protocol + "//uapi.boe.com.cn/500.html",
|
||
// true
|
||
// );
|
||
xmlhttp.send();
|
||
xmlhttp.onreadystatechange = function () {
|
||
if (xmlhttp.readyState == 4) {
|
||
if (xmlhttp.status == 200) {
|
||
clearTimeout(timer);
|
||
$this.Internet = 1;
|
||
} else {
|
||
clearTimeout(timer);
|
||
// $this.protocolDialogVisible=true
|
||
$this.Internet = 2;
|
||
}
|
||
} else {
|
||
if (timedOut) return; //忽略中止请求
|
||
clearTimeout(timer); //取消等待的超时
|
||
}
|
||
};
|
||
},
|
||
loadStudyData(result) {
|
||
let $this = this;
|
||
this.loadScorePraiseAndTrample();
|
||
this.studyId = result.studyId;
|
||
//对已学习的内容进行比对,重要的字段, 学习内容id,在后缀的
|
||
let playIndex = -1;
|
||
this.contentList.forEach((con, conIdx) => {
|
||
con.progressVideo = con.progressVideo || 0;
|
||
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;
|
||
}
|
||
}
|
||
con.lastStudyTime = scon.lastStudyTime;
|
||
con.progressVideo = scon.progressVideo || 0;
|
||
//以下判断是为了兼容之前的问题,学习状态
|
||
if (scon.status) {
|
||
con.status = scon.status;
|
||
} else {
|
||
con.status = 9;
|
||
}
|
||
con.studyItemId = scon.id; //这个就是学习内容(条目)的id
|
||
}
|
||
});
|
||
});
|
||
|
||
if (this.courseInfo.type == 10) {
|
||
this.showRes(this.contentList[0]);
|
||
} else {
|
||
//如果没有,就定位第一项内容
|
||
if (playIndex === -1) {
|
||
this.showRes(this.catalogTree[0].children[0]);
|
||
} else {
|
||
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,
|
||
// type: 1
|
||
// };
|
||
// apiStudy.updateStudyVideoTime(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);
|
||
},
|
||
|
||
finishStudyItem() {
|
||
//设置完成学习的内容,针对于音视频的内容
|
||
if (!this.contentData.studyItemId) {
|
||
//这种可能没有,不过这里也是为了万中那个1
|
||
!this.tentative && this.saveStudyInfo();
|
||
} else {
|
||
// 如果正在处理完成请求,则直接返回,避免重复调用
|
||
if (this.isFinishingStudyItem) {
|
||
return;
|
||
}
|
||
let params = {
|
||
itemId: this.contentData.studyItemId,
|
||
studyId: this.studyId,
|
||
courseId: this.courseId,
|
||
cnum: this.totalContent,
|
||
};
|
||
this.isFinishingStudyItem = true; // 设置标志位
|
||
apiVideoStudy
|
||
.finishStudyItem(params)
|
||
.then((res) => {
|
||
if (res.status == 200) {
|
||
this.contentData.status = 9;
|
||
this.contentData.progress = 100;
|
||
} else {
|
||
console.log("记录完成学习失败:" + res.message + "," + res.error);
|
||
}
|
||
this.isFinishingStudyItem = false; // 重置标志位
|
||
})
|
||
.catch((error) => {
|
||
console.error("记录完成学习出错:", error);
|
||
this.isFinishingStudyItem = false; // 出错时也重置标志位
|
||
});
|
||
}
|
||
},
|
||
|
||
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;
|
||
},
|
||
// ai播放器相关
|
||
heartabthree() {
|
||
this.tab = 3;
|
||
},
|
||
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;
|
||
}
|
||
},
|
||
},
|
||
destroyed() {
|
||
this.cleanAppendTime();
|
||
this.stopStudyTime();
|
||
},
|
||
};
|
||
</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-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 100%;
|
||
}
|
||
.course-player {
|
||
//内容播放区域
|
||
flex: 4; // 80%高度
|
||
min-width: 700px;
|
||
// min-height: 400px;
|
||
// max-height: 800px;
|
||
height: 80%;
|
||
border: 1px solid #ffffff;
|
||
padding-right: 20px;
|
||
background-color: rgb(238, 238, 238);
|
||
// overflow: auto;
|
||
}
|
||
.course-control {
|
||
//内容控制区域
|
||
width: 420px;
|
||
}
|
||
}
|
||
|
||
@media screen and (max-width: 1200px) {
|
||
.course-playbox,
|
||
.course-infobox {
|
||
flex-direction: column;
|
||
}
|
||
.course-player,
|
||
.course-info {
|
||
min-width: 100%;
|
||
padding-right: 0;
|
||
}
|
||
.course-control,
|
||
.course-teacher {
|
||
width: 100%;
|
||
margin-top: 20px;
|
||
}
|
||
}
|
||
.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;
|
||
width: 100%;
|
||
max-width: 300px;
|
||
margin: 20px auto;
|
||
height: 187px;
|
||
background: rgba(74, 74, 74, 0.8);
|
||
border-radius: 33px;
|
||
text-align: center;
|
||
padding: 20px;
|
||
top: 50%;
|
||
box-sizing: border-box;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
|
||
.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 {
|
||
flex: 1; // 20%高度
|
||
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");
|
||
}
|
||
|
||
.protocol {
|
||
.protocol-title {
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
text-align: center;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.protocol-content {
|
||
font-size: 14px;
|
||
line-height: 25px;
|
||
}
|
||
}
|
||
</style>
|