fix monaco-editor

dev_aliyun2
harry 5 years ago
parent a691b82a7e
commit afadd23dfd

@ -313,16 +313,10 @@ $(function(){
window.top.__updateWebsshRows && window.top.__updateWebsshRows(rows)
}
window.refresh_editor_monaco = function(height) {
console.log('refresh_editor_monaco')
if (window.editor_monaco) {
height && $('#codetab_con_1').height(height)
window.editor_monaco.layout();
}
// if ($('#game_operate_action').width() < 720) {
// $('#game_operate_action .time_limit').hide()
// } else {
// $('#game_operate_action .time_limit').show()
// }
}
// end;
//解決IE瀏覽器大小改變時webssh佈局變亂。

@ -206,16 +206,6 @@ class TPIContextProvider extends Component {
}
// 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;
@ -308,13 +298,6 @@ pop_box_new(htmlvalue, 480, 182);
// 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
}
@ -645,34 +628,10 @@ pop_box_new(htmlvalue, 480, 182);
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)
})
@ -842,9 +801,6 @@ pop_box_new(htmlvalue, 480, 182);
onGdialogOkBtnClick() {
this.dialogOkCallback && this.dialogOkCallback();
// this.setState({
// gDialogOpen: true
// })
}
handleGdialogClose = () => {
this.setState({
@ -852,7 +808,6 @@ pop_box_new(htmlvalue, 480, 182);
})
}
render() {
const { classes } = this.props;
return (
<TPIContext.Provider
value={{
@ -901,11 +856,11 @@ pop_box_new(htmlvalue, 480, 182);
>知道啦</a>
</div> :
<React.Fragment>
<Button onClick={() => this.handleGdialogClose()} color="primary"
className={`${classes.button} ${classes.buttonGray} ${classes.borderRadiusNone}`}>
<Button onClick={() => this.handleGdialogClose()} color="primary">
关闭
</Button>
<Button variant="raised" className={`${classes.button} ${classes.borderRadiusNone}`}
<Button variant="raised"
onClick={() => this.onGdialogOkBtnClick()} color="primary" autoFocus>
{this.okButtonText ? this.okButtonText : '确定'}
</Button>

@ -13,9 +13,6 @@ class ShixunCustomsPass extends Component {
}
}
componentDidMount() {
}
editgame_scores = (e, id, maxsum, code_rate, copy_user_id) => {
let { datas } = this.state;
@ -182,17 +179,6 @@ class ShixunCustomsPass extends Component {
</span>
),
}];
// {
// title: '调分',
// key: 'adjustmentminute',
// dataIndex: 'adjustmentminute',
//
// render: (text, record) => (
// <span>
// <a>6小时 50分钟 6秒</a>
// </span>
// ),
// },
if (this.props.isAdmin() === false) {

@ -20,36 +20,9 @@ function updateCodeMirror() {
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");
@ -82,52 +55,6 @@ function check_hide() {
}
}
/*评测等待通知*/
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;
@ -167,17 +94,6 @@ class MainContentContainer extends Component {
mainContentfun = (Ref) => {
this.mainContent = Ref;
}
// ------------------------------------------------
// static childContextTypes = {
// muiTheme: PropTypes.object
// }
// getChildContext() {
// return {
// muiTheme: getMuiTheme()
// }
// }
// ------------------------------------------------
handleClose = () => {
this.setState({ open: false });
};
@ -198,11 +114,6 @@ class MainContentContainer extends Component {
|| (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) {
next_game = newProps.next_game;
@ -354,13 +265,6 @@ class MainContentContainer extends Component {
// 异常 直接重试
this.fetchRepositoryCode(props, null, null, true)
} else {
var editor_monaco = window.editor_monaco;
if (path && path.endsWith('.py')) {
editor_monaco.getModel().updateOptions({ insertSpaces: true })
} else {
editor_monaco.getModel().updateOptions({ insertSpaces: false })
}
this.setState({ isEditablePath, currentPath: path });
this.oldRepositoryCode = ((fetchRepositoryCodeResponse.data.content === true || !fetchRepositoryCodeResponse.data.content)
? '' : fetchRepositoryCodeResponse.data.content);
@ -436,7 +340,6 @@ class MainContentContainer extends Component {
}
this.autoSaveInterval = setInterval(() => {
// code变化时每30秒保存到数据库没变化则不处理
var autoSave = true
var fileUpdatePromise = this.doFileUpdateRequest(true)
if (fileUpdatePromise) {
fileUpdatePromise.then((resData) => {
@ -453,16 +356,8 @@ class MainContentContainer extends Component {
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) {
@ -514,19 +409,11 @@ class MainContentContainer extends Component {
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 && window.editor_monaco.getModel()) { // (编程切选择题) 如果dispose了model为空
codeContent = window.editor_monaco.getValue()
}
if (checkIfCodeChanged === true && this.oldRepositoryCode == codeContent) {
// console.log('code not changed');
this.setState({
@ -551,23 +438,14 @@ class MainContentContainer extends Component {
} 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
}
)
}

@ -18,7 +18,7 @@ const firstDrawerWidth = 260;
class VNCContainer extends Component {
constructor(props) {
super(props)
this.state = {
fileTreeSelectedKeys: [],
repositoryCode: '',
@ -46,7 +46,6 @@ class VNCContainer extends Component {
return $('#game_right_contents').width() - firstDrawerWidth
}
onEditBlur = () => {
console.log('blurblur')
this.doFileUpdateRequestOnCodeMirrorBlur()
}
doFileUpdateRequestOnCodeMirrorBlur = () => {
@ -58,18 +57,18 @@ class VNCContainer extends Component {
var url = `/myshixuns/${myshixun.identifier}/update_file.json`
const codeContent = window.editor_monaco.getValue()
this.setState({saving: true})
this.setState({ saving: true })
axios.post(url, {
content: codeContent,
// 评测的时候传1其它情况不用传主要是为了区分是用户自己提交还是自动提交
// evaluate: 0,
game_id : game.id,
path: this.currentPath
}
content: codeContent,
// 评测的时候传1其它情况不用传主要是为了区分是用户自己提交还是自动提交
// evaluate: 0,
game_id: game.id,
path: this.currentPath
}
).then(res => {
this.setState({saving: false})
this.setState({ saving: false })
}).catch(e => {
this.setState({saving: false})
this.setState({ saving: false })
console.error('update_file error')
})
}
@ -80,35 +79,35 @@ class VNCContainer extends Component {
const isEditablePath = false;
return (
<Spin tip={saving ? "保存中..." : "加载中..."} spinning={readingCodeLoading || saving}>
<div style={{ height: `${height}px` }}>
{/* (isEditablePath ? 'none' : 'block') */}
<div className="codemirrorBackground"
style={{ backgroundImage: `url('${notEditablePathImg}')`, display: (shixun.code_edit_permission ? 'none' : 'block') }}></div>
<TPIMonaco
{...this.state}
codeLoading={readingCodeLoading}
repositoryCode={repositoryCode}
isEditablePath={shixun.code_edit_permission}
shixun={this.props.shixun}
doFileUpdateRequestOnCodeMirrorBlur={this.doFileUpdateRequestOnCodeMirrorBlur}
onEditBlur={this.onEditBlur}
></TPIMonaco>
</div>
</Spin>);
<Spin tip={saving ? "保存中..." : "加载中..."} spinning={readingCodeLoading || saving}>
<div style={{ height: `${height}px` }}>
{/* (isEditablePath ? 'none' : 'block') */}
<div className="codemirrorBackground"
style={{ backgroundImage: `url('${notEditablePathImg}')`, display: (shixun.code_edit_permission ? 'none' : 'block') }}></div>
<TPIMonaco
{...this.state}
codeLoading={readingCodeLoading}
repositoryCode={repositoryCode}
isEditablePath={shixun.code_edit_permission}
shixun={this.props.shixun}
doFileUpdateRequestOnCodeMirrorBlur={this.doFileUpdateRequestOnCodeMirrorBlur}
onEditBlur={this.onEditBlur}
></TPIMonaco>
</div>
</Spin>);
}
fetchReadRepositoryCode = (path) => {
this.currentPath = path;
const status = 1
const fetchRepoCodeUrl = `/tasks/${this.props.game.identifier}/rep_content.json?path=${path}&status=${status}`
this.setState({ readingCodeLoading: true });
axios.get(fetchRepoCodeUrl, {
}).then((fetchReadRepositoryCodeResponse) => {
axios.get(fetchRepoCodeUrl, {
}).then((fetchReadRepositoryCodeResponse) => {
if (fetchReadRepositoryCodeResponse.data.content || fetchReadRepositoryCodeResponse.data.content == "") {
this.setState({
this.setState({
repositoryCode: fetchReadRepositoryCodeResponse.data.content,
readingCodeLoading: false
})
@ -117,11 +116,11 @@ class VNCContainer extends Component {
}
// this.setState({ isEditablePath, currentPath: path });
}).catch(error =>{
console.log(error)
}).catch(error => {
console.log(error)
this.setState({ readingCodeLoading: false });
this.props.showSnackbar(`服务端异常,请联系管理员!`);
})
})
}
onTreeSelect = (selectedKeys, info) => {
const isLeaf = info.node.isLeaf();
@ -136,12 +135,12 @@ class VNCContainer extends Component {
if (nodePath) {
const filetype = nodePath.split('.').pop().toLowerCase();
if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg'
|| filetype == 'jar' || filetype == 'exe'
|| filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
|| filetype == 'jar' || filetype == 'exe'
|| filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
this.props.showSnackbar(`不支持加载${filetype}类型的文件。`)
return;
}
this.fetchReadRepositoryCode(nodePath);
this.fetchReadRepositoryCode(nodePath);
} else {
console.error('no eventKey:', info.node)
}
@ -162,7 +161,7 @@ class VNCContainer extends Component {
// 请确保您的数据已保存(如:版本库代码已推送到服务器)
// 是否确认重置?
this.props.confirm({
content: <div style={{textAlign: 'center'}}>
content: <div style={{ textAlign: 'center' }}>
<div>桌面系统将恢复到初始状态您在系统中创建的数据可能会丢失</div>
<div>请确保您的数据已保存版本库代码已推送到服务器</div>
<div>是否确认重置</div>
@ -183,7 +182,7 @@ class VNCContainer extends Component {
}
// this.setState({ isEditablePath, currentPath: path });
}).catch(error =>{
}).catch(error => {
console.log(error)
this.setState({ vnc_reseting: false });
this.props.showSnackbar(`服务端异常,请联系管理员!`);
@ -196,36 +195,36 @@ class VNCContainer extends Component {
},
})
}
/*
selectedKeys={fileTreeSelectedKeys}
onSelect={onTreeSelect}
*/
render() {
const { challenge, vnc_url, git_url, showOrHide, isCollapse } = this.props
render() {
const { challenge, vnc_url, git_url, showOrHide, isCollapse } = this.props
const _classCtx = this.state.bottomDrawer ? 'btn_test_case_active' : 'btn_test_case';
const _classes = this.state.bottomDrawer
? `iconfont icon-xiajiantou btn-arrow`
: 'iconfont icon-shangjiantou btn-arrow';
const _classCtx = this.state.bottomDrawer ? 'btn_test_case_active' : 'btn_test_case';
const _classes = this.state.bottomDrawer
? `iconfont icon-xiajiantou btn-arrow`
: 'iconfont icon-shangjiantou btn-arrow';
const secondDrawerChildren = this.renderSecondDrawerChildren();
const _drawClasses = showOrHide
const _drawClasses = showOrHide
? ('codeEvaluateDrawer code_evaluate_stretch')
: (isCollapse ? 'codeEvaluateDrawer active' : 'codeEvaluateDrawer');
return (
<React.Fragment>
<SecondDrawer
return (
<React.Fragment>
<SecondDrawer
ref="secondDrawer"
floatText={'版本库'}
floatText={'版本库'}
maskClosable={false}
secondDrawerChildren={secondDrawerChildren}
secondDrawerChildren={secondDrawerChildren}
firstDrawerWidth={firstDrawerWidth}
getSecondDrawerWidth={this.getSecondDrawerWidth}
firstDrawerClassName="repoFilesDrawer vncDrawer"
secondDrawerClassName="codeInDrawer"
>
>
<style>{`
/* 评测结果 */
.codeEvaluateDrawer{
@ -370,8 +369,8 @@ class VNCContainer extends Component {
<div style={{ color: '#888888' }}>网址克隆</div>
<div>
<input value={git_url} readonly={true} style={{ color: '#BABABA', width: '203px', background: 'transparent', border: 'none' }}></input>
<i class="iconfont icon-fuzhi font-14 ml10 copybtn"
style={{color: '#4CACFF', cursor: 'pointer', verticalAlign: 'baseline'}} data-clipboard-text={git_url} ></i>
<i class="iconfont icon-fuzhi font-14 ml10 copybtn"
style={{ color: '#4CACFF', cursor: 'pointer', verticalAlign: 'baseline' }} data-clipboard-text={git_url} ></i>
</div>
</div>
<RepoTree
@ -381,26 +380,26 @@ class VNCContainer extends Component {
></RepoTree>
</SecondDrawer>
{/* <FloatButton className="resetVNC" onClick={this.onResetVNC}>
{/* <FloatButton className="resetVNC" onClick={this.onResetVNC}>
{this.state.vnc_reseting ? <Icon type="loading" style={{verticalAlign: 'sub'}} />
: <i className="iconfont icon-zhongzhi2 font-16 "></i>}
<span>重置桌面系统</span>
</FloatButton> */}
<FloatButton className="resetVNC1" onClick={this.onResetVNC}>
{this.state.vnc_reseting ? <Icon type="loading" style={{verticalAlign: 'sub'}} />
: <i className="iconfont icon-zhongzhi2 font-24"></i>}
{this.state.vnc_reseting ? <Icon type="loading" style={{ verticalAlign: 'sub' }} />
: <i className="iconfont icon-zhongzhi2 font-24"></i>}
<span>重置实训</span>
</FloatButton>
{/* <Spin tip="..." spinning={this.state.vnc_reseting}>
{/* <Spin tip="..." spinning={this.state.vnc_reseting}>
</Spin> */}
<VNCDisplay
{...this.props}
<VNCDisplay
{...this.props}
key={this.state.displayKey}
vnc_url={this.state.vnc_url || this.props.vnc_url}
>
>
<Spin tip="加载中..." spinning={this.state.vnc_reseting}>
</Spin>
<Drawer
@ -420,10 +419,10 @@ class VNCContainer extends Component {
const canvas = $('.vncDisply canvas')[0]
canvas && canvas.focus()
}
}}
>
{ this.props.codeEvaluate }
{this.props.codeEvaluate}
</Drawer>
{/* <FloatButton onClick={this.swtichBottomDrawer}
className="codeEvaluateFloatButton"
@ -432,15 +431,15 @@ class VNCContainer extends Component {
className={_classCtx}
onClick={this.swtichBottomDrawer}
> */}
{/* <span className="iconfont icon-shangjiantou btn-arrow"></span> */}
{/* <span className={_classes}></span> */}
{/* <span className="iconfont icon-shangjiantou btn-arrow"></span> */}
{/* <span className={_classes}></span> */}
{/* </div> */}
</VNCDisplay>
</React.Fragment>
);
}
</React.Fragment>
);
}
}
const mapStateToProps = (state) => {

@ -66,46 +66,9 @@ class TPICodeSetting extends Component {
</div>
</div>
</div>
{/* <div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">代码补全</div>
<div className="ide-settings--item-value">
<div className="select -view-flat -value">
<div className="-layout-v -start">
<div className="select--wrapper -layout-h -center -justify" >
<Switch
checked={autoCompleteSwitch}
onChange={onAutoCompleteSwitchChange}
value="checkedB"
color="primary"
/>
</div>
</div>
</div>
</div>
</div> */}
{/*<div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">Auto-brackets</div>
<div className="ide-settings--item-value">
<div className="select -view-flat -value">
<div className="-layout-v -start">
<div className="select--wrapper -layout-h -center -justify" >
4
</div>
</div>
</div>
</div>
</div>*/}
</div>
<h3 className="ide-settings--section -light ">快捷键</h3>
<div className="-padding-24 ">
{/*<div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">CTRL + Enter</div>
<div className="ide-settings--item-value">Submit Solution</div>
</div>*/}
{/* <div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">ALT + /</div>
<div className="ide-settings--item-value">代码补全</div>
</div> */}
<div className="-layout-h -center -justify-between">
<div className="ide-settings--item-key">保存代码</div>
<div className="ide-settings--item-value">Ctrl + S</div>
@ -134,7 +97,6 @@ class TPICodeSetting extends Component {
<h3 className="ide-settings--section -light ">
关卡配置信息
{/* <a href="https://github.com/Microsoft/monaco-editor/wiki/Monaco-Editor-Accessibility-Guide"></a> */}
</h3>
<div className="-padding-24 " style={{ marginBottom: '40px' }}>
<Tooltip title={task_pass ? "允许学员跳关挑战" : "不允许学员跳关挑战"} disableFocusListener={true}>

@ -108,7 +108,7 @@ class UpdateDrawer extends Component {
updateDialogClose();
}
render() {
const { showUpdateDialog, classes } = this.props;
const { showUpdateDialog } = this.props;
const { loading } = this.state;
const { tpm_cases_modified, tpm_modified, tpm_script_modified, challenge } = this.props;
let needUpdateScript = (tpm_modified || tpm_script_modified) && challenge.st === 0;
@ -125,17 +125,17 @@ class UpdateDrawer extends Component {
<React.Fragment >
<Button
disabled={loading}
className={"nextUpdate " + classes.button + ' ' + classes.buttonGray} onClick={() => this.onNextUpdate(tpm_cases_modified)} color="primary" >
className={"nextUpdate "} onClick={() => this.onNextUpdate(tpm_cases_modified)} color="primary" >
稍后再说
</Button>
<Button
disabled={loading}
variant="raised" onClick={() => this.onUpdateNow(tpm_cases_modified)} color="primary" className={"updateNow " + classes.button}>
variant="raised" onClick={() => this.onUpdateNow(tpm_cases_modified)} color="primary" className={"updateNow "}>
立即更新
</Button>
{loading && <p>正在加载中...</p>}
</ React.Fragment> :
<Button onClick={() => this.onCasesModified()} color="primary" className={"nextUpdate " + classes.button}>
<Button onClick={() => this.onCasesModified()} color="primary" className={"nextUpdate "}>
知道啦
</Button>

@ -206,7 +206,6 @@ class WebSSHTimer extends Component {
})
}
render() {
const { myshixun, showUpdateDialog, classes } = this.props;
const { showTimer, loading, dialogOpen } = this.state;
return (
@ -220,12 +219,12 @@ class WebSSHTimer extends Component {
footer={[
<Button
disabled={loading}
className={"nextUpdate " + classes.button + ' ' + classes.buttonGray} onClick={() => this.onNope()} color="primary" >
className={"nextUpdate "} onClick={() => this.onNope()} color="primary" >
不需要
</Button>
, <Button
disabled={loading}
variant="raised" onClick={() => this.onOK()} color="primary" className={"updateNow " + classes.button}>
variant="raised" onClick={() => this.onOK()} color="primary" className={"updateNow "}>
立即延长
</Button>

@ -1,160 +1,432 @@
.monaco-editor .minimap-slider, .monaco-editor .minimap-slider .minimap-slider-horizontal { background: rgba(121, 121, 121, 0.2); }
.monaco-editor .minimap-slider:hover, .monaco-editor .minimap-slider:hover .minimap-slider-horizontal { background: rgba(100, 100, 100, 0.35); }
.monaco-editor .minimap-slider.active, .monaco-editor .minimap-slider.active .minimap-slider-horizontal { background: rgba(191, 191, 191, 0.2); }
.monaco-editor .minimap-shadow-visible { box-shadow: #000000 -6px 0 6px -6px inset; }
.monaco-editor .scroll-decoration { box-shadow: #000000 0 6px 6px -6px inset; }
.monaco-editor .focused .selected-text { background-color: #264f78; }
.monaco-editor .selected-text { background-color: #3a3d41; }
.monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input { background-color: #1e1e1e; }
.monaco-editor, .monaco-editor .inputarea.ime-input { color: #d4d4d4; }
.monaco-editor .margin { background-color: #1e1e1e; }
.monaco-editor .rangeHighlight { background-color: rgba(255, 255, 255, 0.04); }
.vs-whitespace { color: rgba(227, 228, 226, 0.16) !important; }
.monaco-editor .view-overlays .current-line { border: 2px solid #282828; }
.monaco-editor .margin-view-overlays .current-line-margin { border: 2px solid #282828; }
.monaco-editor .lines-content .cigr { box-shadow: 1px 0 0 0 #404040 inset; }
.monaco-editor .lines-content .cigra { box-shadow: 1px 0 0 0 #707070 inset; }
.monaco-editor .line-numbers { color: #858585; }
.monaco-editor .current-line ~ .line-numbers { color: #c6c6c6; }
.monaco-editor .view-ruler { box-shadow: 1px 0 0 0 #5a5a5a inset; }
.monaco-editor .cursor { background-color: #aeafad; border-color: #aeafad; color: #515052; }
.monaco-editor .squiggly-error { background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23ea4646'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left; }
.monaco-editor .squiggly-warning { background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%234d9e4d'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left; }
.monaco-editor .squiggly-info { background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23008000'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left; }
.monaco-editor .squiggly-hint { background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%223%22%20width%3D%2212%22%3E%3Cg%20fill%3D%22rgba(238%2C%20238%2C%20238%2C%200.7)%22%3E%3Ccircle%20cx%3D%221%22%20cy%3D%221%22%20r%3D%221%22%2F%3E%3Ccircle%20cx%3D%225%22%20cy%3D%221%22%20r%3D%221%22%2F%3E%3Ccircle%20cx%3D%229%22%20cy%3D%221%22%20r%3D%221%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") no-repeat bottom left; }
.showUnused .monaco-editor .squiggly-inline-unnecessary { opacity: 0.667; }
.monaco-diff-editor .diff-review-line-number { color: #858585; }
.monaco-diff-editor .diff-review-shadow { box-shadow: #000000 0 -6px 6px -6px inset; }
.monaco-editor .line-insert, .monaco-editor .char-insert { background-color: rgba(155, 185, 85, 0.2); }
.monaco-diff-editor .line-insert, .monaco-diff-editor .char-insert { background-color: rgba(155, 185, 85, 0.2); }
.monaco-editor .inline-added-margin-view-zone { background-color: rgba(155, 185, 85, 0.2); }
.monaco-editor .line-delete, .monaco-editor .char-delete { background-color: rgba(255, 0, 0, 0.2); }
.monaco-diff-editor .line-delete, .monaco-diff-editor .char-delete { background-color: rgba(255, 0, 0, 0.2); }
.monaco-editor .inline-deleted-margin-view-zone { background-color: rgba(255, 0, 0, 0.2); }
.monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px #000000; }
.monaco-editor .bracket-match { background-color: rgba(0, 100, 0, 0.1); }
.monaco-editor .bracket-match { border: 1px solid #888888; }
.monaco-editor .codelens-decoration { color: #999999; }
.monaco-editor .codelens-decoration > a:hover { color: #4e94ce !important; }
.monaco-editor .findOptionsWidget { background-color: #252526; }
.monaco-editor .findOptionsWidget { box-shadow: 0 2px 8px #000000; }
.monaco-editor .findMatch { background-color: rgba(234, 92, 0, 0.33); }
.monaco-editor .currentFindMatch { background-color: #515c6a; }
.monaco-editor .findScope { background-color: rgba(58, 61, 65, 0.4); }
.monaco-editor .find-widget { background-color: #252526; }
.monaco-editor .find-widget { box-shadow: 0 2px 8px #000000; }
.monaco-editor .find-widget.no-results .matchesCount { color: #f48771; }
.monaco-editor .find-widget .monaco-sash { background-color: #454545; width: 3px !important; margin-left: -4px;}
.monaco-editor .find-widget .monaco-checkbox .checkbox:checked + .label { border: 1px solid #007acc; }
.monaco-editor.vs .valueSetReplacement { outline: solid 2px #888888; }
.monaco-editor .detected-link-active { color: #4e94ce !important; }
.monaco-editor .monaco-editor-overlaymessage .anchor { border-top-color: #007acc; }
.monaco-editor .monaco-editor-overlaymessage .message { border: 1px solid #007acc; }
.monaco-editor .monaco-editor-overlaymessage .message { background-color: #063b49; }
.monaco-editor .parameter-hints-widget { border: 1px solid #454545; }
.monaco-editor .parameter-hints-widget.multiple .body { border-left: 1px solid rgba(69, 69, 69, 0.5); }
.monaco-editor .parameter-hints-widget .signature.has-docs { border-bottom: 1px solid rgba(69, 69, 69, 0.5); }
.monaco-editor .parameter-hints-widget { background-color: #252526; }
.monaco-editor .parameter-hints-widget a { color: #3794ff; }
.monaco-editor .parameter-hints-widget code { background-color: rgba(10, 10, 10, 0.4); }
.monaco-editor .snippet-placeholder { background-color: rgba(124, 124, 124, 0.3); outline-color: transparent; }
.monaco-editor .finish-snippet-placeholder { background-color: transparent; outline-color: #525252; }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight { color: #0097fb; }
.monaco-editor .suggest-widget { color: #d4d4d4; }
.monaco-editor .suggest-widget a { color: #3794ff; }
.monaco-editor .suggest-widget code { background-color: rgba(10, 10, 10, 0.4); }
.monaco-editor .focused .selectionHighlight { background-color: rgba(173, 214, 255, 0.15); }
.monaco-editor .selectionHighlight { background-color: rgba(173, 214, 255, 0.07); }
.monaco-editor .wordHighlight { background-color: rgba(87, 87, 87, 0.72); }
.monaco-editor .wordHighlightStrong { background-color: rgba(0, 73, 114, 0.72); }
.monaco-editor .accessibilityHelpWidget { background-color: #252526; }
.monaco-editor .accessibilityHelpWidget { box-shadow: 0 2px 8px #000000; }
.monaco-editor .tokens-inspect-widget { border: 1px solid #454545; }
.monaco-editor .tokens-inspect-widget .tokens-inspect-separator { background-color: #454545; }
.monaco-editor .tokens-inspect-widget { background-color: #252526; }
.monaco-editor .reference-zone-widget .ref-tree .referenceMatch { background-color: rgba(234, 92, 0, 0.3); }
.monaco-editor .reference-zone-widget .preview .reference-decoration { background-color: rgba(255, 143, 0, 0.6); }
.monaco-editor .reference-zone-widget .ref-tree { background-color: #252526; }
.monaco-editor .reference-zone-widget .ref-tree { color: #bbbbbb; }
.monaco-editor .reference-zone-widget .ref-tree .reference-file { color: #ffffff; }
.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows > .monaco-list-row.selected:not(.highlighted) { background-color: rgba(51, 153, 255, 0.2); }
.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows > .monaco-list-row.selected:not(.highlighted) { color: #ffffff !important; }
.monaco-editor .reference-zone-widget .preview .monaco-editor .monaco-editor-background,.monaco-editor .reference-zone-widget .preview .monaco-editor .inputarea.ime-input { background-color: #001f33;}
.monaco-editor .reference-zone-widget .preview .monaco-editor .margin { background-color: #001f33;}
.monaco-editor .marker-widget a { color: #3794ff; }
.monaco-editor .hoverHighlight { background-color: rgba(38, 79, 120, 0.25); }
.monaco-editor .monaco-editor-hover { background-color: #252526; }
.monaco-editor .monaco-editor-hover { border: 1px solid #454545; }
.monaco-editor .monaco-editor-hover .hover-row:not(:first-child):not(:empty) { border-top: 1px solid rgba(69, 69, 69, 0.5); }
.monaco-editor .monaco-editor-hover hr { border-top: 1px solid rgba(69, 69, 69, 0.5); }
.monaco-editor .monaco-editor-hover hr { border-bottom: 0px solid rgba(69, 69, 69, 0.5); }
.monaco-editor .monaco-editor-hover a { color: #3794ff; }
.monaco-editor .monaco-editor-hover .hover-row .actions { background-color: #2c2c2d; }
.monaco-editor .monaco-editor-hover code { background-color: rgba(10, 10, 10, 0.4); }
.monaco-editor .goto-definition-link { color: #4e94ce !important; }
/* .mtk1 { color: #d4d4d4 !important; }
.mtk2 { color: #1e1e1e !important; }
.mtk3 { color: #cc6666 !important; }
.mtk4 { color: #9cdcfe !important; }
.mtk5 { color: #ce9178 !important; }
.mtk6 { color: #b5cea8 !important; }
.mtk7 { color: #608b4e !important; }
.mtk8 { color: #569cd6 !important; }
.mtk9 { color: #dcdcdc !important; }
.mtk10 { color: #808080 !important; }
.mtk11 { color: #f44747 !important; }
.mtk12 { color: #c586c0 !important; }
.mtk13 { color: #a79873 !important; }
.mtk14 { color: #dd6a6f !important; }
.mtk15 { color: #5bb498 !important; }
.mtk16 { color: #909090 !important; }
.mtk17 { color: #778899 !important; }
.mtk18 { color: #ff00ff !important; }
.mtk19 { color: #b46695 !important; }
.mtk20 { color: #ff0000 !important; }
.mtk21 { color: #4f76ac !important; }
.mtk22 { color: #3dc9b0 !important; }
.mtk23 { color: #74b0df !important; }
.mtk24 { color: #4864aa !important; } */
.mtki { font-style: italic; }
.mtkb { font-weight: bold; }
.mtku { text-decoration: underline; text-underline-position: under; }
.monaco-editor .minimap-slider,
.monaco-editor .minimap-slider .minimap-slider-horizontal {
background: rgba(121, 121, 121, 0.2);
}
.monaco-editor .minimap-slider:hover,
.monaco-editor .minimap-slider:hover .minimap-slider-horizontal {
background: rgba(100, 100, 100, 0.35);
}
.monaco-editor .minimap-slider.active,
.monaco-editor .minimap-slider.active .minimap-slider-horizontal {
background: rgba(191, 191, 191, 0.2);
}
.monaco-editor .minimap-shadow-visible {
box-shadow: #000000 -6px 0 6px -6px inset;
}
.monaco-editor .scroll-decoration {
box-shadow: #000000 0 6px 6px -6px inset;
}
.monaco-editor .focused .selected-text {
background-color: #264f78;
}
.monaco-editor .selected-text {
background-color: #3a3d41;
}
.monaco-editor,
.monaco-editor-background,
.monaco-editor .inputarea.ime-input {
background-color: #1e1e1e;
}
.monaco-editor,
.monaco-editor .inputarea.ime-input {
color: #d4d4d4;
}
.monaco-editor .margin {
background-color: #1e1e1e;
}
.monaco-editor .rangeHighlight {
background-color: rgba(255, 255, 255, 0.04);
}
.vs-whitespace {
color: rgba(227, 228, 226, 0.16) !important;
}
.monaco-editor .view-overlays .current-line {
border: 2px solid #282828;
}
.monaco-editor .margin-view-overlays .current-line-margin {
border: 2px solid #282828;
}
.monaco-editor .lines-content .cigr {
box-shadow: 1px 0 0 0 #404040 inset;
}
.monaco-editor .lines-content .cigra {
box-shadow: 1px 0 0 0 #707070 inset;
}
.monaco-editor .line-numbers {
color: #858585;
}
.monaco-editor .current-line~.line-numbers {
color: #c6c6c6;
}
.monaco-editor .view-ruler {
box-shadow: 1px 0 0 0 #5a5a5a inset;
}
.monaco-editor .cursor {
background-color: #aeafad;
border-color: #aeafad;
color: #515052;
}
.monaco-editor .squiggly-error {
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23ea4646'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;
}
.monaco-editor .squiggly-warning {
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%234d9e4d'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;
}
.monaco-editor .squiggly-info {
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23008000'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;
}
.monaco-editor .squiggly-hint {
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%223%22%20width%3D%2212%22%3E%3Cg%20fill%3D%22rgba(238%2C%20238%2C%20238%2C%200.7)%22%3E%3Ccircle%20cx%3D%221%22%20cy%3D%221%22%20r%3D%221%22%2F%3E%3Ccircle%20cx%3D%225%22%20cy%3D%221%22%20r%3D%221%22%2F%3E%3Ccircle%20cx%3D%229%22%20cy%3D%221%22%20r%3D%221%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") no-repeat bottom left;
}
.showUnused .monaco-editor .squiggly-inline-unnecessary {
opacity: 0.667;
}
.monaco-diff-editor .diff-review-line-number {
color: #858585;
}
.monaco-diff-editor .diff-review-shadow {
box-shadow: #000000 0 -6px 6px -6px inset;
}
.monaco-editor .line-insert,
.monaco-editor .char-insert {
background-color: rgba(155, 185, 85, 0.2);
}
.monaco-diff-editor .line-insert,
.monaco-diff-editor .char-insert {
background-color: rgba(155, 185, 85, 0.2);
}
.monaco-editor .inline-added-margin-view-zone {
background-color: rgba(155, 185, 85, 0.2);
}
.monaco-editor .line-delete,
.monaco-editor .char-delete {
background-color: rgba(255, 0, 0, 0.2);
}
.monaco-diff-editor .line-delete,
.monaco-diff-editor .char-delete {
background-color: rgba(255, 0, 0, 0.2);
}
.monaco-editor .inline-deleted-margin-view-zone {
background-color: rgba(255, 0, 0, 0.2);
}
.monaco-diff-editor.side-by-side .editor.modified {
box-shadow: -6px 0 5px -5px #000000;
}
.monaco-editor .bracket-match {
background-color: rgba(0, 100, 0, 0.1);
}
.monaco-editor .bracket-match {
border: 1px solid #888888;
}
.monaco-editor .codelens-decoration {
color: #999999;
}
.monaco-editor .codelens-decoration>a:hover {
color: #4e94ce !important;
}
.monaco-editor .findOptionsWidget {
background-color: #252526;
}
.monaco-editor .findOptionsWidget {
box-shadow: 0 2px 8px #000000;
}
.monaco-editor .findMatch {
background-color: rgba(234, 92, 0, 0.33);
}
.monaco-editor .currentFindMatch {
background-color: #515c6a;
}
.monaco-editor .findScope {
background-color: rgba(58, 61, 65, 0.4);
}
.monaco-editor .find-widget {
background-color: #252526;
}
.monaco-editor .find-widget {
box-shadow: 0 2px 8px #000000;
}
.monaco-editor .find-widget.no-results .matchesCount {
color: #f48771;
}
.monaco-editor .find-widget .monaco-sash {
background-color: #454545;
width: 3px !important;
margin-left: -4px;
}
.monaco-editor .find-widget .monaco-checkbox .checkbox:checked+.label {
border: 1px solid #007acc;
}
.monaco-editor.vs .valueSetReplacement {
outline: solid 2px #888888;
}
.monaco-editor .detected-link-active {
color: #4e94ce !important;
}
.monaco-editor .monaco-editor-overlaymessage .anchor {
border-top-color: #007acc;
}
.monaco-editor .monaco-editor-overlaymessage .message {
border: 1px solid #007acc;
}
.monaco-editor .monaco-editor-overlaymessage .message {
background-color: #063b49;
}
.monaco-editor .parameter-hints-widget {
border: 1px solid #454545;
}
.monaco-editor .parameter-hints-widget.multiple .body {
border-left: 1px solid rgba(69, 69, 69, 0.5);
}
.monaco-editor .parameter-hints-widget .signature.has-docs {
border-bottom: 1px solid rgba(69, 69, 69, 0.5);
}
.monaco-editor .parameter-hints-widget {
background-color: #252526;
}
.monaco-editor .parameter-hints-widget a {
color: #3794ff;
}
.monaco-editor .parameter-hints-widget code {
background-color: rgba(10, 10, 10, 0.4);
}
.monaco-editor .snippet-placeholder {
background-color: rgba(124, 124, 124, 0.3);
outline-color: transparent;
}
.monaco-editor .finish-snippet-placeholder {
background-color: transparent;
outline-color: #525252;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
color: #0097fb;
}
.monaco-editor .suggest-widget {
color: #d4d4d4;
}
.monaco-editor .suggest-widget a {
color: #3794ff;
}
.monaco-editor .suggest-widget code {
background-color: rgba(10, 10, 10, 0.4);
}
.monaco-editor .focused .selectionHighlight {
background-color: rgba(173, 214, 255, 0.15);
}
.monaco-editor .selectionHighlight {
background-color: rgba(173, 214, 255, 0.07);
}
.monaco-editor .wordHighlight {
background-color: rgba(87, 87, 87, 0.72);
}
.monaco-editor .wordHighlightStrong {
background-color: rgba(0, 73, 114, 0.72);
}
.monaco-editor .accessibilityHelpWidget {
background-color: #252526;
}
.monaco-editor .accessibilityHelpWidget {
box-shadow: 0 2px 8px #000000;
}
.monaco-editor .tokens-inspect-widget {
border: 1px solid #454545;
}
.monaco-editor .tokens-inspect-widget .tokens-inspect-separator {
background-color: #454545;
}
.monaco-editor .tokens-inspect-widget {
background-color: #252526;
}
.monaco-editor .reference-zone-widget .ref-tree .referenceMatch {
background-color: rgba(234, 92, 0, 0.3);
}
.monaco-editor .reference-zone-widget .preview .reference-decoration {
background-color: rgba(255, 143, 0, 0.6);
}
.monaco-editor .reference-zone-widget .ref-tree {
background-color: #252526;
}
.monaco-editor .reference-zone-widget .ref-tree {
color: #bbbbbb;
}
.monaco-editor .reference-zone-widget .ref-tree .reference-file {
color: #ffffff;
}
.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows>.monaco-list-row.selected:not(.highlighted) {
background-color: rgba(51, 153, 255, 0.2);
}
.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows>.monaco-list-row.selected:not(.highlighted) {
color: #ffffff !important;
}
.monaco-editor .reference-zone-widget .preview .monaco-editor .monaco-editor-background,
.monaco-editor .reference-zone-widget .preview .monaco-editor .inputarea.ime-input {
background-color: #001f33;
}
.monaco-editor .reference-zone-widget .preview .monaco-editor .margin {
background-color: #001f33;
}
.monaco-editor .marker-widget a {
color: #3794ff;
}
.monaco-editor .hoverHighlight {
background-color: rgba(38, 79, 120, 0.25);
}
.monaco-editor .monaco-editor-hover {
background-color: #252526;
}
.monaco-editor .monaco-editor-hover {
border: 1px solid #454545;
}
.monaco-editor .monaco-editor-hover .hover-row:not(:first-child):not(:empty) {
border-top: 1px solid rgba(69, 69, 69, 0.5);
}
.monaco-editor .monaco-editor-hover hr {
border-top: 1px solid rgba(69, 69, 69, 0.5);
}
.monaco-editor .monaco-editor-hover hr {
border-bottom: 0px solid rgba(69, 69, 69, 0.5);
}
.monaco-editor .monaco-editor-hover a {
color: #3794ff;
}
.monaco-editor .monaco-editor-hover .hover-row .actions {
background-color: #2c2c2d;
}
.monaco-editor .monaco-editor-hover code {
background-color: rgba(10, 10, 10, 0.4);
}
.monaco-editor .goto-definition-link {
color: #4e94ce !important;
}
.mtki {
font-style: italic;
}
.mtkb {
font-weight: bold;
}
.mtku {
text-decoration: underline;
text-underline-position: under;
}
#extend-challenge-file-edit {
height: 100%;
height: 100%;
}
/* context menu会有样式问题先给隐藏掉 */
.context-view {
display: none !important;
display: none !important;
}
/* 去掉灰色边框 */
#extend-challenge-file-edit {
border: none !important;
border: none !important;
}
/* 覆盖tpi样式 */
.monaco-tree .monaco-tree-rows > .monaco-tree-row > .content {
min-width: auto;
.monaco-tree .monaco-tree-rows>.monaco-tree-row>.content {
min-width: auto;
}
/* 选中行边框 */
.monaco-editor .view-overlays .current-line {
border-width: 1px !important;
}
/* .monaco-editor .margin,
.monaco-editor .margin-view-overlays{
width: 54px !important;
text-align: center !important;
}
.monaco-editor .monaco-scrollable-element{
left: 54px !important;
}
.monaco-editor .margin-view-overlays .line-numbers{
text-align: center !important;
} */
border-width: 1px !important;
}

@ -1,299 +1,88 @@
import React, { Component } from 'react';
import React, { Component } from 'react'
import { Drawer } from 'antd'
import MonacoEditor from './monaco-editor'
import _ from 'lodash'
import { Drawer } from 'antd';
import './TPIMonaco.css'
import TPICodeSetting from '../TPICodeSetting'
import * as monaco from 'monaco-editor'
import { fromStore, toStore } from 'educoder'
import './TPIMonacoConfig'
// https://microsoft.github.io/monaco-editor/playground.html#customizing-the-appearence-exposed-colors
monaco.editor.defineTheme('myCoolTheme', {
base: 'vs', // vs、vs-dark、hc-black
inherit: true,
rules: [
{ token: 'green', background: 'FF0000', foreground: '00FF00', fontStyle: 'italic' },
{ token: 'red', foreground: 'FF0000', fontStyle: 'bold underline' },
{ background: '#121c23' },
// { foreground: 'FFFFFF' }
],
colors: {
'editor.background': '#121c23',
'editor.lineHighlightBorder': '#222c34', // .current-line
}
});
const $ = window.$;
function loadMonacoResouce(callback) {
if (!window['monaco']) {
callback && callback()
var editor = monaco.editor.create(document.getElementById('container'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('\n'),
language: 'javascript'
});
// });
} else {
callback && callback()
}
}
function checkIfLoaded(callback) {
if (window.monaco && window.monaco.editor) {
$.ajaxSetup({
cache: false
});
callback && callback()
} else {
console.log('check again 2s later..')
setTimeout(() => {
checkIfLoaded(callback)
}, 2000);
}
}
const mirror2LanguageMap = {
'JFinal': 'java',
'Java': 'java',
'JavaWeb': 'java',
'Kotlin': 'java',
'Html': 'html',
'Css': 'css',
'Javascript': 'javascript',
'JavaScript': 'javascript',
'C/C++': 'cpp',
'MachineLearning': 'python',
'Python2.7': 'python',
'Python3.6': 'python',
'C#': 'csharp',
'R': 'r'
}
function getLanguageByMirrorName(mirror_name) {
let lang = 'javascript'
if (mirror_name && mirror_name.length) {
// 需要倒着遍历, html、css的实训主评测语言环境是python小类别是html或css
// TODO http://localhost:3007/tasks/hmcwa3g8typ5?debug=t ["Python3.6", "VNC", "Html"]
for (let i = mirror_name.length - 1; i >= 0; i--) {
let languageVal = mirror2LanguageMap[mirror_name[i]];
if (languageVal) {
lang = languageVal;
break;
}
}
}
return lang;
}
let notCallCodeMirrorOnChangeFlag = false;
/**
props :
mirror_name 决定语言
isEditablePath
repositoryCode
codemirrorDidMount
shixun.forbid_copy
showSettingDrawer, settingDrawerOpen
*/
class TPIMonaco extends Component {
constructor(props) {
super(props)
loadMonacoResouce();
this.state = {
cmFontSize: fromStore('cmFontSize', 16),
cmCodeMode: fromStore('cmCodeMode', 'vs-dark'),
autoCompleteSwitch: fromStore('autoCompleteSwitch', true),
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
const { mirror_name } = this.props
const editor_monaco = this.editor_monaco;
if (editor_monaco && !_.isEqual(prevProps.mirror_name, mirror_name)) {
// TODO 后期考虑加入根据文件类型的不同使用不同的lang
const lang = getLanguageByMirrorName(mirror_name);
// https://github.com/Microsoft/monaco-editor/issues/539
window.monaco.editor.setModelLanguage(editor_monaco.getModel(), lang)
} else if (prevProps.isEditablePath != this.props.isEditablePath) {
// 当前文件是否可编辑
if (this.props.isEditablePath || this.props.shixun && this.props.shixun.code_edit_permission == true) {
editor_monaco.updateOptions({ readOnly: false })
} else {
editor_monaco.updateOptions({ readOnly: true })
}
} else if (editor_monaco && prevProps.codeLoading === true && this.props.codeLoading === false
) {
if (this.props.repositoryCode != editor_monaco.getValue()) {
// newProps.repositoryCode !== this.props.repositoryCode &&
notCallCodeMirrorOnChangeFlag = true;
// 重要setState(因获取代码、重置代码等接口引起的调用)调用引起的变化才需要setValue
editor_monaco.setValue(this.props.repositoryCode)
}
// 代码没变也需要layout可能从命令行自动切回了代码tab
editor_monaco.layout();
// Clears the editor's undo history.
// TODO
// extend_editor.clearHistory()
}
editor_monaco.layout();
}
componentWillUnmount() {
// 注意销毁不然会出现不能编辑的bug
this.editor_monaco && this.editor_monaco.dispose()
}
componentDidMount() {
checkIfLoaded(() => {
let value = [
'define([], function() {',
'\treturn ({p1, p2}) => {',
'\t\treturn Promise.resolve("Hello, World");',
'\t};',
'});'
].join('\n');
// value = [
// 'function x() {',
// '\tconsole.log("Hello world!");',
// '}'
// ].join('\n'),
value = "<h1>Hello</h1>↵<!-- ********* Begin ********* -->↵ ↵ ↵<!-- ********* End ********* -->"
value = this.props.repositoryCode
const height = $('#games_repository_contents').height() - 40
const width = $('#games_repository_contents').width()
$('#codetab_con_1').height(height)
const lang = getLanguageByMirrorName(this.props.mirror_name);
const editor = window.monaco.editor.create(document.getElementById('extend-challenge-file-edit'), {
value: value,
readOnly: !this.props.isEditablePath && this.props.shixun && this.props.shixun.code_edit_permission != true,
// 属性说明
// http://testeduplus2.educoder.net/react/build/static/node_modules/_monaco-editor@0.15.6@monaco-editor/esm/vs/editor/common/config/commonEditorConfig.js
// https://github.com/Microsoft/monaco-editor/issues/29
scrollBeyondLastLine: false,
language: lang,
// language: 'css',
// theme: "vs",
theme: this.state.cmCodeMode,
// theme: 'myCoolTheme',
insertSpaces: false,
fontSize: this.state.cmFontSize,
// theme: this.state.cdCodeMode
});
window.editor_monaco = editor;
this.editor_monaco = editor
// editor.setPosition({ lineNumber: 2, column: 30 });
// editor.model.onDidChangeContent((event) => {
// if (notCallCodeMirrorOnChangeFlag === true) {
// notCallCodeMirrorOnChangeFlag = false
// return;
// }
// this.props.onRepositoryCodeUpdate(editor.getValue())
// });
editor.onDidChangeModelContent((event) => {
if (notCallCodeMirrorOnChangeFlag === true) {
notCallCodeMirrorOnChangeFlag = false
return;
}
this.props.onRepositoryCodeUpdate && this.props.onRepositoryCodeUpdate(editor.getValue())
})
this.props.codemirrorDidMount && this.props.codemirrorDidMount()
if (this.props.shixun && this.props.shixun.forbid_copy == true) {
// 禁用粘贴
// https://github.com/Microsoft/monaco-editor/issues/100
window.editor_monaco.onDidPaste((a, b, c) => { window.__pastePosition = a })
window.addEventListener('paste', (a, b, c) => {
const selection = window.editor_monaco.getSelection();
const range = new monaco.Range(
window.__pastePosition.startLineNumber || selection.endLineNumber,
window.__pastePosition.startColumn || selection.endColumn,
window.__pastePosition.endLineNumber || selection.endLineNumber,
window.__pastePosition.endColumn || selection.endColumn);
window.editor_monaco.executeEdits('', [{ range, text: '' }])
})
// 禁用复制
window.editor_monaco.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_C, () => null);
window.editor_monaco.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_V, () => null);
}
setTimeout(() => {
editor.layout();
editor.focus();
}, 600)
window.editor_monaco.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => {
this.props.doFileUpdateRequestOnCodeMirrorBlur();
return false;
});
window.editor_monaco.onDidBlurEditorWidget(() => {
this.props.onEditBlur && this.props.onEditBlur();
})
})
// window.document.onkeydown = (e) => {
// e = window.event || e;
// if(e.keyCode== 83 && e.ctrlKey){
// /*延迟兼容FF浏览器 */
// // setTimeout(function(){
// // alert('ctrl+s');
// // },1);
// this.props.doFileUpdateRequestOnCodeMirrorBlur();
// return false;
// }
// };
this.onSetEditor = this.onSetEditor.bind(this)
}
onFontSizeChange = (value) => {
toStore('cmFontSize', value)
this.setState({ cmFontSize: value });
this.editor_monaco.updateOptions({ fontSize: value })
}
onCodeModeChange = (value) => {
toStore('cmCodeMode', value);
this.setState({ cmCodeMode: value });
window.monaco.editor.setTheme(value);
toStore('cmCodeMode', value)
this.setState({ cmCodeMode: value })
}
onAutoCompleteSwitchChange = () => {
onSetEditor(instance, monaco) {
const { codemirrorDidMount, shixun, doFileUpdateRequestOnCodeMirrorBlur, onEditBlur } = this.props
if (codemirrorDidMount) { codemirrorDidMount(instance) }
if (shixun && shixun.forbid_copy) {
instance.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_C, () => null)
instance.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_V, () => null)
instance.onDidPaste(a => { window.__pastePosition = a })
window.addEventListener('paste', () => {
const selection = instance.getSelection();
const range = new monaco.Range(
window.__pastePosition.startLineNumber || selection.endLineNumber,
window.__pastePosition.startColumn || selection.endColumn,
window.__pastePosition.endLineNumber || selection.endLineNumber,
window.__pastePosition.endColumn || selection.endColumn);
instance.executeEdits('', [{ range, text: '' }])
})
}
if (doFileUpdateRequestOnCodeMirrorBlur) {
instance.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => {
doFileUpdateRequestOnCodeMirrorBlur()
return false
})
}
if (onEditBlur) {
instance.onDidBlurEditorWidget(() => {
onEditBlur()
})
}
}
render() {
const { repositoryCode, showSettingDrawer, settingDrawerOpen } = this.props;
const { cmFontSize } = this.state;
const { repositoryCode, showSettingDrawer, shixun, isEditablePath, settingDrawerOpen, mirror_name } = this.props;
const { cmFontSize, cmCodeMode } = this.state
const editorOptions = {
value: repositoryCode,
language: mirror_name,
options: {
readOnly: !isEditablePath && shixun && shixun.code_edit_permission != true,
scrollBeyondLastLine: false,
},
theme: cmCodeMode,
insertSpaces: false,
fontSize: cmFontSize,
onChange: (value) => { if (onRepositoryCodeUpdate) { onRepositoryCodeUpdate(value) } },
editorDidMount: this.onSetEditor
}
return (
<React.Fragment>
@ -311,8 +100,7 @@ class TPIMonaco extends Component {
onAutoCompleteSwitchChange={this.onAutoCompleteSwitchChange}
></TPICodeSetting>
</Drawer>
<div className="" id="extend-challenge-file-edit" name="content"
style={{ width: '100%', height: '100%', border: '1px solid grey' }}></div>
<MonacoEditor {...editorOptions} />
</React.Fragment>
);
}

@ -1,5 +1,5 @@
import * as monaco from 'monaco-editor'
import _ from 'lodash'
import { union } from 'lodash'
const ifelse = {
label: 'ifelse',
kind: monaco.languages.CompletionItemKind.Snippet,
@ -16,7 +16,7 @@ const ifelse = {
function getWordsInString(string) {
return string.match(/[A-z]+/g);
return string.match(/[A-z]+/g)
}
const cArray = ['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', 'else', 'enum', 'extern',
@ -27,7 +27,7 @@ const cArray = ['auto', 'break', 'case', 'char', 'const', 'continue', 'default',
monaco.languages.registerCompletionItemProvider('cpp', {
provideCompletionItems: (model) => {
const currentFileWords = getWordsInString(model.getValue());
const all = _.union(cArray, currentFileWords)
const all = union(cArray, currentFileWords)
var suggestions = all.map((item) => {
return {
label: item,
@ -50,7 +50,7 @@ const pythonArray = ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'c
monaco.languages.registerCompletionItemProvider('python', {
provideCompletionItems: (model) => {
const currentFileWords = getWordsInString(model.getValue());
const all = _.union(pythonArray, currentFileWords)
const all = union(pythonArray, currentFileWords)
var suggestions = all.map((item) => {
return {
label: item,

@ -0,0 +1,173 @@
import React, { useEffect, useRef, useState } from 'react'
import * as monaco from 'monaco-editor'
import './TPIMonacoConfig'
import './TPIMonaco.css'
import './monaco-editor.less'
function processSize(size) {
return !/^\d+$/.test(size) ? size : `${size}px`
}
function noop() { }
let __prevent_trigger_change_event = false
function debounce(func, wait, immediate) {
var timeout
return function () {
var context = this, args = arguments
var later = function () {
timeout = null
if (!immediate) func.apply(context, args)
};
var callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, wait)
if (callNow) func.apply(context, args)
}
}
const mirror2LanguageMap = {
'JFinal': 'java',
'Java': 'java',
'JavaWeb': 'java',
'Kotlin': 'java',
'Html': 'html',
'Css': 'css',
'Javascript': 'javascript',
'JavaScript': 'javascript',
'C/C++': 'cpp',
'MachineLearning': 'python',
'Python2.7': 'python',
'Python3.6': 'python',
'C#': 'csharp',
'R': 'r'
}
function getLanguageByMirrorName(mirror_name) {
let lang = 'javascript'
if (mirror_name && mirror_name.length) {
// htmlcsspythonhtmlcss
for (let i = mirror_name.length - 1; i >= 0; i--) {
let languageVal = mirror2LanguageMap[mirror_name[i]]
if (languageVal) {
lang = languageVal
break
}
}
}
return lang
}
export default ({
width = '100%',
height = '100%',
value,
language = 'javascript',
options = {},
overrideServices = {},
theme = 'vs-dark',
onChange = noop,
editorDidMount = noop
}) => {
const editorEl = useRef()
const editor = useRef({})
const [init, setInit] = useState(false)
useEffect(() => {
editor.current.instance = monaco.editor.create(
editorEl.current, {
value,
language: getLanguageByMirrorName(language),
theme,
...options
},
overrideServices
)
editorDidMount(editor.current.instance, monaco)
editor.current.subscription = editor.current.instance.onDidChangeModelContent(event => {
if (!__prevent_trigger_change_event) {
onChange(editor.current.instance.getValue(), event);
}
})
setInit(true)
const resizeHandler = debounce(() => { editor.current.instance.layout() }, 100)
window.addEventListener('resize', resizeHandler)
return () => {
const el = editor.current.instance
el.dispose()
const model = el.getModel()
if (model) {
model.dispose()
}
if (editor.current.subscription) {
editor.current.subscription.dispose()
}
window.removeEventListener('resize', resizeHandler)
}
}, [editorEl.current])
useEffect(() => {
let instance = editor.current.instance
if (instance && init) {
__prevent_trigger_change_event = true
const model = instance.getModel()
instance.pushUndoStop()
model.pushEditOperations(
[],
[
{
range: model.getFullModelRange(),
text: value
}
]
)
instance.pushUndoStop();
__prevent_trigger_change_event = false;
}
}, [value, init])
useEffect(() => {
let instance = editor.current.instance
if (instance && init) {
monaco.editor.setModelLanguage(instance.getModel(), getLanguageByMirrorName(language))
}
}, [language, init])
useEffect(() => {
let instance = editor.current.instance
if (instance && init) {
monaco.editor.setTheme(theme)
}
}, [theme, init])
useEffect(() => {
let instance = editor.current.instance
if (instance && init) {
instance.updateOptions(options)
}
}, [options, init])
useEffect(() => {
let instance = editor.current.instance
if (instance && init) {
instance.layout()
}
}, [width, height, init])
const fixedWidth = processSize(width)
const fixedHeight = processSize(height)
const style = {
width: fixedWidth,
height: fixedHeight
}
return (
<div ref={editorEl} style={style} id="extend-challenge-file-edit" name="content" ></div>
)
}

@ -0,0 +1,5 @@
#extend-challenge-file-edit {
width: '100%';
height: '100%';
border: '1px solid grey';
}

@ -14,10 +14,9 @@ class ActionView extends Component {
}
/*<span className="mt10 -flex c_grey ml15" id="time-consuming">耗时0 天 3 小时 11 分钟 57 秒 </span>*/
render() {
const { onRunCodeTest, onShowPrevStage, onShowNextStage, gameBuilding
, game, classes, st, shixun, record, challenge, time_limit, real_time_limit } = this.props;
const { onRunCodeTest, gameBuilding
, game, st, shixun, record, challenge, time_limit, real_time_limit } = this.props;
console.log(shixun)
return (
<div className="-flex -layout-h" id="game_operate_action">
<style>{`
@ -59,7 +58,7 @@ class ActionView extends Component {
{/*将第一个按钮改为visibility方式隐藏不然加载时测评按钮会出现没有垂直居中的情况*/}
<Tooltip title={"倒计时为0时服务将被关闭"}>
<Button size="small" className={classes.button + ' actionViewfirstButton'} onClick={() => this.showWebDisplay(challenge)}
<Button size="small" className={' actionViewfirstButton'} onClick={() => this.showWebDisplay(challenge)}
style={{
visibility: challenge.showWebDisplayButton ? '' : 'hidden',
minWidth: challenge.showWebDisplayButton ? '' : '1px',
@ -76,8 +75,8 @@ class ActionView extends Component {
{
!gameBuilding &&
(game && !!game.prev_game) ?
<Link to={`/tasks/${game.prev_game}`} className={classes.buttonText + ' act_btn'}>
<Button size="small" className={classes.button}>
<Link to={`/tasks/${game.prev_game}`} className={' act_btn'}>
<Button size="small" >
上一关
</Button>
</Link>
@ -86,8 +85,8 @@ class ActionView extends Component {
{/*未发布的都能跳转*/}
{!gameBuilding &&
((game && (game.status === 2 || shixun.status < 2) || shixun && shixun.task_pass) && !!game.next_game) ?
<Link to={`/tasks/${game.next_game}`} className={classes.buttonText + ' act_btn'}>
<Button size="small" className={classes.button}>
<Link to={`/tasks/${game.next_game}`} className={' act_btn'}>
<Button size="small" >
下一关
</Button>
</Link>

@ -173,7 +173,7 @@ class CodeEvaluateView extends Component {
testSetsComponentArray.push(
<div className="-task-ces-top clearfix" onClick={this.onTestSetHeaderClick.bind(this, index)}
style={{ cursor: 'pointer', 'margin-top': index == 0 ? '4px' : '' }} key={index + '-0'}>
style={{ cursor: 'pointer', 'marginTop': index == 0 ? '4px' : '' }} key={index + '-0'}>
<p className="clearfix">
<i className={`fa ${'fa-caret-right'} mr8 font-16`}
style={isExpanded ? { transform: 'rotate(90deg)' } : {}}></i>
@ -197,7 +197,7 @@ class CodeEvaluateView extends Component {
<div>{`解锁本关所有测试集需要扣除${challenge.score * 5}金币,确定要解锁吗?`}</div>
<div onClick={() => this.goToCertification()} style={{
color: '#4CACFF', cursor: 'pointer', 'text-decoration': 'underline'
, 'margin-top': '12px'
, 'marginTop': '12px'
}}>立即认证</div>
</React.Fragment> :
<React.Fragment>

@ -23,7 +23,7 @@ class LeftView extends Component {
render() {
let { challenge, shixun, tabIndex, tabIndexChange, loading, discusses_count
, dialogOpen, handleDialogClose, handleDialogReadAnswer, gameAnswer, loadingComments, st, user,
classes, onDrawerButtonClick, lockedAnswers, unlockedAnswers, isMultiLevelAnswer } = this.props
onDrawerButtonClick, lockedAnswers, unlockedAnswers, isMultiLevelAnswer } = this.props
let propaedeutics = shixun ? shixun.propaedeutics : null;
let _hasAnswer = challenge.hasAnswer // st === 1 ||
@ -77,11 +77,10 @@ class LeftView extends Component {
onCancel={handleDialogClose}
footer={[
<Button onClick={handleDialogClose} color="primary" className={`${classes.button} ${classes.buttonGray}`}>
<Button onClick={handleDialogClose} color="primary" >
取消
</Button>,
<Button size="medium" variant={"raised"}
className={`${classes.button} `}
onClick={() => handleDialogReadAnswer(this.refs.answerUnlock ? this.refs.answerUnlock.getSelectedId() : '')}
color="primary" autoFocus>
{is_teacher ? '继续查看' : '确定'}
@ -101,7 +100,7 @@ class LeftView extends Component {
{loading ? "" :
<React.Fragment>
<Tooltip title={"点击查看全部任务"} disableFocusListener={true}>
<Button color="default" mini={''} aria-label="edit" className={classes.iconButton}
<Button color="default" mini={''} aria-label="edit"
onClick={onDrawerButtonClick}>
<i className={"fa font-18 fa-list-ul"}></i>
</Button>

@ -26,35 +26,12 @@ class LeftViewContainer extends Component {
this.handleDialogClose = this.handleDialogClose.bind(this)
this.handleDialogReadAnswer = this.handleDialogReadAnswer.bind(this)
// ------------------------------------
// this.createNewComment = this.createNewComment.bind(this)
// this.fetchCommentIfNotFetched = this.fetchCommentIfNotFetched.bind(this)
// this.replyComment = this.replyComment.bind(this)
// this.deleteComment = this.deleteComment.bind(this)
// this.commentPraise = this.commentPraise.bind(this)
// this.hiddenComment = this.hiddenComment.bind(this)
// this.rewardCode = this.rewardCode.bind(this)
this.showNewReply = this.showNewReply.bind(this)
// ------------------------------------
// this.onPaginationChange = this.onPaginationChange.bind(this)
this.state = {
tabIndex: 0,
dialogOpen: false,
gameAnswer: '',
// 评论
// comments: [],
// comment_count_without_reply: 0,
// // 默认pageSize为10
// currentPage: 1,
// loadingComments: true,
// gotNewReply: false,
}
}
// ----------------------------------------------------------------------------------------------评论 Start
@ -189,9 +166,6 @@ class LeftViewContainer extends Component {
flowChart: false, // 默认不解析
sequenceDiagram: false, // 默认不解析
// onload : function(){
// this.previewing(); // 注释了这个后另一个md的onload previewing也不触发了
// }
});
window.knowledge_md = this.knowledge_md
} else {
@ -221,10 +195,6 @@ class LeftViewContainer extends Component {
this.previewing();
console.error(e)
}
// 改动了editormd源码codemirror对象存在的话就不重新加载codemirror脚本避免merge被覆盖掉
// window.editormd.loadScript("js/merge.js", function() {
// });
}
});
window.__task_md = this.task_md;
@ -323,13 +293,6 @@ class LeftViewContainer extends Component {
dialogOpen: unlockedAnswers.length === 0,
isMultiLevelAnswer: newAnswers.length > 1
}, () => {
// unlockedAnswers.forEach( (item, index) => {
// if (window[`tpiMDAnswer${index}`]) {
// window[`tpiMDAnswer${index}`].setMarkdown(item.contents)
// } else {
// window[`tpiMDAnswer${index}`] = this._initAnswerMarkdown(item.contents, `tpiMDAnswer${item.id}`)
// }
// })
})
}
})
@ -371,42 +334,6 @@ class LeftViewContainer extends Component {
console.log(error);
});
return;
// 查看是否有权限直接查看true可以直接查看false需要扣金币查看
// var getAnswerUrl = `/api/v1/games/${this.props.game.identifier}/answer`;
var getAnswerUrl = `/tasks/${this.props.game.identifier}/answer.json`
axios.get(getAnswerUrl, {
// withCredentials: true,
})
.then((response) => {
if (response.data.status == 0) {
this.props.showSnackbar(response.data.message)
return;
}
/*
将扣除XXX点金币是否确认查看答案     
已经过职业认证的教师可以免金币查看答案哟
继续查看 立即认证新开页
*/
// 答案测试 TODO
// if (false && response.data.view_answer === true) {
if (response.data.view_answer === true) {
this.showAnswer(response.data.answer)
} else {
// 三个角色 普通用户、未认证教师、已认证教师,这里要区分普通用户和未认证教师用户
this.setState({
dialogOpen: true,
})
}
})
.catch(function (error) {
console.log(error);
});
}
showUnlockAnswerDialog = (anwser) => {
this.setState({
@ -575,17 +502,5 @@ class LeftViewContainer extends Component {
);
}
}
/*
createNewComment={this.createNewComment}
fetchCommentIfNotFetched={this.fetchCommentIfNotFetched}
replyComment={this.replyComment}
deleteComment={this.deleteComment}
commentPraise={this.commentPraise}
hiddenComment={this.hiddenComment}
rewardCode={this.rewardCode}
showNewReply={this.showNewReply}
onPaginationChange={this.onPaginationChange}
*/
export default commentHOC(LeftViewContainer);

@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, { Component } from 'react';
//MonacoDiffEditor 对比模式
import {
@ -6,12 +6,10 @@ import {
Select,
Radio,
Checkbox,
Modal,
DatePicker,
Button,
} from 'antd';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import moment from 'moment';
@ -19,12 +17,8 @@ import axios from 'axios';
import './css/TPMsettings.css';
import {handleDateStrings} from "./oldTPMsettings";
import Bottomsubmit from "../../modals/Bottomsubmit";
const $ = window.$;
let timeout;
let currentValue;
@ -53,6 +47,27 @@ function disabledDate(current) {
return current && current < moment().endOf('day').subtract(1, 'days');
}
function handleDateStrings(dateString) {
if (!dateString) return dateString;
const ar = dateString.split(':')
if (ar[1] == '00' || ar[1] == '30') {
return dateString
}
const miniute = parseInt(ar[1]);
if (miniute < 30 || miniute == 60) {
return [ar[0], '30'].join(':')
}
if (miniute < 60) {
// 加一个小时
const tempStr = [ar[0], '00'].join(':');
const format = "YYYY-MM-DD HH:mm";
const _moment = moment(tempStr, format)
_moment.add(1, 'hours')
return _moment.format(format)
}
return dateString
}
export default class Shixuninformation extends Component {
constructor(props) {
@ -65,24 +80,24 @@ export default class Shixuninformation extends Component {
oldscope_partment: [],
scope_partment: [],
loading: false,
opening_timetype:false,
use_scope_type:false,
scope_partmenttype:false
opening_timetype: false,
use_scope_type: false,
scope_partmenttype: false
}
}
componentDidMount() {
if (this.props.data) {
if (this.props.data.shixun) {
let time =this.props.data && this.props.data.shixun.opening_time;
let timetype=false;
if(!time){
timetype=false;
}else{
timetype=true;
let time = this.props.data && this.props.data.shixun.opening_time;
let timetype = false;
if (!time) {
timetype = false;
} else {
timetype = true;
}
this.setState({
use_scope_type:this.props&&this.props.status>1&& this.props.data && this.props.data.shixun.use_scope===0&&this.props&&this.props.identity>2||this.props&&this.props.public===2&& this.props.data && this.props.data.shixun.use_scope===0&&this.props&&this.props.identity>2?true:false,
use_scope_type: this.props && this.props.status > 1 && this.props.data && this.props.data.shixun.use_scope === 0 && this.props && this.props.identity > 2 || this.props && this.props.public === 2 && this.props.data && this.props.data.shixun.use_scope === 0 && this.props && this.props.identity > 2 ? true : false,
can_copy: this.props.data && this.props.data.shixun.can_copy === undefined ? false : this.props.data && this.props.data.shixun.can_copy,
use_scope: this.props.data && this.props.data.shixun.use_scope,
opening_time: this.props.data && this.props.data.shixun.opening_time,
@ -110,15 +125,15 @@ export default class Shixuninformation extends Component {
if (prevProps.data != this.props.data) {
if (this.props.data) {
if (this.props.data.shixun) {
let time =this.props.data && this.props.data.shixun.opening_time;
let timetype=false;
if(!time){
timetype=false;
}else{
timetype=true;
let time = this.props.data && this.props.data.shixun.opening_time;
let timetype = false;
if (!time) {
timetype = false;
} else {
timetype = true;
}
this.setState({
use_scope_type:this.props&&this.props.status>1&& this.props.data && this.props.data.shixun.use_scope===0&&this.props&&this.props.identity>2||this.props&&this.props.public===2&& this.props.data && this.props.data.shixun.use_scope===0&&this.props&&this.props.identity>2?true:false,
use_scope_type: this.props && this.props.status > 1 && this.props.data && this.props.data.shixun.use_scope === 0 && this.props && this.props.identity > 2 || this.props && this.props.public === 2 && this.props.data && this.props.data.shixun.use_scope === 0 && this.props && this.props.identity > 2 ? true : false,
can_copy: this.props.data && this.props.data.shixun.can_copy === undefined ? false : this.props.data && this.props.data.shixun.can_copy,
use_scope: this.props.data && this.props.data.shixun.use_scope,
opening_time: this.props.data && this.props.data.shixun.opening_time,
@ -133,40 +148,40 @@ export default class Shixuninformation extends Component {
onChangeTimePicker = (value, dateString) => {
this.setState({
opening_time: dateString === "" ? "" : handleDateStrings(dateString),
opening_timetype:false,
opening_timetype: false,
loading: false
})
}
onSubmits = () => {
let {can_copy, use_scope, scope_partment, opening_time,oldscope_partment} = this.state;
let { can_copy, use_scope, scope_partment, opening_time, oldscope_partment } = this.state;
if(this.state.opentime===true){
if(opening_time===null){
if (this.state.opentime === true) {
if (opening_time === null) {
this.setState({
opening_timetype:true
opening_timetype: true
})
return
}
}
if(use_scope===1){
if(oldscope_partment.length===0&&scope_partment.length===0){
if (use_scope === 1) {
if (oldscope_partment.length === 0 && scope_partment.length === 0) {
this.setState({
scope_partmenttype:true
scope_partmenttype: true
})
this.props.showNotification("请选择指定单位公开")
return
}
}
let list=[]
scope_partment.map((item,key)=>{
let list = []
scope_partment.map((item, key) => {
list.push(item)
})
oldscope_partment.map((item,key)=>{
oldscope_partment.map((item, key) => {
list.push(item)
})
@ -175,7 +190,7 @@ export default class Shixuninformation extends Component {
axios.post(url,
{
scope_partment:use_scope===0?undefined:list,
scope_partment: use_scope === 0 ? undefined : list,
shixun: {
can_copy: can_copy,
use_scope: use_scope,
@ -189,8 +204,8 @@ export default class Shixuninformation extends Component {
this.props.showNotification("权限配置保存成功!")
this.setState({
loading: false,
scope_partment:[],
oldscope_partment:list
scope_partment: [],
oldscope_partment: list
})
this.props.getdatas("3")
}
@ -213,7 +228,7 @@ export default class Shixuninformation extends Component {
}
shixunScopeInput = (e) => {
let {scope_partment, oldscope_partment} = this.state;
let { scope_partment, oldscope_partment } = this.state;
let datalist = scope_partment;
if (datalist === undefined) {
datalist = []
@ -221,7 +236,7 @@ export default class Shixuninformation extends Component {
let scopetype = false;
if(scope_partment.length>0){
if (scope_partment.length > 0) {
scope_partment.map((item, key) => {
if (item === e) {
scopetype = true
@ -229,7 +244,7 @@ export default class Shixuninformation extends Component {
})
}
if(oldscope_partment.length>0){
if (oldscope_partment.length > 0) {
oldscope_partment.map((item, key) => {
if (item === e) {
scopetype = true
@ -243,7 +258,7 @@ export default class Shixuninformation extends Component {
datalist.push(e)
this.setState({
scope_partment: datalist,
scope_partmenttype:false
scope_partmenttype: false
});
} else {
this.props.showNotification("请勿指定相同的单位")
@ -271,11 +286,11 @@ export default class Shixuninformation extends Component {
}
shixunHandleSearch = (value) => {
this.shixunsfetch(value, departmentslist => this.setState({departmentslist}));
this.shixunsfetch(value, departmentslist => this.setState({ departmentslist }));
}
deleteScopeInput = (key) => {
let {scope_partment} = this.state;
let { scope_partment } = this.state;
let datalist = scope_partment;
datalist.splice(key, 1);
this.setState({
@ -284,9 +299,9 @@ export default class Shixuninformation extends Component {
}
setopentime = (e) => {
if(e.target.checked===false){
if (e.target.checked === false) {
this.setState({
opening_time:null
opening_time: null
})
}
this.setState({
@ -313,111 +328,111 @@ export default class Shixuninformation extends Component {
return (
<div>
<div className="educontent mb200 edu-back-white padding10-20 pdb30 mb50">
{this.props&&this.props.is_jupyter===true?"":<div className="clearfix ml40">
<span className="color-grey-6 mt5 fl font-16 ml20" style={{minWidth: '45px'}}>复制:</span>
{this.props && this.props.is_jupyter === true ? "" : <div className="clearfix ml40">
<span className="color-grey-6 mt5 fl font-16 ml20" style={{ minWidth: '45px' }}>复制:</span>
<span className="fl mt8 ml13">
<Checkbox
checked={this.state.can_copy}
onChange={this.CheckboxonChange}></Checkbox>
<label style={{top: '6px'}} className="color-grey-9 ml10">选中则允许已职业认证的教师复制该实训</label>
<label style={{ top: '6px' }} className="color-grey-9 ml10">选中则允许已职业认证的教师复制该实训</label>
</span>
</div>}
<div className="edu-back-white mb10 ml30 mt20">
{this.props&&this.props.status>1&&this.state.use_scope===0&&this.props&&this.props.identity>2&&this.state.use_scope_type===true||this.props&&this.props.public===2&&this.state.use_scope===0&&this.props&&this.props.identity>2&&this.state.use_scope_type===true?"":<div>
<span className="color-grey-6 mt5 fl font-16" style={{minWidth: '45px'}}>公开程度:</span>
<span className="fl mt8 ml20">
<RadioGroup onChange={this.SelectOpenpublic} value={this.state.use_scope}>
<Radio className="radioStyle" value={0}><span>对所有单位公开</span> <span
className="color-grey-9">实训发布后所有用户可见</span></Radio>
<Radio className="radioStyle" value={1}><span>对指定单位公开</span> <span
className="color-grey-9">实训发布后仅对下方指定单位的用户可见</span></Radio>
</RadioGroup>
<div className="clearfix" id="unit-all"
style={{display: this.state.use_scope === 0 ? 'none' : 'block'}}>
<div className="fl ml25">
<div className="fl" id="unit-input-part" style={{width: '100%'}}>
<div id="person-unit" className="fl pr mr10">
<div className="shixunScopeInput fl">
<Select
style={{width: '200px'}}
placeholder="请输入并选择单位名称"
onChange={(value) => this.shixunScopeInput(value)}
onSearch={this.shixunHandleSearch}
showSearch
value={this.state.scope_partment}
defaultActiveFirstOption={false}
showArrow={false}
filterOption={false}
notFoundContent={null}
className={this.props.scope_partmenttype === true ? "bor-red" : ""}
>
{options}
</Select>
<div className="edu-back-white mb10 ml30 mt20">
{this.props && this.props.status > 1 && this.state.use_scope === 0 && this.props && this.props.identity > 2 && this.state.use_scope_type === true || this.props && this.props.public === 2 && this.state.use_scope === 0 && this.props && this.props.identity > 2 && this.state.use_scope_type === true ? "" : <div>
<span className="color-grey-6 mt5 fl font-16" style={{ minWidth: '45px' }}>公开程度:</span>
<span className="fl mt8 ml20">
<RadioGroup onChange={this.SelectOpenpublic} value={this.state.use_scope}>
<Radio className="radioStyle" value={0}><span>对所有单位公开</span> <span
className="color-grey-9">实训发布后所有用户可见</span></Radio>
<Radio className="radioStyle" value={1}><span>对指定单位公开</span> <span
className="color-grey-9">实训发布后仅对下方指定单位的用户可见</span></Radio>
</RadioGroup>
<div className="clearfix" id="unit-all"
style={{ display: this.state.use_scope === 0 ? 'none' : 'block' }}>
<div className="fl ml25">
<div className="fl" id="unit-input-part" style={{ width: '100%' }}>
<div id="person-unit" className="fl pr mr10">
<div className="shixunScopeInput fl">
<Select
style={{ width: '200px' }}
placeholder="请输入并选择单位名称"
onChange={(value) => this.shixunScopeInput(value)}
onSearch={this.shixunHandleSearch}
showSearch
value={this.state.scope_partment}
defaultActiveFirstOption={false}
showArrow={false}
filterOption={false}
notFoundContent={null}
className={this.props.scope_partmenttype === true ? "bor-red" : ""}
>
{options}
</Select>
</div>
<span className="color-grey-9 openrenyuan">请通过搜索并选中单位名称进行添加</span>
</div>
</div>
<span className="color-grey-9 openrenyuan">请通过搜索并选中单位名称进行添加</span>
</div>
</div>
<div style={{width: '100%'}}>
<div className="mt20 clearfix" id="task_tag_content">
{
this.state.oldscope_partment.map((item, key) => {
return (
<li key={key} className={"fl mr20"}>
<Button type="primary" ghost className={"Permanentban "}>
{item}
</Button>
</li>
)
})
}
{
this.state.scope_partment === undefined ? "" : this.state.scope_partment.map((item, key) => {
return (
<li key={key} className={"fl mr20"}>
<Badge count={"x"} onClick={(key) => this.deleteScopeInput(key)}>
<Button type="primary" ghost className={"Permanentban "}>
{item}
</Button>
</Badge>
</li>
)
})
}
</div>
<div style={{ width: '100%' }}>
<div className="mt20 clearfix" id="task_tag_content">
{
this.state.oldscope_partment.map((item, key) => {
return (
<li key={key} className={"fl mr20"}>
<Button type="primary" ghost className={"Permanentban "}>
{item}
</Button>
</li>
)
})
}
{
this.state.scope_partment === undefined ? "" : this.state.scope_partment.map((item, key) => {
return (
<li key={key} className={"fl mr20"}>
<Badge count={"x"} onClick={(key) => this.deleteScopeInput(key)}>
<Button type="primary" ghost className={"Permanentban "}>
{item}
</Button>
</Badge>
</li>
)
})
}
</div>
</div>
</div>
<span
className={this.props.scope_partmenttype === true ? "color-orange ml20 fl" : "color-orange ml20 fl none"}
id="public_unit_notice">
<i className="fa fa-exclamation-circle mr3"></i>
请选择需要公开的单位
<span
className={this.props.scope_partmenttype === true ? "color-orange ml20 fl" : "color-orange ml20 fl none"}
id="public_unit_notice">
<i className="fa fa-exclamation-circle mr3"></i>
请选择需要公开的单位
</span>
</div>
</div>
</div>
</span>
</div>}
</span>
</div>}
<div className="clearfix mt20">
<span className="color-grey-6 mt5 fl font-16" style={{minWidth: '45px'}}>开启时间:</span>
<span className="color-grey-6 mt5 fl font-16" style={{ minWidth: '45px' }}>开启时间:</span>
<span className="fl mt8 ml20">
<Checkbox
checked={this.state.opentime === undefined ? false : this.state.opentime}
onChange={this.setopentime}></Checkbox>
<label style={{top: '6px'}}
className="color-grey-9 ml10">选中则学员在指定的开启时间后才能开启学习不选中则学员在实训发布后能立即开启学习</label>
<div className={"both"}></div>
<label style={{ top: '6px' }}
className="color-grey-9 ml10">选中则学员在指定的开启时间后才能开启学习不选中则学员在实训发布后能立即开启学习</label>
<div className={"both"}></div>
{this.state.opentime === false ? "" : <div className="mt20 ml25">
<DatePicker
className={this.state.opening_timetype===true?"bor-red":""}
className={this.state.opening_timetype === true ? "bor-red" : ""}
showToday={false}
showTime={{format: 'HH:mm'}}
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
width={178}
locale={locale}
@ -429,7 +444,7 @@ export default class Shixuninformation extends Component {
dropdownClassName="hideDisable"
/>
</div>}
<div className={this.state.opening_timetype===true?"color-red mt10 ml20":"none"}>请选择开启时间</div>
<div className={this.state.opening_timetype === true ? "color-red mt10 ml20" : "none"}>请选择开启时间</div>
</span>
</div>
@ -439,8 +454,7 @@ export default class Shixuninformation extends Component {
</div>
{this.props.identity < 5 ?
<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${this.props.match.params.shixunId}/challenges`}
onSubmits={this.onSubmits} loadings={this.state.loading}
// bottomvalue={ this.props.shixunsDetails&&this.props.shixunsDetails.is_jupyter === true?"确 定":"下一步"}
onSubmits={this.onSubmits} loadings={this.state.loading}
/> : ""}
</div>
);

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save