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.

732 lines
22 KiB

4 years ago
<template>
<div>
<el-container class="scrollbar" v-if="pannelVisible">
4 years ago
<el-header>
<div class="flex between">
<div class="flex" style="width: 28%">
<p>实训项目</p>
<el-select
3 years ago
v-model="projectId"
4 years ago
placeholder="请选择"
class="select"
:disabled="projectPermissions != 0"
@change="selectProject"
style="flex: 1"
>
<el-option
3 years ago
v-for="item in projectList"
4 years ago
:key="item.projectId"
:label="item.projectName"
:value="item.projectId"
></el-option>
</el-select>
</div>
<div class="countDownBox">
<div style="margin-left: -40px;">
<div :autoStart="autoStart">
4 years ago
实训{{text}}时间
<span class="timeSpan">{{day}}</span>
<span class="timeSpan">{{hour}}</span>小时
<span class="timeSpan">{{minutes}}</span>
<span class="timeSpan">{{seconds}}</span>
</div>
</div>
</div>
<div class="countDownBox">
<div>
总得分
<span class="gradeSpan">{{grade}}</span>
</div>
</div>
<div>
<el-button
style="backgroundColor: #202020;color: #d0d0d0;font-size:14px;"
v-show="projectPermissions == 0"
@click="reload"
>重新开始</el-button>
<el-button style="margin-right:7px" @click="submit" :disabled="isSubmit">提交</el-button>
4 years ago
</div>
</div>
</el-header>
<el-container>
<el-aside width="30%">
<div class="aside-header">
<div class="header_h flex">
<i class="el-icon-s-order"></i>
<p>实验目标</p>
</div>
<div class="font_css">
<div class="experimentTarget">
<div class="break-all" v-html="experimentTarget"></div>
4 years ago
</div>
</div>
</div>
<div class="aside-footer">
<div class="header_h flex">
<i class="el-icon-s-management"></i>
<p>实验任务</p>
</div>
<div>
<el-row>
<el-col :span="24">
<el-card shadow="hover">
<el-table :data="taskList" :stripe="true" height="405">
4 years ago
<el-table-column type="index"></el-table-column>
<el-table-column prop="name" label="判分标准" align="center"></el-table-column>
4 years ago
<el-table-column prop="right" label="完成结果" align="center">
<template slot-scope="scope">
<i
v-if="scope.row.right=='0'"
class="el-icon-check"
style="color:green;font-size:20px"
></i>
<i
v-else-if="scope.row.right=='-1'"
class="el-icon-close"
style="color:red;font-size:20px"
></i>
</template>
</el-table-column>
<el-table-column prop="score1" label="得分" align="center"></el-table-column>
4 years ago
</el-table>
</el-card>
</el-col>
</el-row>
</div>
</div>
</el-aside>
<el-main>
3 years ago
<el-tabs v-model="pannelTab" type="card">
4 years ago
<el-tab-pane label="案例" name="first">
<div class="break-all" v-html="experimentDescription"></div>
4 years ago
</el-tab-pane>
<el-tab-pane label="实验要求" name="second">
<el-collapse v-model="curReq">
4 years ago
<el-collapse-item v-for="(loop, index) in points" :key="index">
<template slot="title">
<i class="el-icon-s-ticket"></i>
3 years ago
<div class="break-all" v-html="loop.experimentalRequirements"></div>
4 years ago
</template>
3 years ago
<div class="break-all" v-html="loop.expserimentalRequirements"></div>
4 years ago
</el-collapse-item>
</el-collapse>
</el-tab-pane>
3 years ago
<el-tab-pane label="实验提示" name="fifth" v-if="hintOpen">
<div class="break-all" v-html="experimentHint"></div>
4 years ago
</el-tab-pane>
</el-tabs>
</el-main>
</el-container>
</el-container>
<!-- </div> -->
<div
:style="pannelVisible ? {position: 'fixed', left: '85%',top:'50%'} : {position: 'fixed',top:'50%'}"
4 years ago
>
<div @click="togglePannel">
<img src="../assets/img/left.png" alt class="left-btn" v-if="pannelVisible" />
<img src="../assets/img/right.png" alt class="right-btn" v-if="!pannelVisible" />
4 years ago
</div>
</div>
</div>
</template>
<script>
import newmain from "../util/newMain";
import util from '@/util'
4 years ago
export default {
data() {
return {
classId: util.getCookie('classId'),
className: util.getCookie("className"),
3 years ago
courseId: util.getCookie("courseId"),
projectId: util.getCookie("projectId"),
assessmentId: util.getCookie("assessmentId"),
projectPermissions: 0, // 项目权限(0、练习 1、考核 2、竞赛)
isSubmit: false, // 是否提交的标识
entryTime: new Date(),
3 years ago
startTime: util.getCookie("startTime") ? new Date(util.getCookie("startTime")).getTime() : '',
endTime: util.getCookie("stopTime") ? new Date(util.getCookie("stopTime")).getTime() : '',
autoStart: true,
pannelVisible: true, // 实验面板显示标识
grade: '00', // 得分
text: '', // 倒计时前面的文字,练习:所用;考核:剩余。练习是计时,考核是倒计时
counterTimer: null, // 获取setInterval对象值
day: 0, // 天数
seconds: 0, // 秒数
minutes: 0, // 分钟数
hour: 0, // 小时数
3 years ago
createTime: '', // 开始时间
actEndTime: '', // 倒计时结束时间
projectList: [], // 项目列表
experimentTarget: "", //实验目标
experimentDescription: "", //案例描述
experimentHint: "", //实验提示
hintOpen: 1, // 是否显示实验提示
points: [], // 判分点列表
judgmentId: '', // 当前判分点id
curReq: [], // 当前实验要求
taskList: [], // 实验任务列表
pannelTab: "first", // 面板信息切换值
isSelected: false // 是否选择过项目的标识,选择了会置为true
4 years ago
};
},
mounted() {
3 years ago
this.projectPermissions = this.projectId ? 1 : 0 // 考核/练习
if(this.projectId){ // 考核(考核才会从外面带进来projectId,练习是默认显示第一个项目)
this.getProDetail()
}else{ // 练习
// 获取项目列表
this.getList().then(() => {
let cache = localStorage.getItem('codeCache') // 获取本地缓存
// 如果有缓存,再调接口取上次运行的代码
if (cache) {
3 years ago
cache = JSON.parse(cache)
this.getCache(cache.projectId, cache.judgmentId)
} else {
this.getCache()
3 years ago
}
}).catch(res => {})
4 years ago
}
},
methods: {
// 获取项目列表
getList(){
let data = {
systemId: 1,
cId: this.courseId, // 课程id
permissions: this.projectPermissions // 练习/考核
}
return new Promise((resolve, reject) => {
this.$get(`${this.api.queryTestProject}`,data).then(res => {
const list = res.projects
this.projectList = list
this.projectId = list ? list[0].projectId : 0 // 默认取第一个项目
this.getProDetail().then(() => {
resolve()
}).catch(res => {
reject()
3 years ago
})
}).catch(res => {
reject()
4 years ago
})
})
4 years ago
},
3 years ago
// 获取项目详情
getProDetail() {
const projectId = this.projectId
return new Promise((resolve, reject) => {
this.$get(this.api.QueryProject, {
projectId
}).then(res => {
const points = res.projectJudgmentVos
const project = res.projectManage
points.map(e => {
e.code = '' // 后端返回的字段没有code,要手动加上以存储运行的代码
e.codeId = '' // 代码通过接口传给后端运行后,接口会返回一个codeId,提交的时候需要传这个codeId
3 years ago
})
this.points = points
this.taskList = points // 实验任务
this.judgmentId = points[0].judgmentId // 默认取第一个判分点
3 years ago
this.experimentTarget = project.experimentTarget
this.experimentDescription = project.experimentDescription
this.experimentHint = project.experimentHint
// this.actEndTime = project[0].endTime
this.hintOpen = !res.projectManage.hintOpen // 0显示,1不显示
this.$emit('tell', projectId, this.points)
if (this.projectPermissions == 1) {
this.text = "剩余"
4 years ago
var interval = setInterval(() => {
// 获取当前时间,同时得到活动结束时间数组
let newTime = new Date().getTime();
// 对结束时间进行处理渲染到页面
let endTime = new Date(this.actEndTime).getTime();
let obj = null; // 如果活动未结束,对时间进行处理
if (endTime - newTime > 0) {
let time = (endTime - newTime) / 1000; // 获取天、时、分、秒
let day = parseInt(time / (60 * 60 * 24));
let hou = parseInt((time % (60 * 60 * 24)) / 3600);
let min = parseInt(((time % (60 * 60 * 24)) % 3600) / 60);
let sec = parseInt(((time % (60 * 60 * 24)) % 3600) % 60);
obj = {
day: this.timeFormat(day),
hou: this.timeFormat(hou),
min: this.timeFormat(min),
sec: this.timeFormat(sec)
};
} else {
// 活动已结束,全部设置为'00'
obj = {
day: "00",
hou: "00",
min: "00",
sec: "00"
};
clearInterval(interval);
}
this.day = obj.day;
this.hour = obj.hou;
this.minutes = obj.min;
this.seconds = obj.sec;
}, 1000);
} else {
4 years ago
this.text = "已用";
// 获取当前时间
this.createTime = new Date().getTime()
4 years ago
//自动开始
if (this.autoStart) {
this.startCount()
4 years ago
}
}
3 years ago
resolve()
}).catch(err => {
reject()
4 years ago
})
3 years ago
})
4 years ago
},
// 获取上次缓存记录
getCache(pId, jId) {
const projectId = pId ? pId : this.projectId
const judgmentId = jId ? jId : this.judgmentId
this.$post(this.api.getLastCache, {
bcId: judgmentId, // 如果传进来了判分点id,说明本地有缓存,则直接取本地缓存的判分点id,否则,取第一个项目的第一个判分点id
projectId, // 项目id,同上
cid: this.courseId // 课程id
}).then(res => {
const code = res.getLastCache
// 如果有缓存代码,再提示用户是否要继续上次的实验
if (code) {
this.$confirm('是否要继续上次的实验?', '提示', {
confirmButtonText: '是',
cancelButtonText: '否',
type: 'success'
}).then(() => {
localStorage.removeItem('codeCache') // 恢复代码后清除本地缓存
this.projectId = projectId
this.judgmentId = judgmentId
const item = this.points.find(e => e.judgmentId === judgmentId)
if (item) item.code = code
// debugger
this.$emit('tell', projectId, this.points)
this.$emit('recoveryCode', judgmentId + '')
}).catch(() => {
localStorage.removeItem('codeCache')
3 years ago
})
}
}).catch(res => {})
4 years ago
},
3 years ago
// 项目选择回调
4 years ago
selectProject(){
this.isSelected = true
this.getProDetail().then(() => {
this.getCache()
}).catch(res => {})
4 years ago
this.isSubmit = false
this.countVal = 0
this.grade = 0
// 切换实训项目-标签页回到第一个位置
this.$emit('recoveryCode')
newmain.$emit('isSubmit', this.isSubmit)
},
//重新开始
reload() {
this.reloadCount()
this.grade = '00'
localStorage.removeItem('codeCache')
this.isSubmit = false
newmain.$emit('isSubmit', this.isSubmit)
this.$emit('recoveryCode')
this.startCount()
// let taskList = this.taskList
// taskList.map(n => {
// delete n.score
// delete n.right
// })
// this.taskList = JSON.parse(JSON.stringify(taskList))
},
// 提交
submit() {
const pointList = this.$parent.workbench
// debugger
console.log(pointList)
if(!pointList.find(e => e.codeId)) return this.$message.error('请先完成实验')
this.$confirm("此操作将视为结束考试, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
center: true
}).then(() => {
const date = new Date()
const entryTime = this.entryTime
const timeSum = Math.ceil((date.getTime() - entryTime.getTime()) / 60000) // 计算实验用时(分钟),向上取整
const endTime = util.formatDate('yyyy-MM-dd hh:mm:ss', date) // 结束时间
const projectId = this.projectId
const projectName = this.projectList.find(e => e.projectId == projectId).projectName // 获取项目名称
this.actEndTime = date
this.reloadCount()
const attributesReqList = []
pointList.map(e => {
e.codeId && attributesReqList.push({
codeId: e.codeId,
bcId: e.judgmentId,
score: e.score,
isSubmit: 0
})
})
const data = {
classId: this.classId ? this.classId : '',
className: this.className ? this.className : '',
curriculumId: this.courseId,
startTime: util.formatDate('yyyy-MM-dd hh:mm:ss', entryTime),
endTime,
submitTime: endTime,
timeSum,
projectId,
projectName,
assessmentId: this.assessmentId ? this.assessmentId : '',
totalScore: 100,
systemId: 1,
purpose: this.experimentTarget,
attributesReqList
}
this.$post(this.api.submit, data).then(res => {
localStorage.removeItem('codeCache')
this.isSubmit = true
newmain.$emit("isSubmit", this.isSubmit);
let list = res.message
let result = []
let taskList = this.taskList
result.map(n => {
if(taskList.find(e => e.judgmentPointsId == n.judgmentPointsId).isError){
n.score = 0
n.right = -1
}
})
this.taskList = result
//计算总分
var s = 0;
this.taskList.forEach(element => {
// this.test = element.score;
// s += this.test;
this.grade = s;
});
})
.catch(err => {})
}).catch(() => {
this.$message({
type: "info",
message: "已取消提交"
})
})
},
// 实验面板显示隐藏
togglePannel() {
this.pannelVisible = !this.pannelVisible
},
// 倒计时
timeFormat(param) {
return param < 10 ? '0' + param : param
},
// 清除时间
reloadCount() {
clearInterval(this.counterTimer)
this.countVal = ''
this.day = '00'
this.seconds = '00'
this.minutes = '00'
this.hour = '00'
4 years ago
},
counterFn(counterTime) {
let leave1 = counterTime % (24 * 3600) //计算天数后剩余的毫秒数
let leave2 = leave1 % 3600 //计算小时数后剩余的毫秒数
let leave3 = leave2 % 60 //计算分钟数后剩余的毫秒数
4 years ago
let day = Math.floor(counterTime / (24 * 3600 * 1)); //计算相差天数
let hour = Math.floor(leave1 / (3600 * 1)); //计算相差小时
let minutes = Math.floor(leave2 / (60 * 1)); //计算相差分钟
let seconds = Math.round(leave3 / 1); //计算相差秒
day = day >= 10 ? day : "0" + day;
hour = hour >= 10 ? hour : "0" + hour;
minutes = minutes >= 10 ? minutes : "0" + minutes;
seconds = seconds >= 10 ? seconds : "0" + seconds;
this.day = day;
this.hour = hour;
this.minutes = minutes;
this.seconds = seconds;
},
3 years ago
// 倒计时
startCount() {
clearInterval(this.counterTimer)
this.countVal = this.countVal ? this.countVal : 0
this.counterTimer = setInterval(() => {
this.counterFn(this.countVal++)
}, 1000)
4 years ago
}
}
};
</script>
<style lang="scss" scoped>
.break-all{
word-break: break-all;
}
.left-btn {
4 years ago
height: 150px;
width: 35px;
cursor: pointer;
display: block !important;
}
.right-btn {
4 years ago
height: 150px;
width: 35px;
cursor: pointer;
display: block !important;
}
//el-main
.el-main {
width: 60%;
background-color: #fff;
color: #333;
padding: 0;
font-size: 16px;
margin: 0px 20px 10px 10px;
white-space: pre-wrap;
}
::v-deep .el-collapse-item__wrap {
border-bottom: none;
}
::v-deep .el-collapse-item__header {
border-bottom: none;
}
::v-deep .el-tabs__content {
margin: 0 20px;
}
::v-deep .el-icon-s-ticket:before {
font-size: 16px;
padding: 5px;
color: #fdca17;
}
::v-deep .el-collapse-item__arrow {
margin: 0 5px 0 0;
}
::v-deep .el-icon-arrow-right:before {
// content: "\e78f";
font-size: 12px;
padding: 1px;
margin-left: 10px;
background-color: #fdca17;
border-radius: 50%;
color: #ffffff;
}
::v-deep .el-tabs__item {
font-size: 16px;
}
::v-deep .el-tabs--card > .el-tabs__header .el-tabs__nav {
border: none;
}
::v-deep .el-tabs--card > .el-tabs__header .el-tabs__item {
border-left: none;
}
::v-deep .el-tabs--card > .el-tabs__header {
border-bottom: none;
}
::v-deep .el-collapse {
border-bottom: none;
border-top: none;
height: 500px;
overflow: hidden;
overflow-y: auto;
}
::v-deep .el-tabs__item.is-active {
color: #333;
background-color: #fdca17;
}
::v-deep .el-tabs__header {
padding: 5px 20px;
}
//el-aside
.el-aside {
color: #333;
}
.el-aside ::v-deep [class*=" el-icon-"],
[class^="el-icon-"] {
line-height: 40px;
font-size: 16px;
}
.aside-header {
margin: 0px 10px 10px 10px;
background-color: #fff;
}
.aside-footer {
margin: 0px 10px 10px 10px;
background-color: #fff;
}
.header_h {
height: 40px;
background-color: #fdca17;
justify-content: center;
}
.header_h p {
line-height: 40px;
font-size: 16px;
padding-left: 10px;
}
//表格
::v-deep .el-card__body {
padding: 0;
}
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
background: #fff9e6;
}
::v-deep .el-table td,
.el-table th.is-leaf {
border-bottom: 0;
}
::v-deep .el-table th > .cell {
font-weight: 100;
}
::v-deep .el-table thead {
color: #ffffff;
font-size: 10px;
}
::v-deep .el-table th,
.el-table tr {
background-color: #202020;
}
::v-deep .el-table {
font-size: 12px;
color: #202020;
}
//.el-header
.el-header {
color: #333;
padding: 0 12px;
}
.between {
justify-content: space-between;
}
//字体样式
.font_css {
margin: 0 10px;
text-indent: 2em;
font-size: 14px;
padding: 10px 0;
}
//改变placeholder的样式
.select ::v-deep input::-webkit-input-placeholder {
color: #333;
}
.select ::v-deep input::-moz-input-placeholder {
color: #333;
}
.select ::v-deep input::-ms-input-placeholder {
color: #333;
}
//下拉框的icon
.select ::v-deep .el-input__icon {
line-height: 60px;
}
//下拉框
.select ::v-deep .el-select__caret:before {
content: "\e78f";
font-size: 16px;
padding: 3px;
background-color: #fdca17;
border-radius: 50%;
color: #ffffff;
}
.select ::v-deep .el-input--suffix .el-input__inner {
color: #333;
font-size: 14px;
border-radius: 30px;
border: none;
background-color: #fff;
margin-left: 15px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// white-space: pre-line;
}
.select ::v-deep .el-input {
padding: 10px 0;
}
//实训时间、得分
.countDownBox {
font-size: 16px;
margin: 0 10px;
padding: 20px 0;
}
.timeSpan {
color: #333333;
padding: 5px 15px;
font-size: 14px;
background: #ffffff;
border-radius: 18px;
margin: 0 5px;
text-align: center;
}
.gradeSpan {
color: #ffffff;
padding: 10px;
font-size: 14px;
background: #000000;
border-radius: 6px;
text-align: center;
}
//重新开始、提交
.el-header ::v-deep .el-button {
background-color: #fdca17;
color: #202020;
border: none;
margin: 5px 0px 5px 5px;
font-size: 16px;
}
.el-header ::v-deep .el-button:hover,
.el-button:focus,
.el-button:active {
background-color: #fdca17;
color: #202020;
}
//公共类
::v-deep .el-container {
height: 80%;
}
.el-container.is-vertical {
background-color: #f5f5f5;
width: 85%;
height: 70%;
position: fixed;
top: 200px;
bottom: 20px;
left: 0;
}
.flex {
display: flex;
align-items: center;
}
// 滚动条的宽度
.scrollbar ::-webkit-scrollbar {
width: 2px; // 横向滚动条
height: 6px; // 纵向滚动条 必写
}
// 滚动条的滑块
.scrollbar ::-webkit-scrollbar-thumb {
background-color: #fdca17;
border-radius: 3px;
box-shadow: inset 0 0 5px #dddddd;
}
.scrollbar ::-webkit-scrollbar-track {
/*滚动条里面轨道*/
box-shadow: inset 0 0 5px #dddddd;
border-radius: 0;
background: #dddddd;
}
</style>