Files
learning-system-portal/src/views/portal/course/rePreview.vue
2024-09-25 11:02:11 +08:00

730 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<portal-header current="course"></portal-header>
<div class="portal-content xcontent">
<el-breadcrumb separator-class="el-icon-arrow-right" class="breadname" style="margin:20px 0">
<el-breadcrumb-item :to="{ path: '/course' }"
>课程列表</el-breadcrumb-item
>
<el-breadcrumb-item>课程详情</el-breadcrumb-item>
</el-breadcrumb>
<!-- <span style="display:block;margin-bottom:10px">课程列表 > 课程预览</span> -->
<el-row :gutter="10">
<el-col :span="16">
<div>
<div class="re-title">{{ courseInfo.name }}</div>
<!--课程资源内容播放-->
<div class="player" style="min-height: 510px; width: 100%;border: 1px solid #ffffff;background-color: #FFFFFF;overflow: auto;">
<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 v-if="resType == 10" :src="fileBaseUrl+curriculumData.url"
@onPlayerPlaying="onPlayerPlaying"
:initTime="contentData.lastStudyTime"
@onPlayerPlay="onPlayerPlay"
@onPlayerPause="onPlayerPause"
@onPlayerEnded="onPlayerEnded"></videoPlayer>
</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="fileBaseUrl+curriculumData.url"
:name="contentData.contentName"
@onPlaying="audioPlaying"
@onPlay="audioPlay"
@onPause="audioPause"
@onPlayEnd="audioEnd">
</audioPlayer>
</div>
</div>
</div>
<div v-if="resType == 40">
<pdfPreview :autoScroll="true" v-if="resType == 40" :filePath="fileBaseUrl+contentData.content"></pdfPreview>
</div>
<div v-if="resType == 41">
<div class="textimg" style="padding: 20px;" v-html="contentData.content"></div>
</div>
<div v-if="resType == 52">
<div v-if="contentData.content!=''">
<!-- <div class="hyper-link" v-if="!showiframe">
<div class="hyper-link-row">{{contentData.contentName}}</div>
<div class="hyper-link-row">{{contentData.content}}</div>
<div class="hyper-link-row">
<el-button @click="showiframe = true" type="warning">本页面打开</el-button>
<el-button @click="widthOpen(contentData.content)" type="primary">新窗口打开</el-button>
</div>
</div>
<div v-if="showiframe">
<iframe :src="contentData.content" style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe>
</div> -->
<hyper-link :content="contentData"></hyper-link>
</div>
</div>
<div v-if="resType == 60">
<homework :showRecord="false" :showSubmit="false" :content="contentData"></homework>
</div>
<div v-if="resType == 61 ">
<exam :showTest="true" :showRecord="false" :showSubmit="false" :content="contentData"></exam>
</div>
<div v-if="resType == 62" style="padding:5px">
<assess v-if="contentData.id" :showSubmit="false" :showRecord="false" :content="contentData"></assess>
</div>
</div>
</div>
<div class="course-interact">
<div class="score" style="display: flex;">
<el-rate disabled v-model="courseInfo.score" :max="5" :allow-half="true" show-score text-color="#ff9900" score-template="{value}"></el-rate>
<div v-if="!scoreInfo.has" style="margin-left:10px;cursor: pointer;">
<!-- <el-popover placement="top" width="300" trigger="hover">
<div style="text-align:center;line-height:50px;padding:20px 0px">
<el-rate v-model="scoreInfo.score"></el-rate>
<div style="padding-top:30px">
<el-button @click="addScore">提交评分</el-button>
</div>
</div>
<el-tag slot="reference">去打分</el-tag> -->
<!-- </el-popover> -->
</div>
</div>
<div style="display: flex;justify-content: flex-end;cursor: pointer;">
<div>
<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')">
</div>
<div style="margin-left: 15px;">
<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')">
</div>
</div>
</div>
<!-- <div style="padding-left:5px;margin: 20px 0px;background-color: #FFFFFF;" class="info">
<comments v-if="courseInfo.id && courseInfo.id!=''" :obj-type="1" :obj-id="courseInfo.id" :toUsers="toUsers"></comments>
</div> -->
</div>
</el-col>
<el-col :span="8">
<div class="course-units">
<!-- <p class="title">课程目录</p> -->
<!-- <el-tabs type="border-card" v-model="ctabName" @tab-click="ctabChange">
<el-tab-pane label="课程目录" name="catalog"> -->
<div style="min-height: 500px;">
<div class="catalog" v-if="courseInfo.type == 20">
<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" 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=""> {{index+1}}.
{{ list.contentName }}
<!-- </div> -->
</div>
</div>
</div>
<!-- </el-tab-pane>
</el-tabs> -->
</div>
<div style="margin-top: 15px;">
<el-card :body-style="{ padding: '0px' }" class="teachers">
<div class="top">授课讲师</div>
<div>
<div class="teacher" v-for="(item, idx) in teachers" :key="idx" >
<div class="teacher-avator">
<el-avatar v-if="item.authorInfo.avatar !== '' " :src="fileBaseUrl + item.authorInfo.avatar" shape="square" :size="50"></el-avatar>
<div v-else class="uavatar">
<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">{{ item.teacherName }}</div>
<div class="teacher-remark" v-html="item.remark"></div>
</div>
</div>
</div>
</el-card>
</div>
</el-col>
</el-row>
</div>
<portal-footer></portal-footer>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import portalHeader from '@/components/PortalHeader.vue';
import portalFooter from '@/components/PortalFooter.vue';
import comments from "@/components/Portal/comments.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 interactBar from '@/components/Portal/interactBar.vue';
import apiStudy from '@/api/modules/courseStudy.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 apiCourse from '@/api/modules/course.js';
import apiUser from '@/api/system/user.js';
import apiCourseFile from '@/api/modules/courseFile.js';
import {resListMap, resOwnerListMap,courseType,getType} from '@/utils/tools.js';
import pdfPreview from '@/components/PdfPreview/index.vue';
import audioPlayer from '@/components/AudioPlayer/index.vue';
import videoPlayer from '@/components/VideoPlayer/index.vue';
import hyperLink from '@/components/Course/hyperLink.vue';
export default {
name: 'ucStudyIndex',
components: { courseImage,portalHeader, portalFooter,hyperLink, comments, homework, exam, interactBar,assess,pdfPreview,audioPlayer,videoPlayer},
data() {
return {
curriculumData:{url:'',isDrag:false,completeSetup:1,},// 课件内容
publicPath:process.env.VUE_APP_PUBLIC_PATH,
showiframe: false,
courseId:'',//当前课程的id
studyId: '',//当前学习的id
initContentId:'',//初始化当前学习的内容节
contentData:{},//当前的显示的内容
courseInfo:{id:'',name:''},//课程信息
totalContent:0,//课程内容数量
pageCount:0,
currentPage:0,
// contentData:{},// 章节内容
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
contentList: [],
sectionList:[],
teachers: [],
toUsers:[],//对于@教师的处理
getType: getType,
ctabName: 'catalog',
toolsTabName: 'info',
videoEnded: false,
resType: null,
activeNames: [0, 1, 2, 3, 4],
scoreInfo:{
dlgShow:false,
score:5,
has:false,
},
isPraise:false,
isTrample:false
};
},
mounted(){
this.courseId=this.$route.query.id;
this.loadData();
},
computed:{
catalogTree(){
let treeList=[];
let $this=this;
$this.sectionList.forEach(sec=>{
let treeNode={section:sec,children:[]}
let finish=true;
$this.contentList.forEach(c=>{
if(c.csectionId==sec.id){
if(c.status<9){
finish=false;
}
treeNode.children.push(c);
}
});
if(finish){
sec.status=9;
}
treeList.push(treeNode);
})
return treeList;
}
},
methods: {
widthOpen(url) {
window.open(this.webBaseUrl+url,'_blank');
},
onPlayerPlay(){
//console.log("开始播放");
},
onPlayerPause(){
//console.log("暂停");
},
onPlayerEnded(){
//console.log("播放结束");
},
onPlayerPlaying(itme){
// //console.log("当前播放"+itme);
// //console.log("当前播放11"+itme);
},
audioPlaying(item){
//console.log("当前播放"+item);
},
audioPlay(){
//console.log("开始播放");
},
audioPause(){
//console.log("暂停");
},
audioEnd(){
//console.log("播放结束");
},
loadData() {
apiCoursePortal.detail(this.courseId,true).then(rs=>{
if(rs.status==200){
//设置必须的字段
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){
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.sectionList=rs.result.sections;
this.courseInfo=rs.result.course;
this.teachers=rs.result.teachers;
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,};
userIds.push(item.teacherId);
ctoUsers.push({aid:item.teacherId,name:item.teacherName});
})
this.toUsers=ctoUsers;
this.loadAuthorInfo(rs.result.teachers,userIds)
}
this.contentList=rs.result.contents;
this.totalContent=rs.result.contents.length;
}else{
this.$message.error(rs.message);
}
})
},
ctabChange(e) {
console.log(e);
},
toolsTabChange(e) {
},
showRes(r) { //显示内容部分
let $this=this;
this.resType = r.contentType;
//console.log(r,'r');
if(r.contentType == 10 || r.contentType == 20) {
if (r.content.startsWith('\{')) {
this.curriculumData = JSON.parse(r.content);
} else {
this.curriculumData.url = r.content;
}
} else if(r.contentType == 40) {
//let url = this.fileBaseUrl + r.content;
if(r.content!='' && r.content.indexOf('.pdf')==-1){
apiCourseFile.detail(r.contentRefId).then(cfrs=>{
if(cfrs.status==200){
r.content=cfrs.result.previewFilePath;
//console.log(r.content);
}else{
$this.$message.error('加载pdf课件文件失败');
}
});
}
if(r.content==''){
apiCourseFile.detail(r.contentRefId).then(cfrs=>{
if(cfrs.status==200){
r.content=cfrs.result.previewFilePath;
}else{
$this.$message.error('加载pdf课件文件失败');
}
});
}
}
this.contentData = r;
},
videoEnd() {
},
handleChange(val) {
console.log(val);
},
addScore(){
},
praiseContent(){
},
treadContent(){
},
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;
return true;
}else{
return false;
}
})
});
}else{
//console.log('加载课程信息失败:'+res.error);
//this.$message.error(res.message);
}
});
},
}
};
</script>
<style scoped lang="scss">
.textimg{
word-break: break-all;
img{
max-width: 100%;
}
}
.course-units {
background: #fff;
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;
}
}
}
.one-line-ellipsis{
overflow: hidden;
box-sizing: border-box;
white-space: nowrap;
word-break: break-all;
text-overflow: ellipsis;
// display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1; /* 这里是超出几行省略 */
}
.re-title{
word-break: break-all;
background-color: #FFFFFF;
font-weight: 600;
border-bottom:1px solid #d0d0d0 ;
padding: 10px;
font-size: 22px;
color: #333333;
word-break:break-all;
}
.icon-small{
width: 20px;
height: 20px;
line-height: 20px;
vertical-align: middle;
}
.con-audio{
padding: 50px;
text-align: center;
.con-audio-title{
font-size: 16px;
font-weight: 700;
}
.con-audio-player{
padding: 20px 100px;
}
}
.hyper-link{
padding-left:20px;
text-align: center;
padding-top: 100px;
.hyper-link-row{
padding: 20px;
}
}
.catalog-box {
background: #fff;
.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: 40px;
padding-top: 5px;
padding-right: 10px;
background-color: #FFFFFF;
display: flex;
justify-content: space-between;
}
.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;
// border: 0px dotted #1ea0fa;
// padding: 3px 10px;
// color: #1ea0fa;
// font-size: 12px;
// margin-left: 2px;
// background: #ffedd6;
// float: right;
// }
// .catalog-cell-state9 {
// height: 24px;
// width: 58px;
// line-height: 20px;
// border: 0px dotted #1ea0fa;
// padding: 3px 10px;
// color: green;
// font-size: 12px;
// background: #edf2fd;
// float: right;
// }
// .catalog-cell-state1 {
// height: 24px;
// width: 58px;
// line-height: 20px;
// border: 0px dotted #1ea0fa;
// padding: 3px 10px;
// color: red;
// font-size: 12px;
// margin-left: 2px;
// background: #fff0f0;
// float: right;
// }
.catalog {
height: 500px;
max-width: 500px;
overflow:auto;
.catalog-row {
margin: 0px;
padding: 0px 10px 10px 10px;
.title-type-info{
width: 60px !important;
height: 20px;
line-height: 20px;
padding: 0px 3px;
text-align: center;
color: #666666;
border: 1px solid #666666;
margin-right: 8px;
}
ul {
padding: 0px;
margin: 0px;
li{
padding: 5px 0;
}
}
.catalog-cell {
display: flex;
line-height: 32px;
cursor: pointer;
list-style: none;
margin: 0px;
padding-left: 20px;
color: #5c5c5c;
span{
}
}
}
}
.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);
}
}
// margin-bottom: 50px;
// line-height: 20px;
// .el-link{
// font-size: 30px;
// color: #70a5f4;
// margin: 0 30px;
// }
}
.score {
display: flex;
justify-content: center;
align-items: center;
}
}
.teacher{
background-color: #FFFFFF;
display: flex;
border-top: 1px solid #e7e7e7;
padding: 10px 0px;
.teacher-avator{
.uavatar{
div{
img{
width: 50px;
height: 50px;
}
}
}
}
.teacher-info{
flex: 1;
.teacher-name{
padding: 0px 5px 10px 10px;
}
.teacher-remark{
padding: 0px 5px 0 10px;
font-size: 12px;
color: #797979;
}
}
}
.teachers {
background-color: #fff;
margin-top: 10px;
padding: 5px 15px 5px 10px;
.top {
font-size: 16px;
font-weight: 600;
line-height: 50px;
}
}
</style>