You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1460 lines
45 KiB

<template>
<div style="padding: 24px">
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="back" :content="curriculumName || courseName"></el-page-header>
</div>
</el-card>
<el-card class="source-card" shadow="hover" style="background: none;">
<div class="flex">
<div class="cover" :class="{ 'is-word': showMask1 }">
<!--实验台不显示课程封面-->
<img v-if="coverUrl" :src="coverUrl" alt="" width="100%" height="100%">
<template v-else-if="iframeSrc">
<iframe class="inner fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe>
<template v-if="showMask">
<div class="mask" style="top: 0;width:100%;height: 48px;"></div>
<div class="mask" style="top: 53px;width:100%;height: 30px;"></div>
<div class="mask" style="bottom: 0;right: 40px;width:195px;height: 22px;background-color: #444;"></div>
</template>
<template v-if="showMask1">
<div class="word-mask" style="height: 40px;"></div>
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
</template>
<template v-if="showMask2">
<div class="excel-mask1" style="height: 48px;"></div>
</template>
</template>
<div class="pdf inner" v-else-if="pdfSrc">
<img class="full" src="@/assets/img/screen/full.png" alt="" @click="fullScreen">
<p class="arrow">
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left"
:class="{ grey: currentPage == 1 }"></span>
{{ currentPage }} / {{ pageCount }}
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right"
:class="{ grey: currentPage == pageCount }"></span>
</p>
<div style='color:#393A3D;height: 30px;background: #393A3D;'></div>
<pdf class="pdf-wrap" :src="pdfSrc" :page="currentPage" @num-pages="pageCount = $event"
@page-loaded="currentPage = $event" @loaded="loadPdfHandler">
</pdf>
</div>
<div class="inner" v-else-if="playAuth">
<div class="video_wid" id="player"></div>
</div>
<div class="inner" v-else-if="videoSrc">
<video class="video" :key="videoSrc" width="100%" height="100%" autoplay controls>
<source :src="videoSrc" type="video/mp4">
您的浏览器不支持 video 标签。
</video>
</div>
</div>
<div class="catalog">
<div v-if="mallId" class="m-b-20">
<el-button v-if="mallId && !overdue" class="entry" type="primary" size="small"
@click="showBuy">续费</el-button>
<el-button v-if="practiceTheoreticalPaper" class="entry" type="primary" @click="entry(1)">进入理论</el-button>
<el-button v-if="practicePracticeProject" class="entry" type="primary" @click="entry(0)">进入实训</el-button>
</div>
<div class="list">
<h4 class="title">{{ curriculumName || courseName }}</h4>
<div>
<h6 class="pro-title">当前教学进度</h6>
<el-progress :stroke-width="12" :percentage="schedule" :format="percentFormat"
:text-color="'#fff'"></el-progress>
</div>
<div class="types">
<div :class="['item', { active: type === 1 }]" @click="typeChange(1)">
<i class="icon el-icon-notebook-2"></i> 目录
</div>
<div :class="['item', { active: type === 2 }]" @click="typeChange(2)">
<i class="icon el-icon-timer"></i> 教学进度
</div>
</div>
<div class="chapters">
<template v-if="type === 1">
<template v-if="chapterList.length">
<div class="chapter" v-for="(item, i) in chapterList" :key="i">
<div class="chapterName">{{ item.name }}</div>
<div class="section" v-if="item.subsectionList.length">
<p class="sectionName" :class="{ active: curLink === `${item.name}${section.name}` }"
v-for="(section, i) in item.subsectionList" :key="i" @click="preview(section, item.name)">
<img v-if="section.fileType === 'pptx'" src="@/assets/img/exts/ppt.png" alt="">
<img v-else-if="section.fileType === 'mp4'" src="@/assets/img/exts/video.png" alt="">
<img v-else-if="section.fileType === 'doc' || section.fileType === 'docx'"
src="@/assets/img/exts/word.png" alt="">
<img v-else-if="section.fileType === 'xlsx' || section.fileType === 'xls'"
src="@/assets/img/exts/excel.png" alt="">
<img v-else-if="section.fileType === 'txt'" src="@/assets/img/exts/txt.png" alt="">
<img v-else-if="section.fileType === 'pdf'" src="@/assets/img/exts/pdf.png" alt="">
<img v-else src="@/assets/img/exts/pic.png" alt="">
{{ section.name }}
</p>
</div>
</div>
</template>
</template>
<div v-else class="section">
<p class="sectionName" v-for="(item, i) in progressList" :key="i" :title="item.projectName">
{{ i + 1 }}.
{{ item.projectName }}
<i :class="['icon', item.whetherToStudyOrNot ? 'el-icon-success' : 'circle']"
@click.stop="studySection(item)"></i>
</p>
</div>
</div>
</div>
</div>
</div>
</el-card>
<div class="tabs">
<a class="item" v-for="(item, i) in tabs" :key="i" :class="{ active: item.id == active }"
@click="tabChange(item)">{{
item.name }}</a>
</div>
<div class="flex">
<div class="tab-content">
<template v-if="active === 1">
<div class="page">
<div class="des" v-html="briefIntroduction"></div>
</div>
</template>
<template v-if="active === 2">
<div class="page">
<template v-if="showNoteAdd || !notes.length">
<el-form class="form" ref="form" label-width="120px" center>
<el-form-item class="required" label="笔记标题">
<el-input placeholder="请输入笔记标题" v-model="noteForm.noteName" maxlength="30"
style="width: 400px"></el-input>
</el-form-item>
<el-form-item class="required" label="笔记内容">
<Editor api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda' v-model="noteForm.noteContent"
:init="editorConfig" />
</el-form-item>
</el-form>
<div class="text-right">
<el-button v-if="notes.length" @click="showNoteAdd = false">取消</el-button>
<el-button type="primary" @click="submitNote">保存</el-button>
</div>
</template>
<template v-else>
<div class="tool">
<ul class="filter">
<li>
<label>搜索:</label>
<el-input placeholder="请输入标题" v-model="noteKeyword" clearable></el-input>
</li>
</ul>
<div>
<el-button type="primary" @click="addNote">新增笔记</el-button>
</div>
</div>
<el-timeline class="timeline">
<el-timeline-item placement="top" v-for="(item, i) in notes" :key="i">
<p class="sign">{{ item.createTime }}</p>
<div class="ver">
{{ item.noteName }}
<span class="action">
<i class="el-icon-edit-outline" @click="editNote(item)"></i>
<i class="el-icon-delete" @click="delNote(item)"></i>
</span>
</div>
<div class="des" v-html="item.noteContent"></div>
</el-timeline-item>
</el-timeline>
</template>
</div>
</template>
<template v-if="active === 4">
<div class="page">
<quill ref="quill" :border="true" v-model="comment" :height="150" :toTop="false" />
<div class="m-t-10 text-right">
<el-button type="primary" size="mini" @click="submitComment(0)">提交</el-button>
</div>
<ul class="msg">
<li v-for="(item, i) in comments" :key="i" :id="'comment' + item.commentId">
<div class="li-wrap">
<img :src="item.createUserAvatars" alt="" class="avatar">
<div class="texts">
<h6>
<span class="name">{{ item.createUsername }}</span>
发表于 {{ item.createTime }}
</h6>
<div class="m-t-8" v-html="item.content"></div>
</div>
<div class="action">
<i class="icon el-icon-chat-dot-square" @click="showReplay(item)"></i>
<!-- 当前用户是管理员 || 该条评论是学生发的(没有createRoleName即是学生) || 当前用户的account==该条评论的创建人accountId -->
<i v-if="(item.currentRoleName && item.currentRoleName.includes('管理员')) || !item.createRoleName || item.currentAccountId == item.createAccountId"
class="icon el-icon-delete" @click="delComment(item)"></i>
<!-- <div class="like-wrap"
@click="like(item)">
<img v-if="item.isLike"
class="icon"
src="@/assets/img/like-up.png"
alt="">
<img v-else
class="icon"
src="@/assets/img/like.png"
alt="">
{{ item.likeCount || '' }}
</div> -->
</div>
</div>
<div class="reply" v-if="item.showReply">
<quill :border="true" v-model="item.replyContent" :toTop="false" :height="150" />
<div class="m-v-10 text-right">
<el-button type="primary" size="mini" @click="submitComment(item)">提交</el-button>
</div>
</div>
<ul class="msg children" v-if="item.showChildren">
<li v-for="(reply, i) in item.children" :key="i" :id="'comment' + reply.commentId">
<div class="li-wrap">
<img class="avatar" :src="reply.createUserAvatars" alt="">
<div class="texts">
<div class="name">{{ reply.createUsername }}</div>
<div class="flex m-v-8">
<template v-if="reply.level !== 2">
回复
<span class="reply-name">@{{ reply.replyUsername }}:</span>
</template>
<div v-html="reply.content"></div>
</div>
<div class="date">{{ reply.createTime }}</div>
</div>
<div class="action">
<i class="icon el-icon-chat-dot-square" @click="showReplay(reply)"></i>
<!-- 当前用户是管理员 || 该条评论是学生发的(没有createRoleName即是学生) || 当前用户的account==该条评论的创建人accountId -->
<i v-if="(reply.currentRoleName && reply.currentRoleName.includes('管理员')) || !reply.createRoleName || reply.currentAccountId == reply.createAccountId"
class="icon el-icon-delete" @click="delComment(reply)"></i>
<!-- <div class="like-wrap"
@click="like(item, reply)">
<img v-if="reply.isLike"
class="icon"
src="@/assets/img/like-up.png"
alt="">
<img v-else
class="icon"
src="@/assets/img/like.png"
alt="">
{{ reply.likeCount || '' }}
</div> -->
</div>
</div>
<div class="reply" v-if="reply.showReply">
<quill :border="true" v-model="reply.replyContent" :toTop="false" :height="150" />
<div class="p-b-10 m-t-10 text-right">
<el-button type="primary" size="mini" @click="submitComment(item, reply)">提交</el-button>
</div>
</div>
</li>
</ul>
<div v-if="item.children" class="toggle"><span @click="item.showChildren = !item.showChildren">{{
item.showChildren ?
'收起所有回复' : `查看所有${item.children.length}条回复` }} <i class="el-icon-arrow-down"></i></span></div>
</li>
</ul>
</div>
</template>
</div>
<div class="rank">
<h6 class="title">练习成绩排行</h6>
<el-select style="width: 100%" v-model="archProject" placeholder="请选择" @change="getMaximumScore">
<el-option v-for="(item, i) in progressList" :key="i" :label="item.projectName"
:value="item.uuid"></el-option>
</el-select>
<div v-if="maximumScores.length" class="arches">
<div v-for="(item, i) in maximumScores" :key="i" class="line">
<div>
<img :src="item.userAvatars" alt="" class="avatar">
<span class="name">{{ item.userName }}</span>
</div>
<span class="point">{{ item.highestScore }}分</span>
</div>
</div>
<p v-else class="none">暂无数据</p>
</div>
</div>
<el-dialog title="请选择项目" :visible.sync="projectVisible" width="828px" custom-class="project-dia"
:close-on-click-modal="false">
<ul class="projects" v-loading="loading">
<template v-if="isTheory">
<li v-for="(item, i) in papers" :key="i" :class="{ active: curPaper == item.paperId }"
@click="selectPaper(item)">
<img src="@/assets/img/project.png" alt="">
<span>{{ i + 1 }}. {{ item.paperName }}</span>
</li>
</template>
<template v-else>
<li v-for="(item, i) in projects" :key="i" :class="{ active: curProject == item.projectId }"
@click="selectProject(item)">
<img src="@/assets/img/project.png" alt="">
<span>{{ i + 1 }}. {{ item.projectName }}</span>
</li>
</template>
</ul>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="projectVisible = false">取 消</el-button>
<el-button size="small" type="primary" @click="toSub">确 定</el-button>
</span>
</el-dialog>
<!-- 购买弹框 -->
<el-dialog title="温馨提示" :visible.sync="buyVisible" width="420px" center :close-on-click-modal="false">
<div class="buy">
<p class="tips">该课程订阅期限已到期,若需要续费请扫码添加客服咨询</p>
<img src="@/assets/img/wechat-code.jpeg" alt="">
</div>
</el-dialog>
<pdfDia :key="pdfVisible" :visible.sync="pdfVisible" :src.sync="pdfSrc" />
</div>
</template>
<script>
import Util from "@/libs/util";
import Setting from "@/setting";
import { mapState } from "vuex";
import pdf from "vue-pdf";
import quill from "@/components/quill";
import pdfDia from '@/components/pdf'
import Editor from '@tinymce/tinymce-vue'
import editorConfig from '@/components/editor'
export default {
components: { pdf, pdfDia, quill, Editor },
data () {
return {
editorConfig,
mallId: '',
courseId: '',
curriculumName: '',
commentId: '', // 从右上角消息通知点进来用来定位评论的
notifyId: '',
chapter: this.$route.query.chapter,
section: this.$route.query.section,
fromAdmin: this.$route.query.admin, // 是否从产品中心or实验台进来
type: 1,
chapterList: [], // 章节列表
progressList: [],
coverUrl: "", // 课程封面
courseName: "", // 课程名称
briefIntroduction: "", // 课程简介
teachingObjectives: "", // 课程目标
assessmentList: "", // 考核列表
systemIds: '',
practicePracticeProject: 0,
practiceTheoreticalPaper: 0,
curLink: "", // 当前选中
playAuth: "",
player: null,
previewImg: "",
iframeSrc: "",
isWord: false,
isPPT: false,
isExcel: false,
showMask: false,
showMask1: false,
showMask2: false,
closePosi: {
top: "80px"
},
pdfVisible: false,
pdfSrc: "",
currentPage: 0, // pdf文件页码
pageCount: 0, // pdf文件总页数
fileType: "pdf", // 文件类型
videoSrc: '',
desShrink: false,
projectVisible: false,
isTheory: 0,
projects: [],
papers: [],
loading: false,
curPaper: '',
curProject: '',
overdue: 0, //是否过期
buyVisible: false,
active: 1,
tabs: [
{
id: 1,
name: '课程介绍'
},
{
id: 2,
name: '课程笔记'
},
// {
// id: 3,
// name: '全国排行榜'
// },
{
id: 4,
name: '教学互动'
}
],
schedule: 0,
plan: '',
noteKeyword: '',
searchTimer: null,
notes: [],
showNoteAdd: false,
noteContent: '',
noteForm: {
cid: +this.$route.query.courseId,
noteContent: '',
noteName: '',
},
comments: [],
comment: '',
deleteIdentity: false,
archProject: '',
curReplyId: '',
maximumScores: [],
third: '',
};
},
computed: {
...mapState("user", [
"userId", "studentId", "roleId", "userName"
])
},
watch: {
'$route': {
handler () {
this.mallId = +this.$route.query.mallId || ''
this.courseId = +this.$route.query.courseId
this.curriculumName = this.$route.query.curriculumName
this.commentId = this.$route.query.commentId // 从右上角消息通知点进来用来定位评论的
this.notifyId = this.$route.query.notifyId
this.init()
},
immediate: true
},
noteKeyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.getNote();
}, 500);
}
},
mounted () {
},
methods: {
back () {
const { query } = this.$route
this.fromAdmin ?
this.$router.back() :
(this.mallId || query.typeActive) ? this.$router.push(`/station?keyword=${query.keyword || ''}&active=${query.active || ''}&typeActive=${query.typeActive || 0}&page=${query.page || 1}`) : this.$router.back()
},
init () {
this.insertScript()
this.getData()
this.addRecord()
},
async getData () {
if (this.courseId) {
let { data } = await this.$post(`${this.api.curriculumDetail}?cid=${this.courseId}&mallId=${this.mallId}`);
this.courseName = data.curriculumName;
// this.coverUrl = data.coverUrl;
this.briefIntroduction = data.briefIntroduction;
this.teachingObjectives = data.teachingObjectives;
this.assessmentList = data.assessmentConfig;
this.systemIds = data.systemIds
this.practicePracticeProject = data.practicePracticeProject
this.practiceTheoreticalPaper = data.practiceTheoreticalPaper
this.queryProject()
}
this.getStatus()
},
// 记录最近使用
async addRecord () {
await this.$post(`${this.api.recordRecentUsage}?mallId=${this.mallId}&cid=${this.courseId}`)
},
// 查询是否过期
async getStatus () {
if (this.mallId) {
const { isRenew } = await this.$get(this.api.whetherToRenewTheFee, {
mallId: this.mallId
})
// 1正常显示资源,0显示续费,-1试用
this.overdue = isRenew
}
this.getChapter()
this.getProgress()
},
// 获取章节小节
async getChapter () {
if (this.courseId) {
const res = await this.$get(this.api.curriculumChapter + '/' + this.courseId)
this.chapterList = res.chapterList;
const chapter = this.chapter === undefined ? 0 : +this.chapter
const section = this.section === undefined ? 0 : +this.section
const clist = this.chapterList[chapter]
if (this.chapterList.length && clist.subsectionList && clist.subsectionList.length && !this.commentId) {
this.preview(clist.subsectionList[section], clist.name, 1);
}
}
},
// 获取学习进度
async getProgress () {
if (this.courseId) {
let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.courseId}&systemId=${this.systemIds}&mallId=${this.mallId}`);
res.list.forEach(e => {
e.uuid = e.projectId || e.paperId
})
this.progressList = res.list
if (res.list.length) this.archProject = res.list[0].uuid
this.maximumScores.length || this.getMaximumScore()
this.plan = res.plan
this.schedule = +(res.schedule.replace('%', ''))
}
},
// 获取最高分列表
async getMaximumScore () {
const item = this.progressList.find(e => e.uuid === this.archProject)
let { message } = await this.$post(`${this.api.maximumPracticeScoreList}?projectId=${item.projectId || ''}&paperId=${item.paperId || ''}&pageNum=1&pageSize=1000&mallId=${this.mallId}&cid=${this.courseId}`);
const list = message.records
list.forEach(e => {
if (!e.userAvatars) e.userAvatars = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
})
this.maximumScores = list
},
// 进度数字自定义
percentFormat (val) {
return this.plan
},
// 目录和进度切换
typeChange (id) {
this.getChapter()
this.type = id
},
// 获取课程笔记
getNote () {
this.$get(this.api.curriculumNoteList, {
cid: this.courseId,
search: this.noteKeyword
}).then(res => {
this.notes = res.curriculumNotes
}).catch(res => { })
},
// 新增笔记
addNote () {
this.noteForm = {
cid: this.courseId,
noteContent: '',
noteName: '',
}
this.showNoteAdd = true
},
// 保存笔记
submitNote () {
const form = this.noteForm
if (!form.noteName) return Util.errorMsg('请输入笔记标题')
if (!form.noteContent) return Util.errorMsg('请输入笔记内容')
this.$post(this.api[form.noteId ? 'updateNote' : 'addNote'], form).then(res => {
this.getNote()
Util.successMsg(form.noteId ? '修改成功' : '添加成功')
this.showNoteAdd = false
this.noteForm = {
cid: this.courseId,
noteContent: '',
noteName: '',
}
}).catch(res => { })
},
// 删除笔记
delNote (row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.deleteNotes}?noteId=${row.noteId}`).then(res => {
Util.successMsg("删除成功");
this.getNote();
}).catch(res => { })
}).catch(() => { })
},
// 编辑笔记
editNote (row) {
this.noteForm = JSON.parse(JSON.stringify(row))
this.showNoteAdd = true
},
// 教学互动列表
getComment () {
this.$get(this.api.commentTreeList, {
mallId: this.mallId,
}).then(res => {
this.deleteIdentity = res.deleteIdentity
const list = res.rootComments
this.handleComments(list)
this.comments = list
this.$nextTick(async () => {
if (this.curReplyId) {
const el = document.querySelector('#comment' + this.curReplyId)
el && el.scrollIntoView(false)
}
if (this.commentId) {
this.active = 4
const el = document.getElementById('comment' + this.commentId)
el && el.scrollIntoView(false)
this.commentId = ''
}
})
}).catch(res => { })
},
// 递归处理评论参数
handleComments (list, parent = {}) {
list.forEach(e => {
if (!e.createUserAvatars) e.createUserAvatars = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
e.showChildren = false
if (e.commentId == this.commentId) parent.showChildren = true
if (e.commentId == this.curReplyId) e.showChildren = true
e.showReply = false
e.replyContent = ''
if (e.children && e.children.length && parent.children) {
e.children.forEach(n => n.showReplyName = true)
parent.children.push(...e.children)
}
e.children && this.handleComments(e.children, parent.commentId ? parent : e)
})
},
// 回复
showReplay (row) {
row.showReply = !row.showReply
},
// 删除评论
delComment (row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.deleteAComment}?commentId=${row.commentId}`).then(res => {
Util.successMsg("删除成功");
this.getComment();
}).catch(res => { })
}).catch(() => { })
},
// 保存评论
submitComment (row, reply) {
const content = reply ? reply.replyContent : row ? row.replyContent : this.comment
if (!content) return Util.errorMsg('请输入内容!')
this.$post(this.api.addCommentStation, {
mallId: this.mallId,
content,
// pid: reply ? reply.commentId : row ? row.commentId : 0,
pid: row ? row.commentId : 0,
replyAccountId: reply ? reply.createAccountId : row.createAccountId || '',
status: row ? 2 : 1,
replyCommentId: reply ? reply.commentId : row ? row.commentId : ''
}).then(res => {
this.comment = ''
this.curReplyId = row ? row.commentId : ''
this.getComment()
}).catch(res => { })
},
// 评论点赞
like (row) {
this.$post(`${this.api[row.isLike ? 'unlike' : 'commentAndLike']}?commentId=${row.commentId}`).then(res => {
row.isLike = row.isLike ? 0 : 1
}).catch(res => { })
},
// 插入阿里云播放器脚本
insertScript () {
const linkTag = document.createElement("link");
linkTag.id = "aliplayerLink";
linkTag.rel = "stylesheet";
linkTag.href = "https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css";
document.body.appendChild(linkTag);
const scriptTag = document.createElement("script");
scriptTag.id = "aliplayerScript";
scriptTag.type = "text/javascript";
scriptTag.src = "https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js";
document.body.appendChild(scriptTag);
this.$once("hook:beforeDestroy", function () {
document.body.removeChild(document.querySelector("#aliplayerLink"));
document.body.removeChild(document.querySelector("#aliplayerScript"));
});
},
// 显示咨询弹框
showBuy () {
this.buyVisible = true
},
transferType (ext) {
if ("jpg,jpeg,png,gif,svg,psd".includes(ext)) return "图片";
if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(ext)) return "视频";
return ext;
},
// tab切换
tabChange ({ id }) {
this.active = id
id == 2 && this.getNote()
id == 4 && this.getComment()
},
// 勾选/取消勾选学习进度
studySection (item) {
item.whetherToStudyOrNot ?
this.$post(`${this.api.deleteLearningProgress}?id=${item.learningProgressId}`).then(res => {
this.getProgress()
}).catch(res => { }) :
this.$post(this.api.saveLearningProgress, {
cid: this.courseId,
projectId: item.projectId || '',
paperId: item.paperId || '',
}).then(res => {
this.getProgress()
}).catch(res => { })
},
preview (row, chapterName, showDia = 0) {
// 如果没过期,则正常预览,否则显示购买弹框
if (this.overdue === 1 || showDia) {
this.curLink = `${chapterName}${row.name}`; // 章节名称+小节名称,小节名称有重复的情况,如果只用小节名称判断,会有同时选中多个的情况
this.playAuth = ''
this.coverUrl = ''
this.pdfSrc = ''
this.iframeSrc = ''
this.videoSrc = ''
this.isPPT = false;
this.isWord = false;
this.isExcel = false;
if (this.transferType(row.fileType) == "视频") {
// 阿里云视频点播
if (row.fileId) {
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.playAuth;
// 如果已经产生了实例,则销毁重新创建,不然播放器会播放上一个视频
if (this.player) {
this.player.dispose()
this.player = null
}
this.$nextTick(() => {
if (this.player) {
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth);
} else {
this.player = new Aliplayer({
id: "player",
width: "100%",
autoplay: false,
vid: row.fileId,
playauth: this.playAuth,
encryptType: 1 //当播放私有加密流时需要设置。
});
}
});
}).catch(res => { });
} else {
this.videoSrc = row.fileUrl
}
} else if (this.transferType(row.fileType) == "图片") {
this.coverUrl = row.fileUrl;
} else if (row.fileType == "pdf") {
this.pdfSrc = row.fileUrl;
} else {
this.$get(`${this.api.curriculumGetSubsection}/${row.id}`).then(res => {
if (row.fileType == "pptx") this.isPPT = true
if (row.fileType == "doc" || row.fileType == "docx") this.isWord = true
if (row.fileType == "xls" || row.fileType == "xlsx") this.isExcel = true
if (this.isPPT) {
this.showMask = true;
} else {
this.showMask = false;
}
if (this.isWord) {
this.showMask1 = true;
} else {
this.showMask1 = false;
}
if (this.isExcel) {
this.showMask2 = true;
} else {
this.showMask2 = false;
}
this.iframeSrc = res.previewUrl;
}).catch(err => { });
}
} else {
this.showBuy()
}
},
closePlayer () {
this.playAuth = ''
this.player.pause();
},
closeIframe () {
this.iframeSrc = ''
this.showMask = false;
this.showMask1 = false;
},
closePdf () {
this.pdfSrc = ''
this.currentPage = 1;
},
changePdfPage (val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--;
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++;
}
},
loadPdfHandler (e) {
this.currentPage = 1;
},
// pdf全屏
fullScreen () {
this.pdfVisible = true
},
// 选择试卷
selectPaper (item) {
this.curPaper = item.paperId
},
// 选择项目
selectProject (item) {
this.curProject = item.projectId
},
// 展示选择项目弹框
showProjectDia () {
this.projectVisible = true
},
// 查询项目
async queryProject () {
if (this.mallId) {
try {
this.loading = true
const res = await this.$get(this.api.getProjectBySystemId, {
systemId: this.systemIds,
cId: this.courseId, // 课程id
mallId: this.mallId,
permissions: 0 // 0: 练习,1: 考核
})
this.projects = res.projects // 实训项目
this.papers = res.exercisePaperList // 理论试卷
} finally {
this.loading = false
}
}
},
// 进入实验
entryProject (projectId = '', paperId = '') {
this.$confirm(`是否要继续上次的${projectId ? '实验' : '理论试题'}`, '提示', {
confirmButtonText: '是',
cancelButtonText: '否',
type: 'success',
closeOnClickModal: false
}).then(() => {
this.curProject = projectId
this.curPaper = paperId
this.toSub()
}).catch(() => {
this.showProjectDia()
})
},
// 进入实验
async entry (isTheory) {
this.isTheory = isTheory
if (isTheory) {
// 理论试卷
const res = await this.$post(`${this.api.getRecentTestPaperPracticeByCid}?cid=${this.courseId}`)
if (res.recentCacheInfo) {
this.entryProject('', res.recentCacheInfo.paperId)
} else {
this.showProjectDia(1)
}
} else {
// 实训系统
// 查询上次做的项目(python跟沙盘接口不一样)
if (this.systemIds.split(',').includes('19')) { // 沙盘
this.$post(`${this.api.getSandTableLastCache}?cid=${this.courseId}`).then(res => {
// 返回了data则提示是否继续,否则,显示选择项目的弹框
if (res.getLastCache) {
this.entryProject(+res.getLastCache)
} else {
this.showProjectDia()
}
}).catch(res => {
this.showProjectDia()
})
} else { // python
// python只能存在一个打开的窗口
// const opened = +localStorage.getItem('opened')
// if (opened) {
// Util.errorMsg('Python系统限单页活跃,请切换至当前已有的活跃实验页面。', 5000)
// return false
// } else {
// localStorage.setItem('opened', 1)
// }
this.$get(this.api.getTheMostRecentlyRunProject, {
cid: this.courseId
}).then(({ data }) => {
// 返回了data则提示是否继续,否则,显示选择项目的弹框
if (data && data.length) {
this.entryProject(data[0].projectId)
} else {
this.showProjectDia()
}
}).catch(res => {
this.showProjectDia()
})
}
}
},
// 进入python系统
toPython (projectId) {
const id = this.systemIds
let token = Util.local.get(Setting.tokenKey);
Util.cookies.set('assessmentId', '', -1)
Util.cookies.set('startTime', '', -1)
Util.cookies.set('stopTime', '', -1)
projectId ? Util.cookies.set('projectId', projectId) : Util.cookies.set('projectId', '', -1)
Util.cookies.set('token', token)
Util.cookies.set('mallId', this.mallId)
Util.cookies.set('third', this.third)
Util.cookies.set('courseId', this.courseId)
Util.cookies.set('curriculumName', encodeURIComponent(this.curriculumName))
Util.cookies.set('systemId', id)
Util.cookies.set('fromManager', 1)
Util.cookies.set('isSubmit', '', -1)
Util.cookies.set('competitionId', '', -1)
Util.cookies.set('language', '', -1)
Util.cookies.set('className', '', -1)
Util.cookies.set('loaded', '', -1)
// 8个python子系统都跳这个地址,子系统会通过cookie里的systemId识别展示哪套系统
location.href = process.env.NODE_ENV === 'development' ?
`http://${location.hostname}:8085/#/` :
Setting.isPro ?
`https://${location.hostname}/pyTrials` :
`${location.origin}/pyTrials`
},
// 进入子系统
async toSub () {
// 理论试卷
if (this.isTheory) {
window.open(this.$router.resolve(`/theoryExam?paperId=${this.curPaper}&cid=${this.courseId}&mallId=${this.mallId}&curriculumName=${this.curriculumName}`).href)
} else {
// 实训
let curProject = this.projects.find(e => e.projectId == this.curProject)
if (!curProject && this.projects.length) {
curProject = this.projects[0]
this.curProject = curProject.projectId
}
const { systemId } = curProject
let token = Util.local.get(Setting.tokenKey);
this.third = curProject.type === 2 ? (curProject.systemId === 28 ? 'low' : 'ai') : ''
if (systemId == 11) {
// 银行系统
sessionStorage.removeItem('projectId')
sessionStorage.removeItem('submited')
location.href = `${Setting.bankPath}/#/index/list?curriculumName=${this.curriculumName}&token=${token}&cid=${this.courseId}&mallId=${this.mallId}&systemId=${this.systemIds}&projectId=${this.curProject}&assessmentId=&classId=&stopTime=&test=true&manager=1`
} else if (systemId == 12) {
// 众筹系统
window.open(`http://${Setting.zcPath}?systemId=${systemId}&courseId=${this.courseId}&projectId=${this.curProject}&token=${token}&userId=${this.userId}&classId=1&mallId=${this.mallId}${Setting.isTest ? '&beta=1' : ''}`);
} else if (systemId == 19) {
// 沙盘
location.href = `${Setting.sandPath}/#/?curriculumName=${this.curriculumName}&token=${token}&cid=${this.courseId}&mallId=${this.mallId}&systemId=${this.systemIds}&projectId=${this.curProject}&assessmentId=&classId=&stopTime=&manager=1&referrer=${encodeURIComponent(location.href)}`
} else {
// python系统
this.toPython(this.curProject)
}
}
}
}
};
</script>
<style lang="scss" scoped>
@import '../../../styles/page/station.scss';
$height: 700px;
.page {
border-radius: 0;
.intro {
font-size: 14px;
color: #333;
line-height: 24px;
}
/deep/.des {
div,
p,
span {
font-family: PingFangSC-Regular !important;
}
}
}
/deep/.source-card {
.el-card__body {
padding: 0;
}
}
.video_wid,
.cover {
position: relative;
width: 76%;
height: $height !important;
border: 0;
}
.cover {
flex: 1;
width: auto;
}
.cover {
img {
border-radius: 8px;
}
&.is-word {
overflow: hidden;
}
}
.fileIframe {
height: $height !important;
}
.video_wid,
.inner {
width: 100%;
height: 100% !important;
border: 0;
overflow: auto;
}
.cover.is-word {
.inner {
height: calc(100% + 38px) !important;
margin-top: -38px;
}
}
.video_wid:focus {
outline: none;
}
.catalog {
width: 296px;
padding: 16px;
margin-left: 12px;
background-color: #252528;
.entry {
width: 48%;
height: 40px;
font-size: 17px;
&:only-child {
width: 100%;
}
}
.types {
display: flex;
margin: 15px 0;
.item {
display: inline-flex;
justify-content: center;
align-items: center;
width: 120px;
height: 40px;
color: #fff;
background-color: #4e4e4e;
border-radius: 4px;
cursor: pointer;
&:first-child {
margin-right: 10px;
}
&:hover {
background-color: $main-color;
}
&.active {
background-color: $main-color;
}
}
.icon {
margin-right: 5px;
font-size: 18px;
}
}
.list {
height: calc(700px - 104px);
overflow-y: auto;
.title {
margin-bottom: 11px;
color: #fff;
font-size: 16px;
}
.pro-title {
margin-bottom: 5px;
color: #fff;
font-size: 12px;
}
/deep/.el-progress-bar {
width: 92%;
}
/deep/.el-progress__text {
color: #fff;
}
.desc-wrap {
position: relative;
.desc {
font-size: 12px;
color: rgba(0, 0, 0, 0.65);
line-height: 22px;
@include mul-ellipsis(2);
&.active {
display: block;
overflow: visible;
}
}
.arrow {
position: absolute;
bottom: 2px;
right: 0;
display: flex;
justify-content: space-between;
width: 46px;
background-color: #fff;
span {
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
}
img {
width: 16px;
cursor: pointer;
}
&.active {
span {
opacity: 0;
}
img {
transform: rotate(180deg);
}
}
}
}
.chapters {
margin-top: 16px;
max-height: calc(100% - 53px);
overflow: auto;
}
.chapter {
margin-bottom: 20px;
}
.chapterName {
color: #fff;
font-size: 14px;
}
.section {
padding: 5px 15px;
margin-top: 12px;
background-color: #121214;
}
.sectionName {
position: relative;
padding-right: 15px;
margin: 12px 0;
font-size: 12px;
color: #999;
cursor: pointer;
@include ellipsis;
img {
margin-right: 8px;
}
.icon {
position: absolute;
right: 0;
font-size: 14px;
color: #00c935;
}
.circle {
width: 14px;
height: 14px;
border-radius: 50%;
border: 1px solid #ccc;
}
&.active {
color: #fff;
}
}
}
}
.buy {
text-align: center;
.tips {
margin-bottom: 10px;
font-size: 14px;
}
img {
width: 85%;
}
}
.el-image-viewer__wrapper {
transform: translateY(-10px);
transition: transform 0.5s;
&.active {
transform: translateY(0);
}
}
.el-image-viewer__close {
z-index: 2000;
top: 15px;
right: 15px;
&.doc-close {
i {
color: #000 !important;
}
}
}
.list::-webkit-scrollbar {
width: 4px;
}
.list::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(0, 0, 0, 0.06);
}
.mask {
z-index: 9;
position: absolute;
background-color: rgb(57, 58, 61);
}
.word-mask {
z-index: 9;
position: absolute;
top: 0;
right: 0;
width: 100%;
background-color: rgb(243, 242, 241);
}
.word-mask1 {
z-index: 9;
position: absolute;
top: 0;
right: 0;
width: 100%;
background-color: #185abd;
}
.word-mask2 {
z-index: 9;
position: absolute;
background-color: transparent;
}
.excel-mask1 {
z-index: 9;
position: absolute;
top: 0;
left: 20%;
width: 60%;
background-color: #107c41;
}
/deep/.pdf-dia {
border-radius: 0 !important;
.el-dialog__header {
display: none;
}
.el-dialog__body {
padding: 0;
}
.el-dialog__headerbtn {
top: 10px;
.el-dialog__close {
color: #fff;
font-size: 16px;
}
}
}
.pdf {
position: relative;
margin-top: 0 !important;
.full {
position: absolute;
top: 7px;
right: 10px;
cursor: pointer;
}
.arrow {
padding: 10px 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
color: #fff;
background-color: #333;
.turn {
margin: 0 10px;
font-size: 18px;
cursor: pointer;
}
}
.pdf-wrap {
width: 80%;
margin: 0 auto;
}
}
.tabs {
margin-bottom: 10px;
}
.tab-content {
width: 80%;
}
.rank {
width: calc(20% - 12px);
padding: 20px;
margin-left: 12px;
background-color: #fff;
.title {
margin-bottom: 10px;
font-size: 15px;
font-weight: 400;
}
.arches {
max-height: 223px;
padding-right: 10px;
margin-top: 20px;
overflow: auto;
}
.line {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.avatar {
width: 35px;
height: 35px;
margin-right: 10px;
}
.point {
font-weight: 600;
color: $main-color;
}
.none {
margin-top: 10px;
text-align: center;
font-size: 12px;
color: #727272;
}
}
/deep/.project-dia {
.el-dialog__body {
padding: 28px 32px;
}
}
.projects {
display: flex;
flex-wrap: wrap;
max-height: 400px;
overflow: auto;
li {
display: inline-flex;
align-items: center;
width: 238px;
padding: 16px;
margin: 0 20px 20px 0;
background-color: #f6f8fa;
border-radius: 16px;
cursor: pointer;
&:hover {
span {
color: $main-color;
}
}
&:nth-child(3n) {
margin-right: 0;
}
&.active {
background-color: #f2f7ff;
span {
color: #3988ff;
}
}
}
span {
max-width: 140px;
margin-left: 14px;
font-size: 14px;
color: #333;
}
}
</style>