919 lines
26 KiB
JavaScript
919 lines
26 KiB
JavaScript
import React, { Component } from 'react';
|
||
import ReactDOM from 'react-dom';
|
||
|
||
import axios from 'axios';
|
||
import Snackbar from 'material-ui/Snackbar';
|
||
import Fade from 'material-ui/transitions/Fade';
|
||
|
||
import update from 'immutability-helper'
|
||
|
||
import Dialog, {
|
||
DialogActions,
|
||
DialogContent,
|
||
DialogContentText,
|
||
DialogTitle,
|
||
} from 'material-ui/Dialog';
|
||
|
||
import Button from 'material-ui/Button';
|
||
|
||
import EvaluateSuccessEffectDisplay from './EvaluateSuccessEffectDisplay'
|
||
|
||
import _ from 'lodash'
|
||
|
||
/*
|
||
若干js库
|
||
http://inorganik.github.io/countUp.js/
|
||
|
||
*/
|
||
/*
|
||
切下一关需要更新:
|
||
LeftViewContainer state.gameAnswer
|
||
*/
|
||
|
||
import TPIContext from './TPIContext'
|
||
import {
|
||
EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER
|
||
, EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL, EDU_BUSINESS, CNotificationHOC, getRandomNumber
|
||
} from 'educoder'
|
||
import { MuiThemeProvider, createMuiTheme, withStyles } from 'material-ui/styles';
|
||
import MUIDialogStyleUtil from '../modules/page/component/MUIDialogStyleUtil'
|
||
|
||
const styles = MUIDialogStyleUtil.getTwoButtonStyle()
|
||
|
||
// 主题自定义
|
||
const theme = createMuiTheme({
|
||
palette: {
|
||
primary: {
|
||
main: '#4CACFF',
|
||
contrastText: 'rgba(255, 255, 255, 0.87)'
|
||
},
|
||
secondary: { main: '#4CACFF' }, // This is just green.A700 as hex.
|
||
},
|
||
});
|
||
|
||
const testSetsExpandedArrayInitVal = [false, false, false, false, false,
|
||
false, false, false, false, false,
|
||
false, false, false, false, false,
|
||
false, false, false, false, false]
|
||
window.__fetchAllFlag = false; // 是否调用过fetchAll TODO 如何多次使用provider?
|
||
|
||
const $ = window.$
|
||
class TPIContextProvider extends Component {
|
||
constructor(props) {
|
||
super(props)
|
||
this.onRunCodeTestFinish = this.onRunCodeTestFinish.bind(this)
|
||
this.onRunChooseTestFinish = this.onRunChooseTestFinish.bind(this)
|
||
this.testSetUnlock = this.testSetUnlock.bind(this)
|
||
|
||
this.onTestSetHeaderClick = this.onTestSetHeaderClick.bind(this)
|
||
|
||
this.onShowPrevStage = this.onShowPrevStage.bind(this)
|
||
this.onShowNextStage = this.onShowNextStage.bind(this)
|
||
|
||
this.readGameAnswer = this.readGameAnswer.bind(this)
|
||
this.praisePlus = this.praisePlus.bind(this)
|
||
|
||
this.onGamePassed = this.onGamePassed.bind(this)
|
||
|
||
this.onPathChange = this.onPathChange.bind(this)
|
||
|
||
this.showSnackbar = this.showSnackbar.bind(this)
|
||
this.showDialog = this.showDialog.bind(this)
|
||
|
||
this.onShowUpdateDialog = this.onShowUpdateDialog.bind(this)
|
||
this.updateDialogClose = this.updateDialogClose.bind(this)
|
||
|
||
// this.showEffectDisplay();
|
||
|
||
this.state = {
|
||
loading: true, // 正在加载数据
|
||
gDialogOpen: false,
|
||
currentGamePassed: false, // 当前game评测通过
|
||
currentPassedGameGainGold: 0, // 当前通过的game获得的金币数
|
||
currentPassedGameGainExperience: 0, // 当前通过的game获得的经验数
|
||
|
||
user: {},
|
||
challenge: {},
|
||
shixun_name: '',
|
||
hide_code: false,
|
||
|
||
showUpdateDialog: false,
|
||
|
||
testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0),
|
||
}
|
||
}
|
||
|
||
showEffectDisplay = (data) => {
|
||
const dom = document.getElementById('picture_display');
|
||
window.$(dom).show();
|
||
ReactDOM.unmountComponentAtNode(dom)
|
||
ReactDOM.render(<EvaluateSuccessEffectDisplay type={"qrcode"} {...data} />, dom);
|
||
}
|
||
|
||
onShowUpdateDialog() {
|
||
this.setState({ showUpdateDialog: true })
|
||
}
|
||
// updateNowSuccess true 立即更新成功
|
||
// TODO updateDialogClose方法名不对, 改为updateDialogCallback
|
||
updateDialogClose(nextUpdateSuccess, updateNowSuccess) {
|
||
const { myshixun } = this.state;
|
||
if (nextUpdateSuccess) {
|
||
myshixun.system_tip = true;
|
||
}
|
||
let { tpm_cases_modified, tpm_modified, tpm_script_modified } = this.state;
|
||
if (updateNowSuccess) {
|
||
tpm_cases_modified = false;
|
||
tpm_modified = false;
|
||
tpm_script_modified = false;
|
||
}
|
||
this.setState({
|
||
myshixun,
|
||
tpm_cases_modified,
|
||
tpm_modified,
|
||
tpm_script_modified,
|
||
showUpdateDialog: false,
|
||
})
|
||
}
|
||
|
||
|
||
componentWillUnmount() {
|
||
|
||
this.costTimeInterval && window.clearInterval(this.costTimeInterval)
|
||
}
|
||
componentDidMount() {
|
||
|
||
|
||
// TODO 登录状态的判断?
|
||
// request
|
||
// var shixunId = this.props.match.params.shixunId;
|
||
var stageId = this.props.match.params.stageId;
|
||
|
||
window.__fetchAllFlag = false;
|
||
this.fetchAll(stageId);
|
||
this.costTimeInterval = window.setInterval(() => {
|
||
const { game } = this.state;
|
||
if (!game || game.status === 2) { // 已完成的任务不需要计时
|
||
return;
|
||
}
|
||
if (game.cost_time || game.cost_time === 0) {
|
||
// game.cost_time += 1;
|
||
this.setState({
|
||
game: update(game, { cost_time: { $set: (game.cost_time + 1) } })
|
||
})
|
||
}
|
||
}, 1000)
|
||
|
||
// // 页面离开时存下用户的任务耗时
|
||
window.$(window).bind('beforeunload', () => {
|
||
this._updateCostTime();
|
||
})
|
||
// window.$(window).unload( ()=>{
|
||
|
||
// this._updateCostTime();
|
||
|
||
// });
|
||
// // 页面离开时存下用户的任务耗时
|
||
// window.$(window).unload( ()=>{
|
||
// this._updateCostTime();
|
||
|
||
// });
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
// force 评测通过后,异步执行该方法,强制同步costTime到服务端
|
||
_updateCostTime(async = false, force) {
|
||
const { game, loading } = this.state;
|
||
// TODO 还有一种情况,通关后cost_time计时停止,没法通过这个判断
|
||
if (!force && (loading || !game || game.status === 2)) {
|
||
return; // 已完成的任务不需要处理
|
||
}
|
||
let testPath = ''
|
||
if (window.location.port == 3007) {
|
||
testPath = 'http://test-newweb.educoder.net'
|
||
}
|
||
|
||
|
||
// var url = `${testPath}/api/v1/games/${ game.identifier }/cost_time`
|
||
var url = `${testPath}/api/tasks/${game.identifier}/cost_time${getRandomNumber()}`
|
||
window.$.ajax({
|
||
type: 'get',
|
||
url: url,
|
||
async: async, //IMPORTANT, the call will be synchronous
|
||
data: {
|
||
time: game.cost_time
|
||
}
|
||
}).done((data) => {
|
||
console.log('complete');
|
||
});
|
||
}
|
||
|
||
onGamePassed(passed) {
|
||
const { game } = this.state
|
||
// 随便给个分,以免重新评测时又出现评星组件(注意:目前game.star没有显示在界面上,如果有则不能这么做)
|
||
// game.star = 6;
|
||
this.setState({
|
||
game: update(game, { star: { $set: 6 } }),
|
||
currentGamePassed: !!passed
|
||
})
|
||
}
|
||
onTestSetHeaderClick(index) {
|
||
// let { testSetsExpandedArray } = this.state;
|
||
let testSetsExpandedArray;
|
||
// 一次只打开一个
|
||
if (this.state.testSetsExpandedArray[index] === false) {
|
||
testSetsExpandedArray = testSetsExpandedArrayInitVal.slice(0);
|
||
} else {
|
||
testSetsExpandedArray = this.state.testSetsExpandedArray.slice(0);
|
||
}
|
||
testSetsExpandedArray[index] = !testSetsExpandedArray[index];
|
||
this.setState({
|
||
testSetsExpandedArray,
|
||
})
|
||
}
|
||
|
||
onShowPrevStage() {
|
||
|
||
}
|
||
onShowNextStage() {
|
||
window.__fetchAllFlag = false;
|
||
console.log('onShowNextStage.........')
|
||
// this.fetchAll('vznhx7mctwfq')
|
||
}
|
||
|
||
componentWillReceiveProps(newProps, oldProps) {
|
||
var newStageId = newProps.match.params.stageId;
|
||
if (!this.props || newStageId !== this.props.match.params.stageId) {
|
||
window.__fetchAllFlag = false;
|
||
this.fetchAll(newStageId)
|
||
}
|
||
}
|
||
|
||
|
||
praisePlus() {
|
||
const { challenge, game } = this.state;
|
||
let praise = true;
|
||
const url = `/tasks/${game.identifier}/plus_or_cancel_praise.json`
|
||
// const url = `/praise_tread/praise_plus?obj_id=${challenge.id}&obj_type=Challenge&horizontal=${praise}&game_praise=true`
|
||
axios.post(url)
|
||
.then((response) => {
|
||
|
||
if (response.data) {
|
||
const { praise_count, praise } = response.data;
|
||
// challenge.praise_count = praise_tread_count;
|
||
// challenge.user_praise = praise;
|
||
this.setState({
|
||
challenge: update(challenge,
|
||
{
|
||
praise_count: { $set: praise_count },
|
||
user_praise: { $set: praise },
|
||
})
|
||
})
|
||
}
|
||
|
||
})
|
||
.catch(function (error) {
|
||
console.log(error);
|
||
});
|
||
}
|
||
|
||
onPathChange(index, callback) {
|
||
let { challenge } = this.state;
|
||
// challenge = Object.assign({}, challenge)
|
||
// challenge.pathIndex = index;
|
||
this.setState({
|
||
challenge: update(challenge, { pathIndex: { $set: index } }),
|
||
}, () => {
|
||
callback && callback()
|
||
})
|
||
// TODO load new path content
|
||
}
|
||
|
||
updateChallengePath = (path) => {
|
||
const challenge = this.state.challenge;
|
||
if (challenge.path === path) {
|
||
return;
|
||
}
|
||
const { myshixun } = this.state;
|
||
// myshixun.system_tip = false;
|
||
|
||
|
||
challenge.path = path;
|
||
const newChallenge = this.handleChallengePath(challenge);
|
||
this.setState({
|
||
challenge: newChallenge,
|
||
myshixun: update(myshixun, { system_tip: { $set: false } }),
|
||
})
|
||
}
|
||
|
||
handleChallengePath(challenge) {
|
||
if (challenge.path && typeof challenge.path === "string") { // 多path的处理
|
||
let path = challenge.path.split(';');
|
||
_.remove(path, (item) => !item)
|
||
if (path.length > 1) {
|
||
challenge.path = path;
|
||
challenge.multiPath = true;
|
||
} else {
|
||
challenge.path = challenge.path.replace(';', '').trim() // 多path 改为单path 出现了 aaa.java;的情况
|
||
challenge.multiPath = false;
|
||
}
|
||
}
|
||
challenge.pathIndex = 0;
|
||
return challenge;
|
||
}
|
||
|
||
newResData2OldResData(newResData) {
|
||
newResData.latest_output = newResData.last_compile_output
|
||
// newResData.power
|
||
newResData.record = newResData.record_onsume_time
|
||
|
||
// 老版用的hide_code
|
||
newResData.hide_code = newResData.shixun.hide_code;
|
||
|
||
newResData.image_url = newResData.user.image_url
|
||
newResData.grade = newResData.user.grade
|
||
newResData.user_url = newResData.user.user_url
|
||
newResData.username = newResData.user.name
|
||
|
||
newResData.output_sets = {}
|
||
// newResData.output_sets.had_test_count = newResData.test_sets_count
|
||
newResData.output_sets.test_sets = newResData.test_sets // JSON.stringify()
|
||
newResData.output_sets.test_sets_count = newResData.test_sets_count
|
||
// newResData.output_sets.had_passed_testsests_error_count = newResData.sets_error_count
|
||
newResData.output_sets.had_passed_testsests_error_count = newResData.test_sets_count
|
||
- newResData.sets_error_count
|
||
// allowed_hidden_testset
|
||
// sets_error_count
|
||
// test_sets_count
|
||
// test_sets
|
||
// had_passed_testsests_error_count
|
||
// test_sets
|
||
// test_sets
|
||
|
||
return newResData
|
||
}
|
||
// 将若干数据重新组织一下
|
||
_handleResponseData(resData_arg) {
|
||
const resData = this.newResData2OldResData(Object.assign({}, resData_arg))
|
||
let challenge = resData.challenge;
|
||
challenge.isHtml = false;
|
||
challenge.isWeb = false;
|
||
challenge.isAndroid = false;
|
||
challenge.showLanguagePictrue = false;
|
||
challenge.hasAnswer = resData.has_answer;
|
||
|
||
let output_sets = resData.output_sets;
|
||
if (resData.st === 0) { // 代码题
|
||
challenge = this.handleChallengePath(challenge)
|
||
|
||
const mirror_name = (resData.mirror_name && resData.mirror_name.join)
|
||
? resData.mirror_name.join(';') : (resData.mirror_name || '');
|
||
if (mirror_name.indexOf('Html') !== -1) {
|
||
challenge.isHtml = true;
|
||
challenge.showLanguagePictrue = true;
|
||
} else if (mirror_name.indexOf('Web') !== -1 || mirror_name.indexOf('JFinal') !== -1) {
|
||
challenge.isWeb = true;
|
||
} else if (mirror_name.indexOf('Android') !== -1) {
|
||
challenge.isAndroid = true;
|
||
}
|
||
|
||
if (output_sets && output_sets.test_sets && typeof output_sets.test_sets == 'string') {
|
||
const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]");
|
||
output_sets.test_sets_array = test_sets_array;
|
||
} else {
|
||
output_sets.test_sets_array = output_sets.test_sets
|
||
}
|
||
|
||
} else { // 选择题
|
||
// 选择题题干markdown初始化
|
||
const $ = window.$
|
||
window.setTimeout(() => {
|
||
var lens = $("#choiceRepositoryView textarea").length;
|
||
|
||
for (var i = 1; i <= lens; i++) {
|
||
window.editormd.markdownToHTML("choose_subject_" + i, {
|
||
htmlDecode: "style,script,iframe", // you can filter tags decode
|
||
taskList: true,
|
||
tex: true, // 数学公式
|
||
// flowChart: true, // 默认不解析
|
||
// sequenceDiagram: true // 默认不解析
|
||
});
|
||
}
|
||
}, 400)
|
||
}
|
||
challenge.user_praise = resData.user_praise;
|
||
challenge.praise_count = resData.praise_count;
|
||
challenge.showWebDisplayButton = false;
|
||
resData.challenge = challenge;
|
||
|
||
// 将一些属性写到game上
|
||
let game = resData.game;
|
||
game.prev_game = resData.prev_game;
|
||
game.next_game = resData.next_game;
|
||
if (game.status == 2) {
|
||
// 已通关
|
||
game.isPassThrough = true
|
||
}
|
||
resData.game = game;
|
||
|
||
const { tpm_cases_modified, tpm_modified, tpm_script_modified, myshixun } = resData;
|
||
if (myshixun.system_tip) {
|
||
// system_tip为true的时候 不弹框提示用户更新
|
||
resData.showUpdateDialog = false
|
||
} else {
|
||
let needUpdateScript = (tpm_modified || tpm_script_modified) && challenge.st === 0;
|
||
resData.showUpdateDialog = needUpdateScript || tpm_cases_modified
|
||
}
|
||
|
||
/**
|
||
email: "721773699@qq.com"
|
||
grade: 213996
|
||
identity: 1
|
||
image_url: "avatars/User/1"
|
||
login: "innov"
|
||
name: "Coder"
|
||
user_url: "/innov"
|
||
*/
|
||
let user = resData.user;
|
||
user.username = resData.user.name;
|
||
user.user_url = `/${resData.user.login}`;
|
||
// user.image_url = resData.image_url;
|
||
user.is_teacher = resData.is_teacher;
|
||
resData.user = user;
|
||
this._handleUserAuthor(resData)
|
||
// TODO 测试
|
||
// resData.power = 0;
|
||
|
||
resData.shixun.vnc = !!resData.vnc_url
|
||
resData.shixun.vnc_evaluate = resData.vnc_evaluate
|
||
|
||
this.setState({
|
||
...resData,
|
||
currentGamePassed: false,
|
||
loading: false,
|
||
testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0),
|
||
})
|
||
|
||
window.document.title = resData.shixun.name
|
||
|
||
window.__myshixun = resData.myshixun; // tpi_html_show需要用到
|
||
}
|
||
_handleUserAuthor(resData) {
|
||
// tpi tpm权限控制
|
||
// const EDU_ADMIN = 1 // 超级管理员
|
||
// const EDU_SHIXUN_MANAGER = 2 // 实训管理员
|
||
// const EDU_SHIXUN_MEMBER = 3 // 实训成员
|
||
// const EDU_CERTIFICATION_TEACHER = 4 // 平台认证的老师
|
||
// const EDU_GAME_MANAGER = 5 // TPI的创建者
|
||
// const EDU_TEACHER = 6 // 平台老师,但是未认证
|
||
// const EDU_NORMAL = 7 // 普通用户
|
||
|
||
|
||
/**
|
||
EDU_ADMIN = 1 # 超级管理员
|
||
EDU_BUSINESS = 2 # 运营人员
|
||
EDU_SHIXUN_MANAGER = 3 # 实训管理员
|
||
EDU_SHIXUN_MEMBER = 4 # 实训成员
|
||
EDU_CERTIFICATION_TEACHER = 5 # 平台认证的老师
|
||
EDU_GAME_MANAGER = 6 # TPI的创建者
|
||
EDU_TEACHER = 7 # 平台老师,但是未认证
|
||
EDU_NORMAL = 8 # 普通用户
|
||
*/
|
||
|
||
// myshixun_manager power is_teacher
|
||
resData.power = 0
|
||
resData.myshixun_manager = false
|
||
// resData.is_teacher = false
|
||
|
||
if (resData.user.identity === EDU_ADMIN) {
|
||
resData.power = 1
|
||
resData.myshixun_manager = true
|
||
} else if (resData.user.identity === EDU_BUSINESS) {
|
||
resData.power = 1
|
||
resData.myshixun_manager = true
|
||
} else if (resData.user.identity === EDU_SHIXUN_MANAGER) {
|
||
resData.power = 1
|
||
resData.myshixun_manager = true
|
||
} else if (resData.user.identity === EDU_SHIXUN_MEMBER) {
|
||
resData.power = 1
|
||
resData.myshixun_manager = true
|
||
} else if (resData.user.identity === EDU_CERTIFICATION_TEACHER) {
|
||
resData.power = 1
|
||
// 已认证老师允许跳关
|
||
resData.myshixun_manager = true
|
||
// resData.is_teacher = true
|
||
|
||
} else if (resData.user.identity === EDU_TEACHER) {
|
||
// resData.is_teacher = true
|
||
} else if (resData.user.identity === EDU_NORMAL) {
|
||
|
||
}
|
||
return resData
|
||
}
|
||
|
||
fetchAll(stageId, noTimeout) {
|
||
|
||
if (window.__fetchAllFlag == true) {
|
||
console.log('TPIContextProvider call fetchAll repeatly!')
|
||
return;
|
||
}
|
||
// 切换关卡的时候,同步costTime
|
||
this._updateCostTime(true);
|
||
|
||
var url = `/tasks/${stageId}.json`
|
||
window.__fetchAllFlag = true;
|
||
this.setState({
|
||
loading: true,
|
||
currentGamePassed: false, // 切换game时重置passed字段
|
||
})
|
||
|
||
axios.get(url)
|
||
.then((response) => {
|
||
window.__fetchAllFlag = false;
|
||
|
||
if (response.data.status == 403) {
|
||
window.location.href = "/403";
|
||
return;
|
||
}
|
||
if (response.data.status == 404) {
|
||
// 如果第一次发生404,则隔1s后再调用一次本接口;(因为ucloud主从同步可能有延迟)
|
||
if (!noTimeout) {
|
||
setTimeout(() => {
|
||
this.fetchAll(stageId, true)
|
||
}, 1000)
|
||
return;
|
||
}
|
||
window.location.href = '/myshixuns/not_found'
|
||
return;
|
||
}
|
||
|
||
this._handleResponseData(response.data)
|
||
|
||
})
|
||
.catch(function (error) {
|
||
console.log(error);
|
||
});
|
||
|
||
}
|
||
|
||
readGameAnswer(resData) {
|
||
// game.final_score = resData.final_score;
|
||
if (resData.final_score) {
|
||
var game = this.state.game;
|
||
this.setState({
|
||
game: update(game, { final_score: { $set: resData.final_score } }),
|
||
grade: resData.grade
|
||
})
|
||
} else {
|
||
this.setState({
|
||
grade: resData.grade
|
||
})
|
||
}
|
||
|
||
}
|
||
closeTaskResultLayer() {
|
||
this.setState({
|
||
game: (this.state.game.status == 2 ? update(this.state.game, {
|
||
isPassThrough: { $set: true },
|
||
}) : this.state.game),
|
||
currentGamePassed: false
|
||
})
|
||
}
|
||
onRunChooseTestFinish(response) {
|
||
const { test_sets, challenge_chooses_count, choose_correct_num, grade, experience, gold, had_submmit, next_game } = response;
|
||
response.had_submmit = true; // 是否已提交
|
||
const { game } = this.state;
|
||
let currentGamePassed = false
|
||
if (challenge_chooses_count === choose_correct_num) {
|
||
game.status = 2;
|
||
// game.isPassThrough = true
|
||
game.next_game = next_game;
|
||
|
||
currentGamePassed = true;
|
||
|
||
|
||
this._updateCostTime(true, true);
|
||
}
|
||
this.setState({
|
||
choose_test_cases: response,
|
||
grade: grade,
|
||
|
||
game,
|
||
next_game,
|
||
currentGamePassed: currentGamePassed,
|
||
currentPassedGameGainGold: gold,
|
||
currentPassedGameGainExperience: experience,
|
||
})
|
||
}
|
||
initDisplayInterval = () => {
|
||
const challenge = this.state.challenge
|
||
if (this.showWebDisplayButtonTimeout) {
|
||
window.clearTimeout(this.showWebDisplayButtonTimeout)
|
||
}
|
||
this.showWebDisplayButtonTimeout = window.setTimeout(() => {
|
||
this.setState({
|
||
challenge: update(challenge,
|
||
{
|
||
showWebDisplayButton: { $set: false },
|
||
})
|
||
})
|
||
this.showWebDisplayButtonTimeout = null
|
||
}, 61 * 1000)
|
||
|
||
let remain = 60
|
||
if (this.displayInterval) {
|
||
window.clearInterval(this.displayInterval)
|
||
}
|
||
this.displayInterval = window.setInterval(() => {
|
||
const button = $('#showWebDisplayButton');
|
||
if (button.length) {
|
||
button.html(`查看效果(${remain})`)
|
||
if (remain == 0) {
|
||
button.html('查看效果')
|
||
}
|
||
}
|
||
if (remain == 0) {
|
||
window.clearInterval(this.displayInterval)
|
||
this.displayInterval = null
|
||
return;
|
||
}
|
||
|
||
remain -= 1;
|
||
}, 1000)
|
||
}
|
||
language_display(data) {
|
||
const { game, tomcat_url } = this.state;
|
||
const challenge = Object.assign({}, this.state.challenge)
|
||
if (challenge.isWeb && data.port != -1) {
|
||
challenge.showWebDisplayButton = true; // ActionView处是否出现查看效果按钮
|
||
this.initDisplayInterval()
|
||
|
||
const path = challenge.web_route || challenge.path
|
||
const webDisplayUrl = `${tomcat_url}:${data.port}/${path}`
|
||
challenge.webDisplayUrl = webDisplayUrl
|
||
challenge.showLanguagePictrue = true; // 评测通过弹出层是否出现查看效果按钮
|
||
}
|
||
else if (data.picture != 0) {
|
||
/**
|
||
{
|
||
"type": "image",
|
||
"orignal_picture": [],
|
||
"user_picture": [],
|
||
"answer_picture": []
|
||
}
|
||
*/
|
||
const url = `/tasks/${game.identifier}/picture_display.json`
|
||
axios.get(url)
|
||
.then((response) => {
|
||
this.showEffectDisplay(response.data)
|
||
})
|
||
|
||
challenge.showLanguagePictrue = true;
|
||
}
|
||
this.setState({
|
||
challenge
|
||
})
|
||
}
|
||
onRunCodeTestFinish(response) {
|
||
console.log('onRunCodeTestFinish', response)
|
||
const { test_sets, test_sets_count, test_sets_hidden_count, test_sets_public_count
|
||
, had_test_count, had_passed_testsests_error_count, had_passed_testsests_hidden_count
|
||
, had_passed_testsests_public_count, final_score, gold, experience, latest_output, status
|
||
, had_done, score, tag_count, power, record, next_game, grade, picture,
|
||
sets_error_count, last_compile_output, record_consume_time } = response;
|
||
|
||
const { game } = this.state;
|
||
const currentGamePassed = this.props.game !== 2 && status === 2
|
||
// 评测通过了,立即同步costTime
|
||
currentGamePassed && this._updateCostTime(true, true);
|
||
const output_sets = {
|
||
"test_sets": test_sets,
|
||
"test_sets_array": test_sets,
|
||
"had_test_count": had_test_count || test_sets_count,
|
||
"test_sets_count": test_sets_count,
|
||
// "had_passed_testsests_error_count": had_passed_testsests_error_count,
|
||
"had_passed_testsests_error_count": test_sets_count - sets_error_count,
|
||
"test_sets_hidden_count": test_sets_hidden_count,
|
||
"test_sets_public_count": test_sets_public_count,
|
||
"had_passed_testsests_hidden_count": had_passed_testsests_hidden_count,
|
||
"had_passed_testsests_public_count": had_passed_testsests_public_count
|
||
};
|
||
// 检查是否编译通过
|
||
let compileSuccess = false;
|
||
if (test_sets && test_sets.length) {
|
||
test_sets.some((item) => {
|
||
if (item.compile_success) {
|
||
compileSuccess = true;
|
||
return true;
|
||
}
|
||
})
|
||
}
|
||
|
||
compileSuccess && this.language_display(response);
|
||
if (currentGamePassed) {
|
||
game.status = 2;
|
||
// game.isPassThrough = true
|
||
game.next_game = next_game;
|
||
} else {
|
||
this.showDialog({
|
||
contentText: <div>
|
||
<div>评测未通过</div>
|
||
<div>详情请参见“测试结果”</div>
|
||
</div>,
|
||
isSingleButton: true
|
||
})
|
||
}
|
||
|
||
|
||
this.setState({
|
||
testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态
|
||
currentGamePassed,
|
||
currentPassedGameGainGold: gold,
|
||
currentPassedGameGainExperience: experience,
|
||
|
||
output_sets,
|
||
game,
|
||
next_game,
|
||
|
||
latest_output: last_compile_output,
|
||
record: record_consume_time,
|
||
grade,
|
||
had_done,
|
||
|
||
})
|
||
}
|
||
resetTestSetsExpandedArray = () => {
|
||
this.setState({
|
||
testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态
|
||
})
|
||
}
|
||
|
||
testSetUnlock() {
|
||
const { game, challenge } = this.state;
|
||
const url = `/tasks/${game.identifier}/check_test_sets.json`
|
||
axios.get(url)
|
||
.then((response) => {
|
||
// TODO status -2 重复操作,直接解锁
|
||
if (response.data.test_sets == -1) {
|
||
console.error('testSetUnlock失败!')
|
||
this.showSnackbar(response.data.message)
|
||
return;
|
||
} else {
|
||
// 被扣除的金币,是负数
|
||
const deltaScore = -challenge.score * 5;
|
||
let { output_sets } = this.state;
|
||
output_sets = Object.assign({}, output_sets);
|
||
output_sets.test_sets_array = response.data.test_sets;
|
||
this.setState({
|
||
output_sets: output_sets,
|
||
grade: this.state.grade + deltaScore,
|
||
game: update(game, { test_sets_view: { $set: true } }),
|
||
testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0)
|
||
})
|
||
this.handleGdialogClose();
|
||
}
|
||
|
||
})
|
||
.catch(function (error) {
|
||
console.log(error);
|
||
});
|
||
}
|
||
|
||
handleSnackbarClose() {
|
||
this.setState({
|
||
snackbarOpen: false,
|
||
snackbarVertical: '',
|
||
snackbarHorizontal: '',
|
||
})
|
||
}
|
||
// 全局的snackbar this.props.showSnackbar调用即可
|
||
showSnackbar(text, vertical, horizontal) {
|
||
this.setState({
|
||
snackbarOpen: true,
|
||
snackbarText: text,
|
||
snackbarVertical: vertical,
|
||
snackbarHorizontal: horizontal,
|
||
})
|
||
}
|
||
|
||
showDialog(params) {
|
||
const { contentText, callback, moreButtonsRender, okButtonText, isSingleButton } = params;
|
||
|
||
this.dialogOkCallback = callback;
|
||
this.moreButtonsRender = moreButtonsRender
|
||
this.okButtonText = okButtonText;
|
||
this.isSingleButton = isSingleButton;
|
||
this.setState({
|
||
gDialogOpen: true,
|
||
gDialogContentText: contentText
|
||
})
|
||
}
|
||
onGdialogOkBtnClick() {
|
||
|
||
this.dialogOkCallback && this.dialogOkCallback();
|
||
}
|
||
handleGdialogClose = () => {
|
||
this.setState({
|
||
gDialogOpen: false
|
||
})
|
||
}
|
||
render() {
|
||
const { classes } = this.props;
|
||
return (
|
||
<TPIContext.Provider
|
||
value={{
|
||
...this.props,
|
||
...this.state,
|
||
resetTestSetsExpandedArray: this.resetTestSetsExpandedArray,
|
||
onRunCodeTestFinish: this.onRunCodeTestFinish,
|
||
onRunChooseTestFinish: this.onRunChooseTestFinish,
|
||
testSetUnlock: this.testSetUnlock,
|
||
|
||
onTestSetHeaderClick: this.onTestSetHeaderClick,
|
||
|
||
readGameAnswer: this.readGameAnswer,
|
||
|
||
onShowPrevStage: this.onShowPrevStage,
|
||
onShowNextStage: this.onShowNextStage,
|
||
|
||
praisePlus: this.praisePlus,
|
||
onGamePassed: this.onGamePassed,
|
||
closeTaskResultLayer: () => this.closeTaskResultLayer(),
|
||
|
||
onPathChange: this.onPathChange,
|
||
updateChallengePath: this.updateChallengePath,
|
||
|
||
showSnackbar: this.showSnackbar,
|
||
showDialog: this.showDialog,
|
||
handleGdialogClose: () => this.handleGdialogClose(),
|
||
|
||
onShowUpdateDialog: this.onShowUpdateDialog,
|
||
updateDialogClose: this.updateDialogClose,
|
||
|
||
match: this.props.match
|
||
}}
|
||
>
|
||
<Dialog
|
||
id="tpi-dialog"
|
||
open={this.state.gDialogOpen}
|
||
disableEscapeKeyDown={true}
|
||
onClose={() => this.handleGdialogClose()}
|
||
>
|
||
<DialogTitle id="alert-dialog-title">{"提示"}</DialogTitle>
|
||
<DialogContent id="dialog-content">
|
||
<DialogContentText id="alert-dialog-description" style={{ textAlign: 'center' }}>
|
||
{this.state.gDialogContentText}
|
||
</DialogContentText>
|
||
</DialogContent>
|
||
{/* mb20 加了有样式问题 */}
|
||
<DialogActions className={""} id="dialog-actions">
|
||
{this.isSingleButton ? <div className="task-popup-submit clearfix"
|
||
style={{ textAlign: 'center', 'margin-bottom': '14px' }}>
|
||
<a className="task-btn task-btn-orange"
|
||
onClick={this.handleGdialogClose}
|
||
>知道啦</a>
|
||
</div> :
|
||
<React.Fragment>
|
||
<Button onClick={() => this.handleGdialogClose()} color="primary"
|
||
className={`${classes.button} ${classes.buttonGray} ${classes.borderRadiusNone}`}>
|
||
关闭
|
||
</Button>
|
||
<Button variant="raised" className={`${classes.button} ${classes.borderRadiusNone}`}
|
||
onClick={() => this.onGdialogOkBtnClick()} color="primary" autoFocus>
|
||
{this.okButtonText ? this.okButtonText : '确定'}
|
||
</Button>
|
||
</React.Fragment>}
|
||
{this.moreButtonsRender && this.moreButtonsRender()}
|
||
</DialogActions>
|
||
</Dialog>
|
||
|
||
<Snackbar
|
||
className={"rootSnackbar"}
|
||
open={this.state.snackbarOpen}
|
||
autoHideDuration={3000}
|
||
anchorOrigin={{
|
||
vertical: this.state.snackbarVertical || 'top'
|
||
, horizontal: this.state.snackbarHorizontal || 'center'
|
||
}}
|
||
onClose={() => this.handleSnackbarClose()}
|
||
transition={Fade}
|
||
SnackbarContentProps={{
|
||
'aria-describedby': 'message-id',
|
||
}}
|
||
resumeHideDuration={2000}
|
||
message={<span id="message-id">{this.state.snackbarText}</span>}
|
||
/>
|
||
{this.props.children}
|
||
</TPIContext.Provider>
|
||
)
|
||
}
|
||
}
|
||
|
||
export default CNotificationHOC()(withStyles(styles)(TPIContextProvider));
|
||
|
||
|
||
|