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.
 
 
 
 
 

1455 lines
45 KiB

<template>
<div class="wrap">
<breadcrumb ref="breadcrumb"
:data="'实验台/' + (curriculumName || courseName)"></breadcrumb>
<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: 0;width:280px;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"
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"
width="100%"
height="100%"
autoplay
controls>
<source :src="videoSrc"
type="video/mp4">
您的浏览器不支持 video 标签。
</video>
</div>
</div>
<div class="catalog">
<el-button v-if="!overdue"
class="renew"
type="primary"
size="small"
@click="showBuy">续费</el-button>
<a v-else
class="entry"
@click="entry">进入实验</a>
<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,index) in chapterList"
:key="index">
<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 === '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>
<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">
<div v-if="active === 1"
class="page">
<div class="des"
v-html="briefIntroduction"></div>
</div>
<div v-if="active === 2"
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>
<div v-if="active === 4"
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>
<!-- 当前用户是管理员 || 当前用户的account==该条评论的创建人accountId -->
<i v-if="(item.currentRoleName && item.currentRoleName.includes('管理员')) || item.currentAccountId == item.createAccountId"
class="icon el-icon-delete"
@click="delComment(item)"></i>
<!-- <div class="like-wrap"
@click="like($event, 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-t-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 class="des"
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>
<!-- 当前用户是管理员 || 当前用户的account==该条评论的创建人accountId -->
<i v-if="(reply.currentRoleName && reply.currentRoleName.includes('管理员')) || reply.currentAccountId == reply.createAccountId"
class="icon el-icon-delete"
@click="delComment(reply)"></i>
<!-- <div class="like-wrap"
@click="like($event, 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="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>
</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.projectId"></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="请选择项目"
v-loading="loading"
:visible.sync="projectVisible"
width="828px"
custom-class="project-dia"
:close-on-click-modal="false">
<ul class="projects">
<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>
</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>
</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 breadcrumb from '@/components/breadcrumb'
import pdfDia from '@/components/pdf'
import Editor from '@tinymce/tinymce-vue'
import editorConfig from '@/components/editor'
export default {
components: { pdf, breadcrumb, pdfDia, quill, Editor },
data () {
return {
mallId: '',
courseId: '',
curriculumName: '',
commentId: '', // 从右上角消息通知点进来用来定位评论的
notifyId: '',
editorConfig,
startTime: Date.now(), // 页面进来的时间
systemIds: '',
type: 1,
video: "http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4",
chapterList: [], // 章节列表
progressList: [],
coverUrl: "", // 课程封面
courseName: "", // 课程名称
briefIntroduction: "", // 课程简介
teachingObjectives: "", // 课程目标
assessmentList: "", // 考核列表
curLink: "", // 当前选中
active: 1,
tabs: [
{
id: 1,
name: '课程介绍'
},
{
id: 2,
name: '课程笔记'
},
// {
// id: 3,
// name: '全国排行榜'
// },
{
id: 4,
name: '教学互动'
}
],
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,
projects: [],
loading: false,
curProject: '',
overdue: 0, //是否过期
buyVisible: false,
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: []
};
},
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 () {
},
destroyed () {
// 记录播放时长
this.$post(this.api.playRecordSave, {
courseId: this.courseId,
courseType: 0,
playTime: Math.ceil((Date.now() - this.startTime) / 1000 / 60)
}).then(({ data }) => { }).catch(res => { })
},
methods: {
goBack () {
this.$router.push('/station')
},
init () {
this.insertScript();
this.getData();
this.addRecord()
},
async getData () {
let { data } = await this.$post(`${this.api.curriculumDetail}?cid=${this.courseId}&mallId=${this.mallId}`);
this.courseName = data.curriculumName;
// this.$refs.breadcrumb.update('实验台/' + data.curriculumName)
// this.coverUrl = data.coverUrl;
this.briefIntroduction = data.briefIntroduction;
this.teachingObjectives = data.teachingObjectives;
this.assessmentList = data.assessmentConfig;
this.systemIds = data.systemIds
this.queryProject()
this.getStatus()
},
// 记录最近使用
addRecord () {
this.$post(`${this.api.recordRecentUsage}?mallId=${this.mallId}`).then(res => { }).catch(res => { })
},
// 查询是否过期
getStatus () {
this.$get(this.api.whetherToRenewTheFee, {
mallId: this.mallId
}).then(({ isRenew }) => {
// 1正常显示资源,0显示续费
this.overdue = isRenew
this.getChapter()
this.getProgress()
}).catch(res => { })
},
// 获取章节小节
async getChapter () {
let res = await this.$get(`${this.api.curriculumChapter}/${this.courseId}`);
this.chapterList = res.chapterList;
if (this.chapterList.length && this.chapterList[0].subsectionList && this.chapterList[0].subsectionList.length && !this.commentId) {
this.preview(this.chapterList[0].subsectionList[0], this.chapterList[0].name, 1);
}
},
// 获取学习进度
async getProgress () {
let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.courseId}&systemId=${this.systemIds}&mallId=${this.mallId}`);
this.progressList = res.list
if (res.list.length) this.archProject = res.list[0].projectId
this.maximumScores.length || this.getMaximumScore()
this.plan = res.plan
this.schedule = +(res.schedule.replace('%', ''))
},
// 获取最高分列表
async getMaximumScore () {
let { message } = await this.$post(`${this.api.maximumPracticeScoreList}?projectId=${this.archProject}&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, i) => {
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.addComment, {
mallId: this.mallId,
content,
pid: reply ? reply.commentId : 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 (e, row, reply) {
this.$post(`${this.api[(reply ? reply.isLike : row.isLike) ? 'unlike' : 'commentAndLike']}?commentId=${reply ? reply.commentId : row.commentId}`).then(res => {
this.curReplyId = row.commentId
this.getComment()
}).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) {
const suf = ext.toLowerCase()
if ('jpg,jpeg,png,gif,svg,psd'.includes(suf)) return '图片'
if ('mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv'.includes(suf)) return '视频'
return suf
},
// 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,
}).then(res => {
this.getProgress()
}).catch(res => { })
},
preview (row, chapterName, showDia = 0) {
// 如果没过期,则正常预览,否则显示购买弹框
if (this.overdue || 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.data.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()
}
},
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
},
// 选择项目
selectProject (item) {
this.curProject = item.projectId
},
// 展示选择项目弹框
showProjectDia () {
console.log(123)
this.projectVisible = true
},
// 查询项目
queryProject () {
this.$get(this.api.getProjectBySystemId, {
systemId: this.systemIds,
cId: this.courseId, // 课程id
mallId: this.mallId,
permissions: 0 // 0: 练习,1: 考核
}).then(({ projects }) => {
this.projects = projects
}).catch(res => { })
},
// 进入实验
entryProject (projectId) {
this.$confirm('是否要继续上次的实验?', '提示', {
confirmButtonText: '是',
cancelButtonText: '否',
type: 'success',
closeOnClickModal: false
}).then(() => {
this.curProject = projectId
this.toSub()
}).catch(() => {
this.showProjectDia()
})
},
// 进入实验
entry () {
// 查询上次做的项目(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
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('courseId', this.courseId)
util.cookies.set('curriculumName', encodeURIComponent(this.curriculumName))
util.cookies.set('systemId', id)
util.cookies.set('mallId', this.mallId)
util.cookies.set('isSubmit', '', -1)
util.cookies.set('fromManager', '', -1)
util.cookies.set('competitionId', '', -1)
util.cookies.set('language', '', -1)
util.cookies.set('className', '', -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`
},
// 进入子系统
toSub () {
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);
if (systemId == 11) {
// 银行系统
location.href = `${Setting.systemPath}/#/index/list?curriculumName=${this.curriculumName}&token=${token}&cid=${this.courseId}&mallId=${this.mallId}&systemId=${this.systemIds}&projectId=${this.curProject}&assessmentId=&classId=&stopTime=&test=true`
} 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=&referrer=${encodeURIComponent(location.href)}`
} else {
// python系统
this.toPython(this.curProject)
}
},
}
};
</script>
<style lang="scss" scoped>
@import '../../../styles/page/station.scss';
$height: 700px;
.video_wid,
.cover {
position: relative;
width: 76%;
height: $height !important;
border: 0;
}
.page {
/deep/.des {
overflow: auto;
div,
p,
span {
font-family: PingFangSC-Regular !important;
}
}
}
.l-title {
font-size: 17px;
}
.cover {
flex: 1;
background-color: #252528;
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;
.renew {
width: 100%;
margin-bottom: 16px;
font-size: 17px;
}
.entry {
display: block;
width: 100%;
height: 34px;
margin-bottom: 16px;
font-size: 17px;
color: #fff;
text-align: center;
line-height: 34px;
background: url(../../../assets/img/entry.png) 0 0/100% 100% no-repeat;
cursor: pointer;
&:hover {
opacity: 0.9;
}
}
.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: #377be3;
}
&.active {
background-color: $main-color;
}
}
.icon {
margin-right: 5px;
font-size: 18px;
}
}
}
.list {
height: calc(700px - 82px);
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;
.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;
}
}
/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: #007eff;
}
}
&: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;
}
}
.tabs {
display: flex;
align-items: center;
margin: 10px 0;
.item {
padding: 0 10px;
margin-right: 16px;
font-size: 16px;
text-align: center;
color: #333;
line-height: 50px;
border-bottom: 3px solid transparent;
cursor: pointer;
&.active {
color: #007eff;
border-color: #007eff;
}
}
}
.tab-content {
width: calc(100% - 308px);
}
.rank {
width: 296px;
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: #007eff;
}
.none {
margin-top: 10px;
text-align: center;
font-size: 12px;
color: #727272;
}
}
@media (max-width: 1700px) {
.wrap {
padding: 12px 5% 20px;
}
}
</style>