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.
educoder/public/react/src/modules/page/MainContentContainer.js

950 lines
32 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { Component } from 'react';
import PropTypes from 'prop-types';
// import getMuiTheme from 'material-ui/styles/getMuiTheme'
import Dialog, {
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from 'material-ui/Dialog';
import Button from 'material-ui/Button';
import MainContent from './MainContent'
import UpdateDrawer from './component/UpdateDrawer'
import axios from 'axios'
import _ from 'lodash'
const CancelToken = axios.CancelToken;
let locationPath = window.location.pathname;
let readingRepoTimes = 0;
function updateCodeMirror () {
// TODO 这里的处理方式比较蹩脚css没搞定总高度减去页签头高度
window.$('#games_repository_contents .CodeMirror').height(window.$('#games_repository_contents').height() - 40)
// 为了解决这个问题一开始进入TPI代码框的内容显示不全需要点击一下代码框才会显示全
$('#games_repository_valuation .CodeMirror .CodeMirror-scroll').scrollTop('2')
// 选择题切换到编程题会出现codemirror没初始化成功的问题加下refresh
window.editor_CodeMirror && window.editor_CodeMirror.refresh()
}
// ============================ ============================ ============================ ============================
// 老版本的评测等待通知代码
// ============================ ============================ ============================ ============================
const $ = window.$;
let next_game = null;
function getRandom(min, max){
var r = Math.random() * (max - min);
var re = Math.round(r + min);
re = Math.max(Math.min(re, max), min);
return re;
}
function tipContent(flag, num, mintes, second, first){
console.log("第几次查询get_waiting_time:" + first);
var random = getRandom(15, 120);
var mintes = parseInt((second - random) / 60);
var html=tip_half(flag, num, mintes, second);
$("#update_game_tip").html(html);
if(first == 1){
show_tip_content();
}
}
// 显示右侧评测等待通知
function show_tip_content(){
var $tip = $(".tip-panel-animate");
$(".update_back_main").show();
$tip.addClass("animate-tip").show();
setTimeout(function(){$tip.removeClass("animate-tip")}, 700);
}
//隐藏右侧评测等待通知
function hide_tip_content(){
var $tip = $(".tip-panel-animate");
$tip.addClass("animate-tip-hide");
$(".-task-title").hide();
setTimeout(function(){
$tip.hide().removeClass("animate-tip-hide animate-tip");
check_hide();
}, 700);
}
window.hide_tip_content = hide_tip_content;
//判断是否所有的提示信息都已经隐藏
function check_hide(){
var dis = true;
var $tipLeft = $(".tip-panel-animate-left");
for(var i = 0; i < $tipLeft.length; i++){
if($tipLeft.eq(i).css("display") == "block"){
dis = false;
return;
}
}
if($(".tip-panel-animate").css("display") == "block"){
dis = false;
}
if(dis){
$(".update_back_main").hide();
$('#info_tip_tab').removeClass('leftnav-active');//去除系统通知的选中状态
$('#current_task_tab').addClass('leftnav-active');//选中当前任务
}
}
/*评测等待通知*/
function tip_half(flag, num, mintes, second){
var htmlvalue="";
htmlvalue+="<p class=\"ml15 mr15 mt3 color-grey3 font-16\">评测等待通知</p>";
if(flag == 0){
htmlvalue+="<p class=\"color-dark-grey\" style=\"line-height: 20px;margin:10px 15px\">目前有<span class=\"color-orange03\">" + num + "</span>人正在等待评测,还需等待约<span class=\"color-orange03\">" + (mintes > 0 ? mintes + "分钟" : second + "秒") + "</span>。您可以先完成“下一关”任务。</p>";
}else{
htmlvalue+="<p class=\"color-dark-grey\" style=\"line-height: 20px;margin:0px 15px\">目前有超过<span class=\"color-orange03\">" + num*10 + "</span>人正在等待评测,请您稍后再试。您可以先完成其他关卡</p>";
}
htmlvalue+="<div class=\"tip-operator-btn\">";
if(flag == 0){
htmlvalue+="<a href=\"javascript:void(0)\" class=\"fl color-orange03\" data-tip-top=\"留在本页等待评测结果\" onclick=\"hide_tip_content()\">继续等待</a>";
if (next_game) {
htmlvalue+="<a href=\"/tasks/" + next_game + "\" class=\"fl color-grey\" data-tip-top=\"稍后查看评测结果\" onclick=\"hide_tip_content()\">下一关</a>";
} else {
htmlvalue+="<a href=\"javascript:void(0)\" class=\"fl color-grey\" >已经是最后一关啦</a>"
}
}else{
htmlvalue+="<a href=\"javascript:void(0)\" class=\"fl color-orange03\" data-tip-top=\"留在本页重新评测\" onclick=\"hide_tip_content()\">知道啦</a>";
if (next_game) {
htmlvalue+="<a href=\"/tasks/" + next_game + "\" class=\"fl color-grey\" data-tip-top=\"下一关\" onclick=\"hide_tip_content()\">下一关</a>";
} else {
htmlvalue+="<a href=\"javascript:void(0)\" class=\"fl color-grey\" >已经是最后一关啦</a>"
}
}
htmlvalue+="</div>";
return htmlvalue;
}
/*更新通知*/
function tip_half_update(){
var htmlvalue="";
htmlvalue+="<p class=\"mb5 ml15 mt8 mr15 color-grey3 font-14 mt8\" style=\"line-height: 20px\">本次更新设计以下几个步骤,预计需要花费几分钟时间,请耐心等待~</p>";
htmlvalue+="<ol class=\"ml15\">";
htmlvalue+="<li style=\"list-style-type: disc;margin-left: 20px;line-height: 20px\">更新版本库</li>";
htmlvalue+="<li style=\"list-style-type: disc;margin-left: 20px;line-height: 20px\">同步评测机制</li></ol>";
htmlvalue+="<div class=\"tip-operator-btn\">";
htmlvalue+="<a href=\"javascript:void(0)\" class=\"fl color-orange03\" style=\"width:100%;text-align: center;border:none\" onclick=\"hide_tip_content()\">知道啦</a>";
htmlvalue+="</div>";
return htmlvalue;
}
// ============================ ============================ ============================ ============================
// ============================ ============================ ============================ ============================
const UPDATED = 0;
const SAVING = 1;
const SAVED = 2;
const SAVE_FAILED = 3;
class MainContentContainer extends Component {
constructor(props) {
super(props)
this.onRepositoryCodeUpdate = this.onRepositoryCodeUpdate.bind(this)
this.onRunCodeTest = this.onRunCodeTest.bind(this)
this.codemirrorDidMount = this.codemirrorDidMount.bind(this)
this.fetchRepositoryCode = this.fetchRepositoryCode.bind(this)
this.showResetCodeDialog = this.showResetCodeDialog.bind(this)
this.showResetPassedCodeDialog = this.showResetPassedCodeDialog.bind(this)
this.oldRepositoryCode = '';
this.state = {
repositoryCode: '',
open: false, // 繁忙等级等提示用Dialog考虑重构封装到根组件
gameBuilding: false, // 评测中标志
codeStatus: SAVED, // 0 已修改 1 保存中 2 已保存 3 保存失败
codeLoading: true, // code加载中
readRepoTimeout: false, // 加载代码轮训超时
resetCodeDialogOpen: false, // 考虑重构封装到根组件
resetPassedCodeDialogOpen: false, // 考虑重构封装到根组件
isEditablePath: true
}
}
// ------------------------------------------------
// static childContextTypes = {
// muiTheme: PropTypes.object
// }
// getChildContext() {
// return {
// muiTheme: getMuiTheme()
// }
// }
// ------------------------------------------------
handleClose = () => {
this.setState({open: false});
};
shouldComponentUpdate(nextProps, nextState) {
// _.isEqual(this.props, nextProps)
if (JSON.stringify(nextProps) !== JSON.stringify(this.props) || !_.isEqual(this.state, nextState)) {
return true
} else {
return false
}
}
componentWillReceiveProps(newProps, nContext) {
// 编程题才需要拿代码
if (newProps.game && newProps.st === 0) {
if (!this.props || !this.props.game
|| ( newProps.game.identifier !== this.props.game.identifier ) ) {
setTimeout(this.fetchRepositoryCode( newProps), 1500);
} else if ( this.props.challenge.pathIndex != newProps.challenge.pathIndex
&& newProps.challenge.pathIndex !== -1) { // 切换到只读文件
// pathIndex切换
setTimeout(this.fetchRepositoryCode( newProps), 1500);
}
}
if (newProps.myshixun) {
var stageId = newProps.match.params.stageId;
var shixunId = newProps.myshixun.identifier;
// locationPath = `/myshixuns/${shixunId}/stages/${stageId}`
locationPath = `/api/v1/games/${newProps.game.identifier}`;
next_game = newProps.next_game;
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
const { game } = this.props
if (game && prevProps.game
&& prevProps.game.identifier !== game.identifier) {
// 切换关卡时,停止轮训
this.oldGameIdentifier = prevProps.game.identifier;
}
}
// arg_path 点击文件目录树时传入的点击节点对应的path
fetchRepositoryCode( props, arg_path, type, isRetry) {
const { challenge, showSnackbar, game, shixun, myshixun, hide_code } = props ? props : this.props;
if (shixun.vnc == true) {
// vnc模式下不需要加载代码
return true;
}
if (
// true ||
hide_code) { // 隐藏code的实训
this.setState({ codeLoading: false });
return;
}
const stageId = game.identifier
let path;
let isEditablePath = false;
if (arg_path) {
path = arg_path;
if (challenge.multiPath) {
challenge.path.forEach(item => {
if (path == item) {
isEditablePath = true;
}
})
} else if (path == challenge.path) {
isEditablePath = true;
}
} else {
isEditablePath = true;
path = challenge.multiPath ? challenge.path[challenge.pathIndex] : challenge.path;
}
if (readingRepoTimes === 0) {
this.setState({
readRepoTimeout: false
})
}
// http://localhost:3000/api/v1/games/zl6kx8f7vfpo/rep_content
let status = type ? type : 0; // type 1 目录树点击 默认 0 正常代码加载
// const fetchRepoCodeUrl = `/api/v1/games/${stageId}/rep_content?path=${path}&shixun_gpid=${shixun.gpid}&status=${status}&retry=${isRetry ? 1 : 0}`
const fetchRepoCodeUrl = `/tasks/${game.identifier}/rep_content.json?path=${path}&status=${status}&retry=${isRetry ? 1 : 0}`
// ?path=${path}&shixun_gpid=${shixun.gpid}&status=${status}&retry=${isRetry ? 1 : 0}
if (this.state.codeLoading === true && this._cancel) { // 多次请求则cancel掉前面的请求
// bug cancel掉第一次请求后第二次请求也没法发出先注释掉了
// this._cancel();
// this._cancel = null;
}
const that = this;
this.setState({ gameBuilding: false, codeLoading: true });
axios.get(fetchRepoCodeUrl, {
// path: path
// withCredentials: true,
// cancelToken: new CancelToken(function executor(c) {
// // An executor function receives a cancel function as a parameter
// that._cancel = c;
// })
}).then((fetchRepositoryCodeResponse) => {
// 空字符串还是正常切换
if (fetchRepositoryCodeResponse.data.status == 0) {
readingRepoTimes = readingRepoTimes + 1;
if(readingRepoTimes > 9) {
this.setState({
readRepoTimeout: true
})
readingRepoTimes = 0;
showSnackbar(`网络异常,请稍后重试。`);
return
}else{
if (status === 0) {
// 轮训后点击切换关卡的话,停止上一关的轮训
if (game.identifier == this.oldGameIdentifier) {
this.oldGameIdentifier = null;
return;
}
setTimeout(() => {
this.fetchRepositoryCode(props,arg_path,type)
}, 1500);
}
}
}else if (fetchRepositoryCodeResponse.data && fetchRepositoryCodeResponse.data.status === -1) {
this.setState({ codeLoading: false })
console.error('`获取代码失败!')
showSnackbar(`获取代码失败:${fetchRepositoryCodeResponse.data.message}`)
}else if (fetchRepositoryCodeResponse.data.status === -3) {
readingRepoTimes = readingRepoTimes + 1;
if(readingRepoTimes > 9) {
this.setState({
readRepoTimeout: true
})
readingRepoTimes = 0;
showSnackbar(`网络异常,请稍后重试。`);
return
}else{
if (status === 0) {
// 轮训后点击切换关卡的话,停止上一关的轮训
if (game.identifier == this.oldGameIdentifier) {
this.oldGameIdentifier = null;
return;
}
// 重试调用的这个 this.props.fetchRepositoryCode(this.props, null, null, true)
setTimeout(() => {
this.fetchRepositoryCode(props, arg_path, type, 1)
}, 1500);
}
}
} else if (fetchRepositoryCodeResponse.data.status === -4) {
// 异常 直接重试
this.fetchRepositoryCode(props, null, null, true)
} else{
this.setState({ isEditablePath, currentPath: path });
this.oldRepositoryCode = fetchRepositoryCodeResponse.data.content || '';
this.updateRepositoryCode(this.oldRepositoryCode, updateCodeMirror)
}
}).catch(error =>{
console.log(error)
this.setState({ codeLoading: false });
showSnackbar(`服务端异常,请联系管理员!`);
})
}
componentDidMount() {
window.$(window.documents).bind("submitChoose",function(){
alert("hello world!");
});
}
doFileUpdateRequestOnCodeMirrorBlur = () => {
var fileUpdatePromise = this.doFileUpdateRequest(true)
if (fileUpdatePromise) {
fileUpdatePromise.then((resData) => {
if (resData.status === -1) { // 保存文件出现异常
this.setState({
codeStatus: SAVE_FAILED
})
return;
}
this.setState({
codeStatus: SAVED
})
}).catch((e) => {
console.log(e)
this.setState({
codeStatus: SAVE_FAILED
})
})
}
}
componentWillUnmount() {
this.autoSaveInterval && clearInterval(this.autoSaveInterval);
}
onEditorBlur = () => {
if (this.autoSaveInterval) {
clearInterval(this.autoSaveInterval);
this.autoSaveInterval = null;
}
this.doFileUpdateRequestOnCodeMirrorBlur()
}
onEditorFocus = () => {
if (this.autoSaveInterval) {
return;
}
this.autoSaveInterval = setInterval( () => {
// code变化时每30秒保存到数据库没变化则不处理
var autoSave = true
var fileUpdatePromise = this.doFileUpdateRequest(true)
if (fileUpdatePromise) {
fileUpdatePromise.then((resData) => {
// TODO 保存失败的处理
this.setState({
codeStatus: SAVED
})
}).catch((e) => {
console.log(e)
})
}
}, 30000);
}
codemirrorDidMount() {
var editor_CodeMirror = window.editor_CodeMirror;
var editor_monaco = window.editor_monaco;
// 失去焦点终止保存事件
// editor_CodeMirror && editor_CodeMirror.on('blur', this.onEditorBlur);
// editor_monaco && editor_monaco.onDidBlurEditorText(this.onEditorBlur)
// 每60秒钟保存一次
editor_CodeMirror && editor_CodeMirror.on('focus', this.onEditorFocus);
editor_monaco && editor_monaco.onDidFocusEditorText(this.onEditorFocus)
}
_refreshHtmlIframe(newCode) {
// TODO 是否是html的code
const isHtmlCode = this.props.challenge.isHtml;
if (isHtmlCode) {
// TODO 参考 _code_actions.html.erb 做link script标签替换
// var $iframe = window.$('#htmlIframe');
// $iframe.ready( () => {
// $iframe.contents().find("body").html(newCode || this.state.repositoryCode);
// });
window.tpi_html_show(newCode)
}
}
updateRepositoryCode(newCode, callback) {
this.setState({
codeLoading: false,
repositoryCode: newCode,
}, () => { callback && callback() });
this._refreshHtmlIframe(newCode)
}
onRepositoryCodeUpdate(newCode) {
if (this.refreshHtmlTimeout) {
clearTimeout(this.refreshHtmlTimeout)
}
// 每2s刷新一次
this.setState({
codeStatus: UPDATED
})
this.refreshHtmlTimeout = setTimeout(()=>{
// this.setState({
// // codeStatus: UPDATED,
// repositoryCode: newCode
// });
this._refreshHtmlIframe(newCode)
this.refreshHtmlTimeout = null;
}, 1500)
}
// forTest true 是评测时触发的file_update
doFileUpdateRequest(checkIfCodeChanged, forTest) {
const { codeStatus } = this.state;
if (!forTest && codeStatus !== UPDATED) { // 已修改状态才能保存
return;
}
// TODO 连着2次请求服务端会报500
// if (forTest == true) {
// if (this.state.codeStatus != UPDATED) {
// return;
// }
// }
let codeContent = this.state.repositoryCode;
if (window['editor_CodeMirror']) {
codeContent = window.editor_CodeMirror.getValue();
} else if (window.editor_monaco) {
codeContent = window.editor_monaco.getValue()
}
if (checkIfCodeChanged === true && this.oldRepositoryCode == codeContent) {
// console.log('code not changed');
this.setState({
codeStatus: SAVED
})
return null;
}
const { challenge, output_sets, onRunCodeTestFinish, myshixun } = this.props
// var url = `${locationPath}/file_update?path=${encodeURIComponent(challenge.path)}`
var url = `/myshixuns/${myshixun.identifier}/update_file.json`
this.setState({
codeStatus: SAVING
})
this.oldRepositoryCode = codeContent;
let argPath;
if (challenge.pathIndex === -1) { // 当前是只读文件
argPath = challenge.multiPath === true ? challenge.path[0] : challenge.path
} else {
argPath = challenge.multiPath === true ? challenge.path[challenge.pathIndex] : challenge.path
}
// 跨域请求时会多一个options请求
// https://github.com/axios/axios/issues/475
return axios.post(url, {
content: codeContent,
// 评测的时候传1其它情况不用传主要是为了区分是用户自己提交还是自动提交
// type: forTest === true ? 1 : 0,
evaluate: forTest === true ? 1 : 0,
game_id : this.props.game.id,
path: argPath
},
{
// withCredentials: true
}
)
}
onRunChooseTest() {
const { st, game, onRunChooseTestFinish, showSnackbar } = this.props;
// 获取form表单值
var value = this.refs.mainContent.refs.chooseQ.getForm().getFieldsValue();
var valueArray = []; // map转array
var unSelectOptionIndexArray = [] // 自己做未选提示
for(var key in value) {
if (!value[key] || (_.isArray(value[key]) && !value[key].join('')[0])) {
unSelectOptionIndexArray.push(key)
break; // 为空处理
}
// TODO array判断
valueArray[parseInt(key)] = _.isArray(value[key]) ? value[key].join('') : value[key] ;
}
if (unSelectOptionIndexArray.length) {
var unSelectOptionIndex = unSelectOptionIndexArray[0]
var _unSelectOptionDom = window.$('#games_repository_contents #choice' + unSelectOptionIndex )[0]
_unSelectOptionDom.scrollIntoView()
showSnackbar(`请先给第${parseInt(unSelectOptionIndex)+1}题选择一个答案。`) // , 'top', 'center'
// 有未选择的题
return;
}
// TODO 未选提示、props.onRunChooseTest
console.log(unSelectOptionIndexArray)
console.log('valueArray', valueArray)
var url = `/api/v1/games/${game.identifier}/choose_build`
this.setState({
gameBuilding: true,
})
axios.post(url, {
answer: valueArray
},
{
withCredentials: true,
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
// }
}
).then((response) => {
if (response.data.test_sets) { // 评测完成
onRunChooseTestFinish(response.data);
this.setState({
gameBuilding: false,
})
}
console.log(response)
}).catch((error) => {
console.log(error)
this.setState({
gameBuilding: false,
})
})
}
setGameBuildFalse() {
this.setState({
gameBuilding: false
})
}
onRunCodeTest() {
// tipContent(0, 100, 30, 360, 1)
// return; // for test
const { st, challenge, output_sets, onRunCodeTestFinish, loading, showDialog, handleGdialogClose, onPathChange } = this.props
const { isEditablePath } = this.state;
if (isEditablePath === false) {
showDialog({
contentText: '需要先切回可编辑的文件才可评测,确认要现在切换吗?',
callback: () => {
onPathChange(0)
handleGdialogClose();
}
})
return;
}
if (loading === true) {
return; // 还在加载中
}
if (st === 1) { // 选择题
this.onRunChooseTest();
return;
}
// ---------------------- 以下是编程题处理 ----------------------
console.log('onRunCodeTest onRunCodeTest')
// http://localhost:3000/myshixuns/so5w6iap97/stages/zl6kx8f7vfpo/file_update?path=src%2Fstep6%2FLinkedList.java
// var url = `${locationPath}/file_update?path=${encodeURIComponent(challenge.path)}`
// var timeOut = parseInt(<%= @myshixun.main_mirror.try(:time_limit) %>); // 超时参数
this.setEvaluateMiddleStatusText('')
this.setState({
gameBuilding: true
})
this.doFileUpdateRequest(null, true)
.then((fileUpdateResponse) => {
console.log(fileUpdateResponse);
if (fileUpdateResponse.data.status === -1) { // 保存文件出现异常
this.setGameBuildFalse()
this.setState({
codeStatus: SAVE_FAILED
})
return;
}
this.setState({
codeStatus: SAVED
})
this.gameBuild(fileUpdateResponse, 1)
})
.catch( (fileUpdateError) => {
console.log(fileUpdateError);
this.setGameBuildFalse()
});
}
setEvaluateMiddleStatusText = (msg) => {
window.$('#evaluateMiddleStatusText').html(msg)
}
// 之前的task_commit方法
gameBuild(fileUpdateResponse, first) {
const { st, challenge, output_sets, onRunCodeTestFinish, resetTestSetsExpandedArray, showSnackbar, time_limit, game } = this.props
const { resubmit, content_modified, sec_key } = fileUpdateResponse.data;
const timeOut = time_limit;
// http://localhost:3000/myshixuns/so5w6iap97/stages/zl6kx8f7vfpo/game_build?first=1&resubmit=GDBEX741_1993
// const game_build_url = `${locationPath}/game_build?first=${first}&resubmit=${resubmit}&content_modified=${content_modified}`
const game_build_url = `/tasks/${game.identifier}/game_build.json?first=${first}&resubmit=${resubmit}&content_modified=${!!content_modified ? 1 : 0}&sec_key=${sec_key}`
// var timeOut = parseInt(<%= @myshixun.main_mirror.try(:time_limit) %>); // 超时参数
resetTestSetsExpandedArray();
axios.get(game_build_url, {
// withCredentials: true,
}).then((gameBuildResponse) => {
console.log(gameBuildResponse);
// D:\Code\trustieplus\app\views\games\_code_actions.html.erb
let { port, ableToCreate, waitNum, waitingTime, had_done } = gameBuildResponse.data;
// http://localhost:3000/myshixuns/so5w6iap97/stages/zl6kx8f7vfpo/game_status?resubmit=GDBEX741_1993&port=50241&time_out=false
// TODO dead code 往下走
// if (ableToCreate == 1) {
if (gameBuildResponse.data.status == -1) {
return
}
let timeOutFlag = false;
const intervalDuring = 1000;
let requestTimes = 0;
var gameStatusIntervalId = setInterval(()=>{
// let game_status_url = `${locationPath}/game_status?port=${port}&resubmit=${resubmit||""}&time_out=${timeOutFlag}`
let game_status_url = `/tasks/${game.identifier}/game_status.json?port=${port}&resubmit=${resubmit||""}&time_out=${timeOutFlag}&sec_key=${sec_key}`
axios.get(game_status_url, {
// withCredentials: true,
}).then((gameStatusResponse) => {
requestTimes++;
const { status, running_code_message } = gameStatusResponse.data;
if(!gameStatusResponse.data || !status && status !== 0) {
if(requestTimes >= timeOut - 1){ // 最后一次参数改为true
timeOutFlag = true;
}
if (running_code_message) {
this.setEvaluateMiddleStatusText(running_code_message)
}
return;
}
if (timeOutFlag === false && (status === 2 || status === 0)) {
// 网络太慢或服务处理较慢的情况下,可能这里会执行第二次
console.log('clearIntervalclearIntervalclearIntervalclearInterval status2 0')
clearInterval(gameStatusIntervalId);
onRunCodeTestFinish(gameStatusResponse.data)
this.setGameBuildFalse()
timeOutFlag = true; // 用这个处理重复的获取status为2或0的状态
}
// 超时处理
if(timeOutFlag === true) {
// clearInterval(gameStatusIntervalId);
console.log('超时处理返回值')
this._refreshHtmlIframe();
this.setGameBuildFalse()
return;
}
if(requestTimes >= timeOut - 1){ // 最后一次参数改为true
timeOutFlag = true;
}
}).catch((gameStatusError) => {
console.log(gameStatusError);
})
if (timeOutFlag === true) {
clearInterval(gameStatusIntervalId);
this.setState({
open: true,
gameBuilding: false
})
}
}, intervalDuring)
window.gameStatusIntervalId = gameStatusIntervalId;
// } else if(ableToCreate === 0) { // 排队等待重新执行gameBuild
// const mintes = parseInt((waitNum * 120) / 60); // 等待时间 = 等待人数 * (15(秒)---3分钟的随机数);
// tipContent(ableToCreate, waitNum, mintes, waitNum * 180, first);
// setTimeout(()=>{
// this.gameBuild(fileUpdateResponse, first + 1)
// }, 10000)
// this.setGameBuildFalse()
// } else if(ableToCreate == -1) { // 排队人数过多,建议先玩下一关
// tipContent(ableToCreate, waitNum, 0, 0, first);
// this.setGameBuildFalse()
// } else {
// showSnackbar("实训云平台繁忙繁忙等级94请稍后刷新并重试")
// this.setGameBuildFalse()
// }
}).catch((gameBuildError) => {
console.log(gameBuildError);
this.setGameBuildFalse()
})
}
handleResetCodeDialogClose() {
this.setState({ resetCodeDialogOpen: false })
}
showResetCodeDialog() {
this.setState({ resetCodeDialogOpen: true })
}
doResetCode() {
const { game, challenge, showSnackbar } = this.props;
this.handleResetCodeDialogClose();
let path = challenge.path
if (challenge.multiPath) {
path = path[challenge.pathIndex]
}
// const url = `/api/v1/games/${game.identifier}/reset_original_code?path=${path}`;
const url = `/tasks/${game.identifier}/reset_original_code.json?path=${path}`;
this.setState({
codeLoading: true
})
axios.get(url, {
// withCredentials: true,
}).then((res) => {
this.handleResetCodeDialogClose();
if (res.data.status === -1) {
console.error('代码重置失败!');
this.setState({
codeLoading: false
})
showSnackbar(res.data.message || '加载初始的代码失败')
return;
}
// this.setState({
// codeLoading: false
// })
this.updateRepositoryCode(res.data.content, updateCodeMirror)
}).catch(error =>{
this.setState({
codeLoading: false
})
})
}
handleResetPassedCodeDialogClose() {
this.setState({ resetPassedCodeDialogOpen: false })
}
showResetPassedCodeDialog() {
this.setState({ resetPassedCodeDialogOpen: true })
}
doResetPassedCode() {
this.handleResetPassedCodeDialogClose();
const { game, challenge, showSnackbar } = this.props;
let path = challenge.path
if (challenge.multiPath) {
path = path[challenge.pathIndex]
}
// const url = `/api/v1/games/${game.identifier}/reset_passed_code?path=${path}`;
const url = `/tasks/${game.identifier}/reset_passed_code.json?path=${path}`;
this.setState({
codeLoading: true
})
axios.get(url
// , {
// withCredentials: true,
// }
).then((res) => {
this.handleResetPassedCodeDialogClose();
if (res.data.status === -1) {
console.error('passed代码重置失败')
this.setState({
codeLoading: false
})
showSnackbar(res.data.message || '加载上次通过的代码失败')
return;
}
// 注意最好是合并到一个setState, 这里分两次setState的话触发了2次重新渲染
// this.setState({
// codeLoading: false
// })
this.updateRepositoryCode(res.data.content, updateCodeMirror)
}).catch(error =>{
this.setState({
codeLoading: false
})
})
}
render() {
const { challenge, output_sets, time_limit } = this.props;
// TODO 这里直接写死了game_status在超时时也会返回这句话
let msg = (
<div>
{`代码评测超时!本关限定时间为:${time_limit}s`}<br></br>
请检查代码是否存在死循环或其他耗时操作
</div>)
return (
<React.Fragment>
<Dialog
open={this.state.open}
disableEscapeKeyDown={true}
onClose={this.handleClose}
>
<DialogTitle id="alert-dialog-title">{"提示"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description" style={{textAlign: 'center'}}>
{ msg }
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
关闭
</Button>
</DialogActions>
</Dialog>
<Dialog
open={this.state.resetCodeDialogOpen}
disableEscapeKeyDown={true}
onClose={() => this.handleResetCodeDialogClose()}
>
<DialogTitle id="alert-dialog-title">{"提示"}</DialogTitle>
<DialogContent>
<div style={{textAlign: 'center'}}>
你在本文件中修改的内容将丢失<br></br>
</div>
</DialogContent>
<DialogActions>
<Button onClick={() => this.handleResetCodeDialogClose()} color="primary">
关闭
</Button>
<Button variant="raised" onClick={() => this.doResetCode()} color="primary">
确定
</Button>
</DialogActions>
</Dialog>
<Dialog
disableEscapeKeyDown={true}
open={this.state.resetPassedCodeDialogOpen}
onClose={() => this.handleResetPassedCodeDialogClose()}
>
<DialogTitle id="alert-dialog-title">{"提示"}</DialogTitle>
<DialogContent>
<div style={{textAlign: 'center'}}>
你在本关中修改的内容将丢失<br></br>?
</div>
</DialogContent>
<DialogActions>
<Button onClick={() => this.handleResetPassedCodeDialogClose()} color="primary">
关闭
</Button>
<Button variant="raised" onClick={() => this.doResetPassedCode()} color="primary">
确定
</Button>
</DialogActions>
</Dialog>
<UpdateDrawer {...this.props} fetchRepositoryCode={this.fetchRepositoryCode}></UpdateDrawer>
<MainContent ref="mainContent" {...this.props} output_sets={output_sets} {...this.state}
onRepositoryCodeUpdate={this.onRepositoryCodeUpdate} onRunCodeTest={this.onRunCodeTest}
codemirrorDidMount={this.codemirrorDidMount} fetchRepositoryCode={this.fetchRepositoryCode}
showResetCodeDialog={this.showResetCodeDialog} showResetPassedCodeDialog={this.showResetPassedCodeDialog}
doFileUpdateRequestOnCodeMirrorBlur={this.doFileUpdateRequestOnCodeMirrorBlur} ></MainContent>
</React.Fragment>
);
}
}
export default MainContentContainer;