|
|
|
@ -2,24 +2,22 @@ |
|
|
|
|
<div style="display:flex;"> |
|
|
|
|
<div class="left"> |
|
|
|
|
<codemirror |
|
|
|
|
v-model="exampleData" |
|
|
|
|
:value="codeid" |
|
|
|
|
v-model="codeVal" |
|
|
|
|
:options="cmOption" |
|
|
|
|
class="code-mirror" |
|
|
|
|
@ready="onCmReady3" |
|
|
|
|
@ready="ready" |
|
|
|
|
ref="myCmGenerate" |
|
|
|
|
></codemirror> |
|
|
|
|
<div v-if="isSubmit" class="code-mask"></div> |
|
|
|
|
<el-button |
|
|
|
|
type="warning" |
|
|
|
|
@click="AnswerTips()" |
|
|
|
|
:disabled="isAnswerTips" |
|
|
|
|
@click="runCode" |
|
|
|
|
:disabled="runEnable" |
|
|
|
|
style="width:100px;position:absolute;z-index:99;background:#FDCA17;color:black;right: 50px;bottom:15px;" |
|
|
|
|
>运行</el-button> |
|
|
|
|
</div> |
|
|
|
|
<div class="code-right answer"> |
|
|
|
|
<p class="text-wrapper" v-html="modifys"></p> |
|
|
|
|
<!-- <p class="text-wrapper">{{modifys}}</p> --> |
|
|
|
|
<p class="text-wrapper" v-html="runResult"></p> |
|
|
|
|
<div class="pic-wrap" v-if="picSrc"> |
|
|
|
|
<div style="margin-bottom: 5px;text-align: center"> |
|
|
|
|
<img class="pic" :src="picSrc" alt=""> |
|
|
|
@ -27,17 +25,14 @@ |
|
|
|
|
<el-button class="download-btn" type="primary" size="mini" @click="$refs.picLink.click()">下载图片</el-button> |
|
|
|
|
<a ref="picLink" style="display: none;" download="运行结果.png" :href="picSrc">下载图片</a> |
|
|
|
|
</div> |
|
|
|
|
<div class="code_yes" v-show="this.isError == 0"> |
|
|
|
|
<div class="code_yes" v-show="this.isError"> |
|
|
|
|
<img src="../assets/img/yes.png" alt />运行成功 |
|
|
|
|
</div> |
|
|
|
|
<div class="code_error" v-show="this.isError == 1"> |
|
|
|
|
<div class="code_error" v-show="this.isError === 0"> |
|
|
|
|
<img src="../assets/img/error.png" alt /> |
|
|
|
|
第{{num}}行出现错误 |
|
|
|
|
<!-- <el-button |
|
|
|
|
style="color:rgba(255,49,49,1);background:rgba(255,255,255,1);margin-left:80px" |
|
|
|
|
>求助</el-button>--> |
|
|
|
|
<el-button class="tips-btn" @click="getQueryAnswer()" v-show="ShowAssessmentId">提示</el-button> |
|
|
|
|
<el-dialog title="答案提示" center :visible.sync="error"> |
|
|
|
|
第{{errLine}}行出现错误 |
|
|
|
|
<el-button class="tips-btn" @click="getTips" v-show="showTips">提示</el-button> |
|
|
|
|
<el-dialog title="答案提示" center :visible.sync="tipsVisible"> |
|
|
|
|
<el-tabs> |
|
|
|
|
<el-tab-pane label="参考答案"> |
|
|
|
|
<div class="answer-wrap" v-html="answer"></div> |
|
|
|
@ -90,37 +85,27 @@ import "codemirror/addon/fold/xml-fold.js"; |
|
|
|
|
// 编辑的主题文件 |
|
|
|
|
import "codemirror/theme/monokai.css"; |
|
|
|
|
import "codemirror/theme/base16-light.css"; |
|
|
|
|
import * as $ from "jquery"; |
|
|
|
|
import { Loading } from 'element-ui'; |
|
|
|
|
import axios from 'axios'; |
|
|
|
|
import util from '@/util' |
|
|
|
|
const CANCEL_TOKEN = axios.CancelToken |
|
|
|
|
const CANCEL_TOKEN = axios.CancelToken // 用于input中中断请求 |
|
|
|
|
export default { |
|
|
|
|
props: ["workbench1", "code", "codeid", "projectId"], |
|
|
|
|
props: ["workbench1", "code", "projectId"], |
|
|
|
|
data() { |
|
|
|
|
return { |
|
|
|
|
courseId: util.getCookie("courseId"), |
|
|
|
|
datas: [], |
|
|
|
|
ShowAssessmentId: false, |
|
|
|
|
answer: "", |
|
|
|
|
exampleData: this.code, |
|
|
|
|
codeId: this.codeid, |
|
|
|
|
codes: [], |
|
|
|
|
submit: "", |
|
|
|
|
modifys: "", //运行后返回的 |
|
|
|
|
isError: 2, |
|
|
|
|
timer: "", |
|
|
|
|
after: "", |
|
|
|
|
num: "", |
|
|
|
|
userId: '', |
|
|
|
|
studentId: "", |
|
|
|
|
isSubmit: "", //提交按钮 |
|
|
|
|
isAnswerTips: false, |
|
|
|
|
error: false, |
|
|
|
|
picVisible: false, |
|
|
|
|
picSrc: '', |
|
|
|
|
loadIns: null, |
|
|
|
|
submiting: false, |
|
|
|
|
assessmentId: util.getCookie("assessmentId"), // 考核id |
|
|
|
|
courseId: util.getCookie("courseId"), // 课程id |
|
|
|
|
showTips: false, // 显示隐藏提示按钮 |
|
|
|
|
answer: '', // 正确答案 |
|
|
|
|
codeVal: this.code, |
|
|
|
|
runResult: '', // 运行结果 |
|
|
|
|
isError: false, // 运行正确与否 |
|
|
|
|
errLine: '', // 错误代码的位置 |
|
|
|
|
isSubmit: false, // 是否提交了 |
|
|
|
|
runEnable: false, // 是否禁用运行按钮 |
|
|
|
|
tipsVisible: false, // 答案提示弹框显示标识 |
|
|
|
|
picSrc: '', // 代码运行出来的图片url |
|
|
|
|
loadIns: null, // loading实例 |
|
|
|
|
cmOption: { |
|
|
|
|
scrollbarStyle: "native", |
|
|
|
|
tabSize: 2, // tab |
|
|
|
@ -149,41 +134,34 @@ export default { |
|
|
|
|
theme: "monokai", // 主题 |
|
|
|
|
extraKeys: { Ctrl: "autocomplete" } // 可以用于为编辑器指定额外的键绑定,以及keyMap定义的键绑定 |
|
|
|
|
}, |
|
|
|
|
inputTextReg: /^((?!#).*?(,|\(|\[|\{|\s)+)?input(?!\w)\(['|"]([\s\S]+?)['|"]\)/m,// 匹配input() |
|
|
|
|
requestList: [], |
|
|
|
|
sourceCode: '', |
|
|
|
|
requestTimer: null, |
|
|
|
|
assessmentId: util.getCookie("assessmentId"), |
|
|
|
|
inputTextReg: /^((?!#).*?(,|\(|\[|\{|\s)+)?input(?!\w)\(['|"]([\s\S]+?)['|"]\)/m, // 匹配input() |
|
|
|
|
requestList: [], // 有input的情况下,保存每个axios的对象,用于中断请求 |
|
|
|
|
sourceCode: '', // 把input替换成exit函数后的代码 |
|
|
|
|
requestTimer: null // 用于中断请求的定时器 |
|
|
|
|
}; |
|
|
|
|
}, |
|
|
|
|
components: { |
|
|
|
|
codemirror |
|
|
|
|
}, |
|
|
|
|
watch: { |
|
|
|
|
list() { |
|
|
|
|
this.timer(); |
|
|
|
|
}, |
|
|
|
|
exampleData(val) { |
|
|
|
|
this.$emit("update:code", val); |
|
|
|
|
}, |
|
|
|
|
codeId(val) { |
|
|
|
|
this.$emit("update:codeid", val); |
|
|
|
|
codeVal(val) { |
|
|
|
|
this.$emit("update:code", val) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
mounted() { |
|
|
|
|
if (!this.assessmentId) { |
|
|
|
|
this.ShowAssessmentId = true; |
|
|
|
|
} |
|
|
|
|
if (!this.assessmentId) this.showTips = true |
|
|
|
|
//兄弟组件传值 |
|
|
|
|
newmain.$on("isSubmit", isSubmit => { |
|
|
|
|
this.isSubmit = isSubmit; |
|
|
|
|
}); |
|
|
|
|
this.isSubmit = isSubmit |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
methods: { |
|
|
|
|
onCmReady3() { |
|
|
|
|
// 页面加载完后重置编辑框大小 |
|
|
|
|
ready() { |
|
|
|
|
this.$refs.myCmGenerate.codemirror.setSize("auto", "calc(100vh - 149px)"); |
|
|
|
|
}, |
|
|
|
|
// 下载文件 |
|
|
|
|
downloadFile(fileName,url) { |
|
|
|
|
var x = new XMLHttpRequest() |
|
|
|
|
x.open("GET", url, true) |
|
|
|
@ -203,11 +181,11 @@ export default { |
|
|
|
|
// 下面这个函数就是递归执行这个input输入过程的函数 |
|
|
|
|
confirmInput(msg){ |
|
|
|
|
let receiveResult = msg.replace('validing:','') |
|
|
|
|
this.modifys += receiveResult |
|
|
|
|
this.runResult += receiveResult |
|
|
|
|
this.$prompt(receiveResult, "提示", { |
|
|
|
|
confirmButtonText: "确定" |
|
|
|
|
}).then(({ value }) => { |
|
|
|
|
this.modifys += `${value}<br>` |
|
|
|
|
this.runResult += `${value}<br>` |
|
|
|
|
// 把exit函数替换成用户输入的值 |
|
|
|
|
this.sourceCode = this.sourceCode.replace(`exit('validing:${receiveResult.replace(/[\r\n]*/g,'')}')`,val => { |
|
|
|
|
return `'${value}'` |
|
|
|
@ -222,8 +200,8 @@ export default { |
|
|
|
|
this.requestList.map(n => n('interrupt')) |
|
|
|
|
},1000) |
|
|
|
|
|
|
|
|
|
axios.post(this.api.UpdateCode,{ |
|
|
|
|
code: this.exampleData, |
|
|
|
|
axios.post(this.api.runPythonCode,{ |
|
|
|
|
code: this.codeVal, |
|
|
|
|
bcId: this.workbench1, |
|
|
|
|
cid: this.courseId, |
|
|
|
|
projectId: this.projectId |
|
|
|
@ -236,19 +214,15 @@ export default { |
|
|
|
|
let result = res.message.result |
|
|
|
|
if(result.includes('File ')){ |
|
|
|
|
let modify = res.message.result |
|
|
|
|
this.modifys = modify |
|
|
|
|
this.after = modify.substring( |
|
|
|
|
modify.indexOf("line") + 4, |
|
|
|
|
modify.length |
|
|
|
|
); |
|
|
|
|
this.num = parseInt(this.after) |
|
|
|
|
this.runResult = modify |
|
|
|
|
this.errLine = parseInt(modify.substring(modify.indexOf("line") + 4, modify.length)) |
|
|
|
|
this.isError = res.message.isError |
|
|
|
|
}else if(result.includes('validing:')){ |
|
|
|
|
this.isError = 0 |
|
|
|
|
this.confirmInput(result) |
|
|
|
|
}else if(!res.message.isError){ |
|
|
|
|
this.isError = 0 |
|
|
|
|
this.modifys += result |
|
|
|
|
this.runResult += result |
|
|
|
|
newmain.$emit("updateJud",{ |
|
|
|
|
id: res.data.judgmentPointsId, |
|
|
|
|
isError: res.data.isError |
|
|
|
@ -256,31 +230,30 @@ export default { |
|
|
|
|
} |
|
|
|
|
}).catch(e => { |
|
|
|
|
if(e && e.message == 'interrupt'){ |
|
|
|
|
this.AnswerTips(true) |
|
|
|
|
this.runCode(true) |
|
|
|
|
this.requestList = [] |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
}).catch(err => {}) |
|
|
|
|
}, |
|
|
|
|
AnswerTips(isWhile) {// isWhile为true表示代码里有while循环,右边的运行结果需要拼接展示,而不是直接覆盖 |
|
|
|
|
if (this.isSubmit == "") { |
|
|
|
|
this.submit = 1; |
|
|
|
|
if (this.codeid == "") { |
|
|
|
|
runCode(isWhile) { // isWhile为true表示代码里有while循环,右边的运行结果需要拼接展示,而不是直接覆盖 |
|
|
|
|
if (!this.isSubmit) { |
|
|
|
|
if (!this.codeVal) { |
|
|
|
|
this.$message({ |
|
|
|
|
message: "警告哦,内容为空不可运行", |
|
|
|
|
type: "warning" |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
} else { |
|
|
|
|
let inputTextReg = this.inputTextReg |
|
|
|
|
let inputFuncReg = /input\(['|"]/g |
|
|
|
|
// 该正则是验证代码里是否有input,如果有,就要另外做处理,而不是直接传给后端执行 |
|
|
|
|
if (inputTextReg.test(this.exampleData)) { |
|
|
|
|
let sourceCode = this.exampleData |
|
|
|
|
if (inputTextReg.test(this.codeVal)) { |
|
|
|
|
let sourceCode = this.codeVal |
|
|
|
|
sourceCode = sourceCode.replace(inputTextReg,val => { |
|
|
|
|
return val.replace(/\\n/g,"") |
|
|
|
|
}) |
|
|
|
|
this.exampleData = sourceCode |
|
|
|
|
this.codeVal = sourceCode |
|
|
|
|
|
|
|
|
|
// 把input函数替换成exit函数,加上"validing:"作为特定标识,好方便后面的识别 |
|
|
|
|
sourceCode = sourceCode.replace(inputFuncReg,val => { |
|
|
|
@ -288,9 +261,9 @@ export default { |
|
|
|
|
}) |
|
|
|
|
this.sourceCode = sourceCode |
|
|
|
|
|
|
|
|
|
if(!isWhile) this.modifys = '' |
|
|
|
|
this.$post(this.api.UpdateCode, { |
|
|
|
|
code: this.exampleData, |
|
|
|
|
if(!isWhile) this.runResult = '' |
|
|
|
|
this.$post(this.api.runPythonCode, { |
|
|
|
|
code: this.codeVal, |
|
|
|
|
bcId: this.workbench1, |
|
|
|
|
cid: this.courseId, |
|
|
|
|
projectId: this.projectId |
|
|
|
@ -299,16 +272,12 @@ export default { |
|
|
|
|
if(result.includes('File ')){ |
|
|
|
|
let modify = res.message.result |
|
|
|
|
if(isWhile){ |
|
|
|
|
this.modifys += modify |
|
|
|
|
this.runResult += modify |
|
|
|
|
}else{ |
|
|
|
|
this.modifys = modify |
|
|
|
|
this.runResult = modify |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.after = modify.substring( |
|
|
|
|
modify.indexOf("line") + 4, |
|
|
|
|
modify.length |
|
|
|
|
); |
|
|
|
|
this.num = parseInt(this.after) |
|
|
|
|
this.errLine = parseInt(modify.substring(modify.indexOf("line") + 4, modify.length)) |
|
|
|
|
this.isError = res.message.isError |
|
|
|
|
}else if(result.includes('validing:')){ |
|
|
|
|
this.isError = 0 |
|
|
|
@ -319,93 +288,65 @@ export default { |
|
|
|
|
this.loadIns = Loading.service({ |
|
|
|
|
background: 'transparent' |
|
|
|
|
}) |
|
|
|
|
//实时更新编辑器代码(修改代码) |
|
|
|
|
this.$post(this.api.UpdateCode, { |
|
|
|
|
code: this.exampleData, |
|
|
|
|
// 把代码传给后端,在后端运行Python代码 |
|
|
|
|
this.$post(this.api.runPythonCode, { |
|
|
|
|
code: this.codeVal, |
|
|
|
|
bcId: this.workbench1, |
|
|
|
|
cid: this.courseId, |
|
|
|
|
projectId: this.projectId |
|
|
|
|
}) |
|
|
|
|
.then(res => { |
|
|
|
|
this.loadIns.close() |
|
|
|
|
this.picSrc = '' |
|
|
|
|
if(typeof res.message == 'string'){ |
|
|
|
|
this.isError = res.message.isError; |
|
|
|
|
this.modifys = '' |
|
|
|
|
this.picSrc = `${res.message}?id=${new Date().getTime()}` |
|
|
|
|
newmain.$emit("updateJud",{ |
|
|
|
|
id: res.data.judgmentPointsId, |
|
|
|
|
isError: res.data.isError |
|
|
|
|
}) |
|
|
|
|
}else{ |
|
|
|
|
// 这段是为要下载图片的项目案例写的,后端会返回图片名称的数组,前端负责循环这个数组,然后下载下来 |
|
|
|
|
// 只有该系统有这段代码,因为其他7个系统没有下载图片的项目,后续如果加了,直接把这段代码复制过去即可 |
|
|
|
|
if(!res.message.isError){ |
|
|
|
|
let result = '' |
|
|
|
|
try { |
|
|
|
|
result = eval(res.message.result) |
|
|
|
|
} catch (error) {} |
|
|
|
|
if(result instanceof Array && result.length && (result[0].includes('.jpg') || result[0].includes('.png') || result[0].includes('.gif'))){ |
|
|
|
|
result.map((n,i) => { |
|
|
|
|
this.downloadFile(`${i+1}.jpg`,n) |
|
|
|
|
}) |
|
|
|
|
this.isError = 0 |
|
|
|
|
this.modifys = '下载完成' |
|
|
|
|
}else{ |
|
|
|
|
this.isError = res.message.isError; |
|
|
|
|
newmain.$emit("updateJud",{ |
|
|
|
|
id: res.data.judgmentPointsId, |
|
|
|
|
isError: res.data.isError |
|
|
|
|
}) |
|
|
|
|
var modify = res.message.result; |
|
|
|
|
this.modifys = modify; |
|
|
|
|
this.after = modify.substring( |
|
|
|
|
modify.indexOf("line") + 4, |
|
|
|
|
modify.length |
|
|
|
|
); |
|
|
|
|
this.num = parseInt(this.after); |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
this.isError = res.message.isError; |
|
|
|
|
newmain.$emit("updateJud",{ |
|
|
|
|
id: res.data.judgmentPointsId, |
|
|
|
|
isError: res.data.isError |
|
|
|
|
}).then(res => { |
|
|
|
|
const data = res.code |
|
|
|
|
const photo = data.photoUrl |
|
|
|
|
const result = data.runResult |
|
|
|
|
this.loadIns.close() |
|
|
|
|
this.picSrc = '' |
|
|
|
|
if(photo){ |
|
|
|
|
this.isError = 0 |
|
|
|
|
this.runResult = '' |
|
|
|
|
this.picSrc = `${photo}?id=${new Date().getTime()}` |
|
|
|
|
}else{ |
|
|
|
|
// 这段是为要下载图片的项目案例写的,后端会返回图片名称的数组,前端负责循环这个数组,然后下载下来 |
|
|
|
|
// 只有该系统有这段代码,因为其他7个系统没有下载图片的项目,后续如果加了,直接把这段代码复制过去即可 |
|
|
|
|
if(0){ |
|
|
|
|
if(result instanceof Array && result.length && (result[0].includes('.jpg') || result[0].includes('.png') || result[0].includes('.gif'))){ |
|
|
|
|
result.map((n,i) => { |
|
|
|
|
this.downloadFile(`${i+1}.jpg`,n) |
|
|
|
|
}) |
|
|
|
|
var modify = res.message.result; |
|
|
|
|
this.modifys = modify; |
|
|
|
|
this.after = modify.substring( |
|
|
|
|
modify.indexOf("line") + 4, |
|
|
|
|
modify.length |
|
|
|
|
); |
|
|
|
|
this.num = parseInt(this.after); |
|
|
|
|
this.isError = 0 |
|
|
|
|
this.runResult = '下载完成' |
|
|
|
|
}else{ |
|
|
|
|
this.isError = 0 |
|
|
|
|
this.runResult = data.runResult |
|
|
|
|
this.errLine = parseInt(result.substring(modify.indexOf("line") + 4, modify.length)) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
this.isError = data.retResult |
|
|
|
|
this.runResult = result |
|
|
|
|
this.errLine = parseInt(result.substring(result.indexOf("line") + 4, result.length)) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.catch(res => { |
|
|
|
|
res.status == 500 && this.$message.error('检测到代码里有非法代码,请检查是否有调用系统命令。') |
|
|
|
|
this.loadIns.close() |
|
|
|
|
}); |
|
|
|
|
clearTimeout(this.timer); |
|
|
|
|
} |
|
|
|
|
}).catch(res => { |
|
|
|
|
res.status == 500 && this.$message.error('检测到代码里有非法代码,请检查是否有调用系统命令。') |
|
|
|
|
this.loadIns.close() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
this.isAnswerTips = true; |
|
|
|
|
this.runEnable = true |
|
|
|
|
this.$message({ |
|
|
|
|
message: "警告哦,已提交不可再运行", |
|
|
|
|
type: "warning" |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
getQueryAnswer() { |
|
|
|
|
this.error = true; |
|
|
|
|
getTips() { |
|
|
|
|
this.tipsVisible = true |
|
|
|
|
//提示答案 |
|
|
|
|
this.$get(this.api.QueryAnswer, { |
|
|
|
|
judgmentPointsId: this.workbench1 |
|
|
|
|
}) |
|
|
|
|
.then(res => { |
|
|
|
|
this.answer = res.message; |
|
|
|
|
}) |
|
|
|
|
.catch(err => {}); |
|
|
|
|
}).then(res => { |
|
|
|
|
this.answer = res.message |
|
|
|
|
}).catch(err => {}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|