|
|
|
<template>
|
|
|
|
<div v-show="loaded">
|
|
|
|
<div class="header" :class="{hh: $config.isHh}">
|
|
|
|
<img v-if="$config.isHh" src="@/assets/images/logo-hh.png" alt="" class="logo">
|
|
|
|
<p v-else>{{curriculumName}}</p>
|
|
|
|
<el-button class="back btn" type="primary" @click="back">退出实验</el-button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="language">
|
|
|
|
<p v-if="$config.isHh" style="font-size: 18px">{{$config.title}}</p>
|
|
|
|
<p>编程语言</p>
|
|
|
|
<el-input placeholder="请输入内容" v-model="language" :disabled="true"></el-input>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="tab">
|
|
|
|
<el-tabs v-model="curTab" type="card" @tab-click="judChange">
|
|
|
|
<el-tab-pane
|
|
|
|
v-for="(item, i) in workbench"
|
|
|
|
:key="item.judgmentId"
|
|
|
|
:label="item.name"
|
|
|
|
:value="item.judgmentId"
|
|
|
|
>
|
|
|
|
<codemirror
|
|
|
|
:ref="'code' + i"
|
|
|
|
:key="codeKey"
|
|
|
|
:projectId.sync="projectId"
|
|
|
|
:systemId.sync="systemId"
|
|
|
|
:code.sync="item.code"
|
|
|
|
:judgmentId="item.judgmentId"
|
|
|
|
:codeId.sync="item.codeId"
|
|
|
|
:answer.sync="item.answer"
|
|
|
|
:retResult.sync="item.retResult"
|
|
|
|
:modelIsShow.sync="modelIsShow"
|
|
|
|
@cache="leavePage"
|
|
|
|
></codemirror>
|
|
|
|
</el-tab-pane>
|
|
|
|
</el-tabs>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="menu">
|
|
|
|
<testPanel
|
|
|
|
@tell="setPoints"
|
|
|
|
@recoveryCode="recoveryCode"
|
|
|
|
ref="mainindex"
|
|
|
|
:workbench.sync="workbench"
|
|
|
|
></testPanel>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import testPanel from "../components/TestPanel";
|
|
|
|
import codemirror from "../components/codemirror";
|
|
|
|
import util from '@/util'
|
|
|
|
import { Loading } from 'element-ui'
|
|
|
|
export default {
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
loaded: false, // 页面是否加载完的标识,页面默认隐藏,一进来先显示加载条,接口加载完后再显示页面,不然一开始会一闪而过没有样式的页面
|
|
|
|
loadIns: null, // loading实例
|
|
|
|
courseId: util.getCookie('courseId'), // 课程id
|
|
|
|
curriculumName: util.getCookie('curriculumName') ? unescape(util.getCookie('curriculumName')) : 'python', // 课程名称
|
|
|
|
assessmentId: util.getCookie('assessmentId'), // 考核id
|
|
|
|
projectId: '',
|
|
|
|
systemId: '',
|
|
|
|
modelIsShow: false, // 导入模型按钮是否显示
|
|
|
|
projectPermissions: 0, // 项目权限(0、练习 1、考核 2、竞赛)
|
|
|
|
language: 'Python', // 编程语言
|
|
|
|
curTab: '', // 选中后绑定的对象
|
|
|
|
workbench: [], // 判分点切换列表
|
|
|
|
codeKey: 1 // 编辑器索引
|
|
|
|
};
|
|
|
|
},
|
|
|
|
components: {
|
|
|
|
codemirror,
|
|
|
|
testPanel
|
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
this.loadIns = Loading.service({
|
|
|
|
background: 'rgba(255, 255, 255, .1)'
|
|
|
|
})
|
|
|
|
this.autoLogout()
|
|
|
|
// 绑定页面离开监听
|
|
|
|
window.onbeforeunload = () => {
|
|
|
|
this.leavePage()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
// 页面离开的时候缓存未提交的代码(只有未提交状态下才会调用该接口)
|
|
|
|
leavePage(){
|
|
|
|
const list = this.workbench
|
|
|
|
if(!this.$refs.mainindex.isSubmit && list.length && list.some(e => e.code)){
|
|
|
|
const cache = {
|
|
|
|
projectId: Number(this.projectId),
|
|
|
|
judgmentIdList: this.workbench.map(e => e.judgmentId)
|
|
|
|
}
|
|
|
|
localStorage.setItem('codeCache', JSON.stringify(cache)) // 在本地缓存里保存项目id和判分点id,下次进来通过这两个id去查找缓存代码。之所以不在前端缓存代码是预防更换了浏览器或电脑后依然可以找回缓存代码,只不过更换了客户端后本地缓存就消失了,这种情况就做一个向下处理,就切换项目的时候去恢复代码
|
|
|
|
list.map(e => {
|
|
|
|
if (e.code) {
|
|
|
|
let data = {
|
|
|
|
assessmentId: this.assessmentId,
|
|
|
|
code: e.code,
|
|
|
|
bcId: e.judgmentId,
|
|
|
|
cid: this.courseId,
|
|
|
|
projectId: this.projectId
|
|
|
|
}
|
|
|
|
this.$post(this.api.saveCache,data).then(res => {}).catch(e => {})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// 获取导入模型按钮展示状态
|
|
|
|
getModelStatus(systemId) {
|
|
|
|
this.$post(`${this.api.checkIsShowBySystemId}?systemId=${systemId}`).then(res => {
|
|
|
|
this.modelIsShow = !res.isShow // 0为展示 1为不展示
|
|
|
|
}).catch(res => {})
|
|
|
|
},
|
|
|
|
// 长时间未点击页面,就自动退出页面
|
|
|
|
autoLogout(){
|
|
|
|
let lastTime = new Date().getTime()
|
|
|
|
let logout = false
|
|
|
|
// 页面点击后赋值当前时间
|
|
|
|
document.onmousedown = () => {
|
|
|
|
lastTime = new Date().getTime()
|
|
|
|
}
|
|
|
|
// 每秒钟判断一次,如果当前时间距离上次点击页面的试卷超过了设置的时间,就退出登录
|
|
|
|
setInterval(() => {
|
|
|
|
if((new Date().getTime() - lastTime) > this.$config.autoLogoutTime){
|
|
|
|
logout || this.$message.error('用户登录过期,请重新登录')
|
|
|
|
logout = true
|
|
|
|
setTimeout(this.back,1500)
|
|
|
|
}
|
|
|
|
},1000)
|
|
|
|
},
|
|
|
|
// 判分规则切换
|
|
|
|
judChange() {
|
|
|
|
this.$nextTick(_ => {
|
|
|
|
const code = this.$refs['code' + this.curTab][0].$refs.codemirror.codemirror // 获取codemirror实例
|
|
|
|
code.focus() // 编辑器聚焦
|
|
|
|
code.setCursor(code.lineCount(), 0) // 焦点移动至最后面
|
|
|
|
})
|
|
|
|
},
|
|
|
|
// 重置编辑器
|
|
|
|
recoveryCode(curTab = '0'){
|
|
|
|
this.curTab = curTab
|
|
|
|
this.codeKey++
|
|
|
|
},
|
|
|
|
// 退出实验
|
|
|
|
back() {
|
|
|
|
history.back()
|
|
|
|
},
|
|
|
|
// 赋值项目id、项目列表
|
|
|
|
setPoints(projectId, systemId, workbench) {
|
|
|
|
this.projectId = projectId
|
|
|
|
this.systemId = systemId
|
|
|
|
this.workbench = workbench
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
[v-cloak] {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
.header {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
height: 58px;
|
|
|
|
line-height: 58px;
|
|
|
|
background-color: #f8f8f8;
|
|
|
|
&.hh{
|
|
|
|
padding: 10px 0;
|
|
|
|
line-height: normal;
|
|
|
|
}
|
|
|
|
p {
|
|
|
|
margin-left: 18px;
|
|
|
|
font-size: 20px;
|
|
|
|
color: rgba(51, 51, 51, 1);
|
|
|
|
}
|
|
|
|
.logo{
|
|
|
|
width: 200px;
|
|
|
|
margin-left: 10px;
|
|
|
|
}
|
|
|
|
.back {
|
|
|
|
padding: 23px 50px;
|
|
|
|
border: none;
|
|
|
|
border-radius: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/deep/.language {
|
|
|
|
display: flex;
|
|
|
|
height: 60px;
|
|
|
|
line-height: 60px;
|
|
|
|
p {
|
|
|
|
font-size: 16px;
|
|
|
|
margin-left: 15px;
|
|
|
|
margin-right: 15px;
|
|
|
|
}
|
|
|
|
.el-input {
|
|
|
|
width: 10%;
|
|
|
|
}
|
|
|
|
.el-input.is-disabled .el-input__inner {
|
|
|
|
border-radius: 30px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.menu {
|
|
|
|
position: relative;
|
|
|
|
z-index: 1000;
|
|
|
|
}
|
|
|
|
::v-deep .el-dialog--center {
|
|
|
|
width: 400px;
|
|
|
|
}
|
|
|
|
::v-deep .el-dialog__headerbtn .el-icon-close:before {
|
|
|
|
padding: 3px;
|
|
|
|
border-radius: 50%;
|
|
|
|
}
|
|
|
|
/deep/.tab {
|
|
|
|
height: 50px;
|
|
|
|
line-height: 50px;
|
|
|
|
.el-tabs__header {
|
|
|
|
margin-bottom: 0;
|
|
|
|
}
|
|
|
|
.el-tabs__item.is-active {
|
|
|
|
color: #333;
|
|
|
|
}
|
|
|
|
.el-icon-circle-plus-outline:before {
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
.el-tabs--card > .el-tabs__header {
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
.el-tabs--card > .el-tabs__header .el-tabs__nav {
|
|
|
|
border: none;
|
|
|
|
}
|
|
|
|
.el-tabs--card > .el-tabs__header .el-tabs__item {
|
|
|
|
border-left: none;
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|