mirror of
https://gitlink.org.cn/Gitlink/forgeplus.git
synced 2026-05-07 21:51:42 +08:00
init project
This commit is contained in:
50
public/react/src/context/EffectDisplayContent.js
Normal file
50
public/react/src/context/EffectDisplayContent.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class EffectDisplayContent extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { typeName, content1, content2, content3 } = this.props;
|
||||
return (
|
||||
<div className="task-popup-content effectDisplay">
|
||||
<style>{`
|
||||
.effectDisplay .content_title {
|
||||
flex: 1 1 0
|
||||
}
|
||||
.effectDisplay .content>div {
|
||||
flex: 1
|
||||
}
|
||||
.effectDisplay .clappr, .effectDisplay .contentWrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.effectDisplay .clappr>div {
|
||||
width: 400px !important;
|
||||
}
|
||||
`}</style>
|
||||
<div className="clearfix df">
|
||||
{content1 && <p className="content_title edu-txt-center fl mr03precent font-18">原始{typeName}</p>}
|
||||
{content2 && <p className="content_title edu-txt-center fl font-18 mr03precent">实际输出{typeName}</p>}
|
||||
{content3 && <p className="content_title edu-txt-center fl font-18 mr03precent">预期输出{typeName}</p>}
|
||||
</div>
|
||||
<div className="clearfix df content" >
|
||||
{content1 && <div className="fl mr03precent pt10 mb50 contentWrap">
|
||||
{content1}
|
||||
</div>}
|
||||
{content2 && <div className="fl mr03precent pt10 mb50 contentWrap">
|
||||
{content2}
|
||||
</div>}
|
||||
{content3 && <div className="fl mr03precent pt10 mb50 contentWrap">
|
||||
{content3}
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EffectDisplayContent;
|
||||
251
public/react/src/context/EvaluateSuccessEffectDisplay.js
Normal file
251
public/react/src/context/EvaluateSuccessEffectDisplay.js
Normal file
@@ -0,0 +1,251 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import { Redirect } from 'react-router';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { Clappr } from 'educoder'
|
||||
import axios from 'axios';
|
||||
import EffectDisplayContent from './EffectDisplayContent'
|
||||
class EvaluateSuccessEffectDisplay extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps, newContext) {
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.type == 'html') {
|
||||
const iframe = document.getElementById('_displayIframe')
|
||||
if (iframe && iframe.contentWindow && this.props.iframe_src) {
|
||||
iframe.contentWindow.open()
|
||||
iframe.contentWindow.document.write(this.props.iframe_src);
|
||||
iframe.contentWindow.document.close();
|
||||
} else {
|
||||
console.error('not mounted')
|
||||
}
|
||||
}
|
||||
}
|
||||
hidepicture = () => {
|
||||
const dom = document.getElementById('picture_display');
|
||||
ReactDOM.unmountComponentAtNode(dom)
|
||||
// window.$('#picture_display').hide();
|
||||
|
||||
window.$('.data-tip-right').hide()
|
||||
}
|
||||
renderContent = () => {
|
||||
// qrcode
|
||||
// const type = 'image' // 'qrcode'
|
||||
const { type, qrcode_str,
|
||||
answer_picture, orignal_picture, user_picture, contents,
|
||||
user_file, answer_file, orignal_file } = this.props;
|
||||
if (type == 'qrcode') {
|
||||
// 单张图片,比如安卓评测完显示qrcode
|
||||
return (
|
||||
<div style={{ textAlign: 'center', paddingTop: '5%' }}>
|
||||
<p style={{ color: '#333', fontSize: '24px' }}>请使用Android手机浏览器扫码查看效果(暂不支持微信、QQ与支付宝扫一扫)</p>
|
||||
<p>
|
||||
{/* <img src="data:image/png;base64,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 +NIc7MmVogAAAABJRU5ErkJggg== ">
|
||||
</img> */}
|
||||
<img src={`data:image/png;base64,${qrcode_str}`}>
|
||||
</img>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (type == 'image') {
|
||||
return (
|
||||
<div className="task-popup-content">
|
||||
<div className="clearfix">
|
||||
{orignal_picture[0] && <p className="edu-txt-center fl with33 mr03precent font-18">原始图片</p>}
|
||||
<p className="edu-txt-center fl font-18 with33 mr03precent">实际输出图片</p>
|
||||
<p className="edu-txt-center fl font-18 with33 mr03precent">预期输出图片</p>
|
||||
</div>
|
||||
<div className="clearfix" id="picture-content">
|
||||
{orignal_picture[0] && <div className="fl with33 mr03precent pt10 mb50">
|
||||
{orignal_picture.map(item => {
|
||||
return (
|
||||
<img alt="Icon"
|
||||
src={ item.pic_url}/> )
|
||||
})}
|
||||
{/* {orignal_picture[0] && <img alt="Icon"
|
||||
src={ orignal_picture[0].pic_url}/>} */}
|
||||
</div>}
|
||||
<div className="fl with33 mr03precent pt10 mb50">
|
||||
{user_picture.map(item => {
|
||||
return (
|
||||
<img alt="Icon"
|
||||
src={ item.pic_url}/> )
|
||||
})}
|
||||
</div>
|
||||
<div className="fl with33 mr03precent pt10 mb50">
|
||||
{answer_picture.map(item => {
|
||||
return (
|
||||
<img alt="Icon"
|
||||
src={ item.pic_url}/> )
|
||||
})}
|
||||
{/* { answer_picture[0] && <img alt="Icon"
|
||||
src={ answer_picture[0].pic_url}/> } */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (type == "txt") {
|
||||
return (
|
||||
<div className="task-popup-content clearfix">
|
||||
<div className="with80" style={{margin: '0 auto'}}>
|
||||
<p className="color-blue font-18 mb20 edu-txt-center">实际输出</p>
|
||||
<textarea className="output-txt" readonly="" defaultValue={contents}></textarea>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else if (type == "html") {
|
||||
return (
|
||||
<iframe id="_displayIframe"></iframe>
|
||||
)
|
||||
} else if (type == 'mp3') {
|
||||
return (
|
||||
<EffectDisplayContent
|
||||
typeName="音频"
|
||||
content1={ orignal_file[0] && orignal_file[0].file_url
|
||||
? <Clappr source={orignal_file[0].file_url} id="1" className="clappr" type="mp3"></Clappr> : null }
|
||||
content2={ user_file[0] && user_file[0].file_url
|
||||
? <Clappr source={user_file[0].file_url} id="2" className="clappr" type="mp3"></Clappr> : null }
|
||||
content3={ answer_file[0] && answer_file[0].file_url
|
||||
? <Clappr source={answer_file[0].file_url} id="3" className="clappr" type="mp3"></Clappr> : null }
|
||||
></EffectDisplayContent>
|
||||
)
|
||||
} else if (type == 'mp4') {
|
||||
return (
|
||||
<EffectDisplayContent
|
||||
typeName="视频"
|
||||
content1={ orignal_file[0] && orignal_file[0].file_url
|
||||
? <Clappr source={orignal_file[0].file_url} id="1" className="clappr" type="mp4"></Clappr> : null }
|
||||
content2={ user_file[0] && user_file[0].file_url
|
||||
? <Clappr source={user_file[0].file_url} id="2" className="clappr" type="mp4"></Clappr> : null }
|
||||
content3={ answer_file[0] && answer_file[0].file_url
|
||||
? <Clappr source={answer_file[0].file_url} id="3" className="clappr" type="mp4"></Clappr> : null }
|
||||
></EffectDisplayContent>
|
||||
)
|
||||
}
|
||||
|
||||
/* <div className="with49 fr">
|
||||
<p className="font-18 mb20 edu-txt-center">预期输出</p>
|
||||
<textarea className="output-txt"></textarea>
|
||||
</div> */
|
||||
|
||||
}
|
||||
render() {
|
||||
const { tpmLoading } = this.props;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<style>
|
||||
{`
|
||||
.task-popup-content {
|
||||
overflow-y: auto;
|
||||
padding-bottom: 55px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
iframe#_displayIframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div className="photo_display">
|
||||
<div className="task-popup">
|
||||
<div className="task-popup-title clearfix">
|
||||
<h3 className="fl color-grey3 mt4">查看效果</h3>
|
||||
<a href="javascript:void(0);" onClick={this.hidepicture}
|
||||
data-tip-left="关闭查看效果" className="pop_close fr">
|
||||
<i className="fa fa-times-circle font-18 link-color-grey mt5"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{ this.renderContent() }
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EvaluateSuccessEffectDisplay;
|
||||
|
||||
// const qrcode_str = "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\nDsg/oT4AK5IwWw0AAAAASUVORK5CYII=\n"
|
||||
|
||||
const content = `
|
||||
AUC值为:0.9786487367132528
|
||||
你的得分为:782.9189893706023
|
||||
你的处理结果如下:
|
||||
id type
|
||||
155 9 0
|
||||
273 13 1
|
||||
1236 15 1
|
||||
618 18 1
|
||||
851 20 1
|
||||
64 24 1
|
||||
366 27 0
|
||||
42 30 1
|
||||
1468 31 1
|
||||
1059 32 0
|
||||
1311 33 1
|
||||
217 34 1
|
||||
486 44 1
|
||||
796 46 1
|
||||
505 48 1
|
||||
661 52 1
|
||||
1455 53 0
|
||||
514 62 0
|
||||
43 66 1
|
||||
930 69 0
|
||||
393 70 0
|
||||
574 71 1
|
||||
1175 74 1
|
||||
99 80 1
|
||||
441 81 1
|
||||
71 85 1
|
||||
971 89 1
|
||||
361 91 1
|
||||
449 94 1
|
||||
517 96 0
|
||||
... ... ...
|
||||
1031 4901 1
|
||||
1065 4902 0
|
||||
153 4903 1
|
||||
1141 4910 1
|
||||
1028 4916 1
|
||||
1021 4917 1
|
||||
272 4918 1
|
||||
809 4919 1
|
||||
557 4921 0
|
||||
1017 4922 1
|
||||
313 4924 1
|
||||
529 4926 1
|
||||
1350 4929 1
|
||||
891 4933 1
|
||||
989 4940 1
|
||||
1213 4941 1
|
||||
821 4943 1
|
||||
939 4955 1
|
||||
1470 4962 1
|
||||
1158 4963 1
|
||||
38 4967 1
|
||||
609 4969 1
|
||||
425 4976 1
|
||||
836 4982 1
|
||||
1387 4989 1
|
||||
927 4991 0
|
||||
417 4996 1
|
||||
428 4997 1
|
||||
752 4999 1
|
||||
1148 5000 1
|
||||
|
||||
[1500 rows x 2 columns]`
|
||||
4
public/react/src/context/TPIContext.js
Normal file
4
public/react/src/context/TPIContext.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
const TPIContext = React.createContext('tpi')
|
||||
|
||||
export default TPIContext;
|
||||
969
public/react/src/context/TPIContextProvider.js
Normal file
969
public/react/src/context/TPIContextProvider.js
Normal file
@@ -0,0 +1,969 @@
|
||||
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).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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// praise_tread/praise_plus?obj_id=569&obj_type=Challenge&horizontal=true&game_praise=true
|
||||
/*
|
||||
TODO 旧的接口在未登录时的返回值
|
||||
//获取登录页面地址
|
||||
var signinPath = '/';
|
||||
var htmlvalue = '<div class="task-popup" style="width:480px;"><div class="task-popup-title clearfix"><h3 class="fl color-grey3">提示</h3></div>'+
|
||||
'<div class="task-popup-content"><p class="task-popup-text-center font-16 mt10 mb10">您还没有登录,请登录后再执行此操作,谢谢!</p></div><div class="task-popup-right-sure clearfix">'+
|
||||
'<a href="javascript:void(0);" onclick="hideModal();" class="task-btn">取消</a><a href="' + signinPath + '" class="task-btn task-btn-orange ml15">登录</a></div></div>';
|
||||
pop_box_new(htmlvalue, 480, 182);
|
||||
*/
|
||||
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: "/users/innov"
|
||||
*/
|
||||
let user = resData.user;
|
||||
user.username = resData.user.name;
|
||||
user.user_url = `/users/${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);
|
||||
|
||||
if (!stageId) {
|
||||
// stageId = 'zl6kx8f7vfpo';
|
||||
// http://localhost:3000/myshixuns/so5w6iap97/stages/zl6kx8f7vfpo
|
||||
}
|
||||
|
||||
// var url = `/api/v1/games/${stageId}`
|
||||
var url = `/tasks/${stageId}.json`
|
||||
// {"status":1,"message":"undefined method `authenticate!' for #<Grape::Endpoint:0xc8c91c0>"}
|
||||
window.__fetchAllFlag = true;
|
||||
|
||||
|
||||
this.setState({
|
||||
loading: true,
|
||||
currentGamePassed: false, // 切换game时重置passed字段
|
||||
})
|
||||
|
||||
// test
|
||||
// var data = {"st":0,"discusses_count":0,"game_count":3,"record_onsume_time":0.36,"prev_game":null,"next_game":"7p9xwo2hklqv","praise_count":0,"user_praise":false,"time_limit":20,"tomcat_url":"http://47.96.157.89","is_teacher":false,"myshixun_manager":true,"game":{"id":2192828,"myshixun_id":580911,"user_id":57844,"created_at":"2019-09-03T15:50:49.000+08:00","updated_at":"2019-09-03T15:51:05.000+08:00","status":2,"final_score":0,"challenge_id":10010,"open_time":"2019-09-03T15:50:49.000+08:00","identifier":"hknvz4oaw825","answer_open":0,"end_time":"2019-09-03T15:51:04.000+08:00","retry_status":0,"resubmit_identifier":null,"test_sets_view":false,"picture_path":null,"accuracy":1.0,"modify_time":"2019-09-03T15:23:33.000+08:00","star":0,"cost_time":14,"evaluate_count":1,"answer_deduction":0},"challenge":{"id":10010,"shixun_id":3516,"subject":"1.1 列表操作","position":1,"task_pass":"[TOC]\n\n---\n\n####任务描述\n\n\n数据集a包含1-10共10个整数,请以a为输入数据,编写python程序,实现如下功能:\n①\t用2种方法输出a中所有奇数\n②\t输出大于3,小于7的偶数\n③\t用2种方法输出[1,2,3,…10,11,…20]\n④\t输出a的最大值、最小值。\n⑤\t用2种方法输出[10,9,…2,1]\n⑥\t输出[1,2,3,1,2,3,1,2,3,1,2,3]\n\n\n####相关知识\n\n\n请自行学习相关知识\n\n\n---\n开始你的任务吧,祝你成功!","score":100,"path":"1-1-stu.py","st":0,"web_route":null,"modify_time":"2019-09-03T15:23:33.000+08:00","exec_time":20,"praises_count":0},"shixun":{"id":3516,"name":"作业1——Python程序设计","user_id":77620,"gpid":null,"visits":23,"created_at":"2019-09-03T14:18:17.000+08:00","updated_at":"2019-09-03T15:58:16.000+08:00","status":0,"language":null,"authentication":false,"identifier":"6lzjig58","trainee":1,"major_id":null,"webssh":2,"homepage_show":false,"hidden":false,"fork_from":null,"can_copy":true,"modify_time":"2019-09-03T14:18:17.000+08:00","reset_time":"2019-09-03T14:18:17.000+08:00","publish_time":null,"closer_id":null,"end_time":null,"git_url":null,"vnc":null,"myshixuns_count":3,"challenges_count":3,"use_scope":0,"mirror_script_id":20,"image_text":null,"code_hidden":false,"task_pass":true,"exec_time":20,"test_set_permission":true,"sigle_training":false,"hide_code":false,"multi_webssh":false,"excute_time":null,"repo_name":"p09218567/6lzjig58","averge_star":5.0,"opening_time":null,"users_count":1,"forbid_copy":false,"pod_life":0},"myshixun":{"id":580911,"shixun_id":3516,"is_public":true,"user_id":57844,"gpid":null,"created_at":"2019-09-03T15:50:49.000+08:00","updated_at":"2019-09-03T15:59:04.000+08:00","status":0,"identifier":"k36hm4rwav","commit_id":"f25e1713882156480fc45ce0af57eff395a5037f","modify_time":"2019-09-03T14:18:17.000+08:00","reset_time":"2019-09-03T14:18:17.000+08:00","system_tip":false,"git_url":null,"onclick_time":"2019-09-03T15:50:49.000+08:00","repo_name":"p53276410/k36hm4rwav20190903155049"},"user":{"user_id":57844,"login":"p53276410","name":"文振乾","grade":24624,"identity":1,"image_url":"avatars/User/57844","school":"EduCoder团队"},"tpm_modified":true,"tpm_cases_modified":false,"mirror_name":["Python3.6"],"has_answer":false,"test_sets":[{"is_public":true,"result":true,"input":"","output":"result of a:\n[1, 3, 5, 7, 9]\n[1, 3, 5, 7, 9]\nresult of b:\n[2, 4, 6, 8, 10]\nresult of c:\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\nresult of d:\nThe minimum is:1\nThe maxium is:10\nresult of e:\n[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nresult of f:\n[10, 9, 8, 10, 9, 8, 10, 9, 8, 10, 9, 8]\n","actual_output":"result of a:\r\n[1, 3, 5, 7, 9]\r\n[1, 3, 5, 7, 9]\r\nresult of b:\r\n[2, 4, 6, 8, 10]\r\nresult of c:\r\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\r\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\r\nresult of d:\r\nThe minimum is:1\r\nThe maxium is:10\r\nresult of e:\r\n[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]\r\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\r\nresult of f:\r\n[10, 9, 8, 10, 9, 8, 10, 9, 8, 10, 9, 8]\r\n","compile_success":1,"ts_time":0.05,"ts_mem":8.77}],"allowed_unlock":true,"last_compile_output":"compile successfully","test_sets_count":1,"sets_error_count":0}
|
||||
// data.test_sets[0].actual_output = data.test_sets[0].actual_output.replace(/\r\n/g, '\n')
|
||||
// data.test_sets[0].output = data.test_sets[0].output.replace(/\r\n/g, '\n')
|
||||
// console.log(JSON.stringify(data))
|
||||
// data.shixun.vnc = true
|
||||
// data.vnc_url= "http://47.96.157.89:41158/vnc_lite.html?password=headless"
|
||||
|
||||
// this._handleResponseData(data)
|
||||
// return
|
||||
|
||||
axios.get(url, {
|
||||
// https://stackoverflow.com/questions/48861290/the-value-of-the-access-control-allow-origin-header-in-the-response-must-not-b
|
||||
// withCredentials: true,
|
||||
})
|
||||
.then((response) => {
|
||||
// {"status":1,"message":"Unauthorized. \u7528\u6237\u8ba4\u8bc1\u5931\u8d25."}
|
||||
|
||||
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) {
|
||||
// var $result = $("#php_display");
|
||||
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(challenge.isAndroid && data.picture != 0){
|
||||
// // https://www.educoder.net/shixuns/qrcode?game_id=218589&_=1525571882782
|
||||
// $.ajax({
|
||||
// url: `/shixuns/qrcode?game_id=${game.id}`,
|
||||
// dataType: 'script'
|
||||
// });
|
||||
// challenge.showLanguagePictrue = true;
|
||||
// }
|
||||
else if(data.picture != 0){
|
||||
// 对应服务端erb文件为 _picture_display.html.erb
|
||||
// $.ajax({
|
||||
// url: "/users/picture_show?game_id="+data.picture,
|
||||
// cache: false,
|
||||
// dataType: 'script'
|
||||
// });
|
||||
|
||||
/**
|
||||
{
|
||||
"type": "image",
|
||||
"orignal_picture": [],
|
||||
"user_picture": [],
|
||||
"answer_picture": []
|
||||
}
|
||||
*/
|
||||
const url = `/tasks/${game.identifier}/picture_display.json`
|
||||
axios.get(url)
|
||||
.then((response) => {
|
||||
// response.data.type qrcode_str
|
||||
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
|
||||
};
|
||||
// if (output_sets && output_sets.test_sets) {
|
||||
// const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]");
|
||||
// output_sets.test_sets_array = test_sets_array;
|
||||
// }
|
||||
|
||||
// 检查是否编译通过
|
||||
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, {
|
||||
// withCredentials: true,
|
||||
})
|
||||
.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;
|
||||
// output_sets
|
||||
let { output_sets } = this.state;
|
||||
output_sets = Object.assign({}, output_sets);
|
||||
// const test_sets_array = JSON.parse("[" + response.data.test_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,
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
TODO 写成HOC组件,更好复用
|
||||
全局的Dialog this.props.showDialog调用即可
|
||||
@param contentText dialog显示的提示文本
|
||||
@param callback 确定按钮回调方法
|
||||
@param moreButtonsRender 除了“确定”、“取消”按钮外的其他按钮
|
||||
@param okButtonText “确定”按钮显示文本,如 继续查看
|
||||
*/
|
||||
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();
|
||||
// this.setState({
|
||||
// gDialogOpen: true
|
||||
// })
|
||||
}
|
||||
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));
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user