dev_forum
杨树明 5 years ago
parent 9441f038be
commit 79385d7bc6

@ -180,7 +180,7 @@ class TPMIndex extends Component {
power: response.data.power,
identity: response.data.identity,
propaedeutics:response.data.propaedeutics,
status: response.data.status,
status: response.data.shixun_status,
});
}
}).catch((error) => {

@ -190,7 +190,7 @@ export default class TPMsettings extends Component {
evaluate_script:undefined,
standard_scripts: undefined,
choice_main_type: "",
choice_small_type: [""],
choice_small_type: [],
choice_standard_scripts:undefined,
editordescriptios: undefined,
editorevaluate_scripts: undefined,
@ -222,7 +222,7 @@ export default class TPMsettings extends Component {
scope_partmenttype:false,
newuse_scope:undefined,
scope_partments:0,
shixun_service_configs:undefined,
pod_exist_time: undefined,
pod_exist_timetype: false,
shixunmemoMDvalue:"",
@ -325,6 +325,7 @@ export default class TPMsettings extends Component {
newuse_scope:response.data.shixun.use_scope,
scope_partments: response.data.shixun.scope_partment.length,
shixunmemoMDvalue:response.data.shixun.evaluate_script,
shixun_service_configs:response.data.shixun.shixun_service_configs
})
// if(response.data.status===403){
@ -513,6 +514,23 @@ export default class TPMsettings extends Component {
bigClass = (value) => {
let {settingsData,shixun_service_configs}=this.state;
let newshixun_service_configs=shixun_service_configs;
settingsData.shixun.main_type.some((item,key)=> {
if (item.id === value) {
newshixun_service_configs[0]={
mirror_repository_id:value,
name:item.type_name,
cpu_limit:1,
lower_cpu_limit:0.1,
memory_limit:1024,
request_limit:10
}
return true
}
}
)
let url = `/shixuns/get_mirror_script.json?mirror_id=`+value;
axios.get(url).then((response) => {
if (response.status === 200) {
@ -520,7 +538,8 @@ export default class TPMsettings extends Component {
this.setState({
choice_main_type: value,
standard_scripts:response.data,
choice_standard_scripts:null
choice_standard_scripts:null,
shixun_service_configs:newshixun_service_configs
})
}
}).catch((error) => {
@ -530,10 +549,78 @@ export default class TPMsettings extends Component {
}
Deselectlittle=(value)=>{
let {settingsData,shixun_service_configs,choice_small_type}=this.state;
let newshixun_service_configs=shixun_service_configs;
let newchoice_small_type=choice_small_type;
newchoice_small_type.some((items,keys)=> {
if (items === value) {
newchoice_small_type.splice(keys, 1)
return true
}
}
)
settingsData.shixun.small_type.some((items,keys)=> {
if (items.id === value) {
newshixun_service_configs.splice(keys+1, 1)
return true
}
}
)
this.setState({
choice_small_type: newchoice_small_type,
shixun_service_configs:newshixun_service_configs
})
}
littleClass = (value) => {
let {settingsData,shixun_service_configs,choice_small_type}=this.state;
let newshixun_service_configs=shixun_service_configs;
let newchoice_small_type=choice_small_type;
// if(Array.isArray(value)===true){
// value.map((item,key)=>{
// settingsData.shixun.small_type.some((items,keys)=> {
// if (items.id === item) {
// newshixun_service_configs.push({
// mirror_repository_id:value,
// name:items.type_name,
// cpu_limit:1,
// lower_cpu_limit:0.1,
// memory_limit:1024,
// request_limit:10
// })
// return true
// }
// }
// )
// })
// }
settingsData.shixun.small_type.some((items,keys)=> {
if (items.id === value) {
newshixun_service_configs.push({
mirror_repository_id:value,
name:items.type_name,
cpu_limit:1,
lower_cpu_limit:0.1,
memory_limit:1024,
request_limit:10
})
return true
}
}
)
newchoice_small_type.push(value)
this.setState({
choice_small_type: value
choice_small_type: newchoice_small_type,
shixun_service_configs:newshixun_service_configs
})
}
onPodExistTimeChange = (e) => {
@ -596,7 +683,7 @@ export default class TPMsettings extends Component {
let {
name, description, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum,
evaluate_script, exec_time, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh,
opening_time, pod_exist_time,shixunmemoMDvalue
opening_time, pod_exist_time,shixunmemoMDvalue,shixun_service_configs
} = this.state;
let operateauthority=this.props.identity<5&&this.state.status==0||this.props.identity===1&&this.state.status==2||this.props.identity===1&&this.state.status==1;
@ -689,31 +776,35 @@ export default class TPMsettings extends Component {
if(newmulti_webssh===null){
newmulti_webssh=0
}
//exec_time: exec_time,
let Url = `/shixuns/` + id + `.json`;
let data = {
name: name,
description: description_editormd,
main_type: choice_main_type,
small_type: choice_small_type,
webssh: webssh,
user_scope: use_scope,
scope_partment: scope_partment,
can_copy: can_copy,
vnc: vnc,
test_set_permission: test_set_permission,
code_hidden: code_hidden,
trainee: trainee,
task_pass: task_pass,
standard_scripts: choice_standard_scripts,
hide_code: hide_code,
forbid_copy: forbid_copy,
exec_time: exec_time,
evaluate_script: evaluate_script_editormd,
multi_webssh:newmulti_webssh,
opening_time:opening_time,
mirror_script_id:choice_standard_scriptssum,
delType:1
shixun:{
name: name,
webssh: webssh,
user_scope: use_scope,
can_copy: can_copy,
vnc: vnc,
test_set_permission: test_set_permission,
code_hidden: code_hidden,
trainee: trainee,
task_pass: task_pass,
standard_scripts: choice_standard_scripts,
hide_code: hide_code,
forbid_copy: forbid_copy,
multi_webssh:newmulti_webssh,
opening_time:opening_time,
mirror_script_id:choice_standard_scriptssum,
delType:1
},
shixun_info:{
description: description_editormd,
evaluate_script: evaluate_script_editormd,
},
main_type: choice_main_type,
small_type: choice_small_type,
scope_partment: scope_partment,
shixun_service_configs:shixun_service_configs
}
axios.put(Url, data).then((response) => {
@ -941,7 +1032,7 @@ export default class TPMsettings extends Component {
this.setState({
opers:true
})
e.stopPropagation();//阻止冒泡
}
bigopens=(e)=>{
@ -951,19 +1042,19 @@ export default class TPMsettings extends Component {
opersss:false,
opensmail:false
})
e.stopPropagation();//阻止冒泡
}
bigopensmal=(e)=>{
this.setState({
opensmail:true
})
e.stopPropagation();//阻止冒泡
}
sbigopen=(e)=>{
this.setState({
operss:true
})
e.stopPropagation();//阻止冒泡
}
sbigopens=()=>{
@ -975,7 +1066,7 @@ export default class TPMsettings extends Component {
this.setState({
opersss:true
})
e.stopPropagation();//阻止冒泡
}
sbigopensss=()=>{
@ -1020,7 +1111,9 @@ export default class TPMsettings extends Component {
})
}
inputs=()=>{
}
render() {
let {
@ -1075,7 +1168,8 @@ export default class TPMsettings extends Component {
scope_partmenttype,
newuse_scope,
scope_partments,
shixunmemoMDvalue,delType
shixunmemoMDvalue,delType,
shixun_service_configs
} = this.state;
let options;
@ -1259,9 +1353,10 @@ export default class TPMsettings extends Component {
value={choice_small_type.length===0||choice_small_type[0]===""||choice_small_type===[]?undefined:choice_small_type}
style={{width: 180}}
disabled={operateauthority?false:true}
onChange={operateauthority?this.littleClass:""}
// onChange={operateauthority?this.littleClass:""}
onDeselect={operateauthority?this.Deselectlittle:""}
onMouseEnter={operateauthority?this.bigopensmal:""}
onSelect={operateauthority?this.bigopens:""}
onSelect={operateauthority?this.littleClass:""}
defaultOpen={false}
open={opensmail}
>
@ -1700,6 +1795,58 @@ export default class TPMsettings extends Component {
{/*</div>*/}
</div>
{/*"name": "我是镜像名", # 镜像名称*/}
{/*"cpu_limit": 1, # cpu核*/}
{/*"lower_cpu_limit": 0.1, # 最低cpu核 浮点数*/}
{/*"memory_limit": 1024 ,#内存限制*/}
{/*"request_limit": 10, # 内存要求*/}
{/*"mirror_repository_id": 12, # 镜像id*/}
<div className="edu-back-white padding40-20 mb20">
{this.props.identity<2?shixun_service_configs&&shixun_service_configs.map((item,key)=>{
return(
<div key={key}>
<p className="color-grey-6 font-16 mb30">服务配置</p>
<div id="5">
<p className="color-grey-6 font-16 mt30 mb10" id="shixun_scenario_type_name">{item.name}</p>
<div className="clearfix mb5">
<label className="panel-form-label fl">CPU()</label>
<div className="pr fl with80 status_con">
<input type="text" name="cpu_limit[]" value={item.cpu_limit} onInput={this.inputs}
className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" />
</div>
<div className="cl"></div>
</div>
<div className="clearfix mb5">
<label className="panel-form-label fl">最低CPU()</label>
<div className="pr fl with80 status_con">
<input type="text" name="lower_cpu_limit[]" value={item.lower_cpu_limit} onInput={this.inputs}
className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" />
</div>
<div className="cl"></div>
</div>
<div className="clearfix mb5">
<label className="panel-form-label fl">内存限制(M)</label>
<div className="pr fl with80 status_con">
<input type="text" name="memory_limit[]" value={item.memory_limit} onInput={this.inputs}
className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" />
</div>
<div className="cl"></div>
</div>
<div className="clearfix mb5">
<label className="panel-form-label fl">内存要求(M)</label>
<div className="pr fl with20 status_con">
<input type="text" name="request_limit[]" value={item.request_limit} onInput={this.inputs}
className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" />
</div>
<label className="panel-form-label fl" style={{width: '48%'}}>温馨提示纯编程类型实训建议使用默认值对于大数据等建议使用最大内存的30%</label>
<div className="cl"></div>
</div>
</div>
</div>
)
}) :""}
</div>
<p>
{
@ -1711,49 +1858,7 @@ export default class TPMsettings extends Component {
<a href={"/shixuns/" + shixunsID + "/challenges"} className="defalutCancelbtn fl">取消</a>
</div> :""
}
{/*{*/}
{/*this.props.identity===1&&this.props.status==2?*/}
{/*<div className="clearfix mt30">*/}
{/*<a className="defalutSubmitbtn fl mr20"*/}
{/*onClick={this.submit_edit_shixun}>保存</a>*/}
{/*<a href={"/shixuns/" + shixunsID + "/challenges"} className="defalutCancelbtn fl">取消</a>*/}
{/*/!*<a className="edu-default-btn edu-blueline-btn fl ml20"*!/*/}
{/*/!*id="challenge_begin"*!/*/}
{/*/!*onClick={this.operateshixuns}>*!/*/}
{/*/!*永久关闭*!/*/}
{/*/!*</a>*!/*/}
{/*</div> :""*/}
{/*}*/}
{/*{*/}
{/*this.props.identity===1||this.props.power==true?*/}
{/*<div className="clearfix mt30">*/}
{/*<a className="defalutSubmitbtn fl mr20"*/}
{/*onClick={this.submit_edit_shixun}>保存</a>*/}
{/*<a href={"/shixuns/" + shixunsID + "/challenges"} className="defalutCancelbtn fl">取消</a>*/}
{/*<Popconfirm title={status===0?"删除实训后,用户不能再开始挑战了是否确认删除?":"关闭实训后,用户不能再开始挑战了是否确认关闭?"} onConfirm={this.shixunsclose} okText="确定"*/}
{/*cancelText="取消"*/}
{/*style={{display:status===0?"none":"block"}}*/}
{/*>*/}
{/*<a*/}
{/*className="edu-default-btn edu-blueline-btn fl ml20"*/}
{/*id="challenge_begin"*/}
{/*style={{display:status===0?"none":"block"}}*/}
{/*>*/}
{/*{status===0?"":"永久关闭"}*/}
{/*</a>*/}
{/*</Popconfirm>*/}
{/*</div> :""*/}
{/*}*/}
{/*<div className="clearfix mt30">*/}
{/*<a className="defalutSubmitbtn fl mr20"*/}
{/*onClick={this.submit_edit_shixun}>保存</a>*/}
{/*<a href={"/shixuns/" + shixunsID + "/challenges"} className="defalutCancelbtn fl">取消</a>*/}
{/*</div>*/}
</p>
</div>

@ -1,366 +1,366 @@
import React, {Component} from 'react';
import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd';
import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
// import "antd/dist/antd.css";
import { getImageUrl, toPath, getUrl } from 'educoder';
import axios from 'axios';
import './css/TPMchallengesnew.css';
let origin = getUrl();
let path = getUrl("/editormd/lib/")
const $ = window.$;
let timeout;
let currentValue;
const Option = Select.Option;
const RadioGroup = Radio.Group;
// 恢复数据
function md_rec_data(k,mdu,id, editor){
if(window.sessionStorage.getItem(k+mdu) !== null){
editor.setValue(window.sessionStorage.getItem(k+mdu));
md_clear_data(k,mdu,id);
}
}
// 保存数据
function md_add_data(k,mdu,d){
window.sessionStorage.setItem(k+mdu,d);
}
// 清空保存的数据
function md_clear_data(k,mdu,id){
window.sessionStorage.removeItem(k+mdu);
var id1 = "#e_tip_"+id;
var id2 = "#e_tips_"+id;
if(k == 'content'){
$(id2).html("");
}else{
$(id1).html("");
}
}
function md_elocalStorage(editor,mdu,id){
if (window.sessionStorage){
var oc = window.sessionStorage.getItem('content'+mdu);
if(oc !== null ){
console.log("#e_tips_"+id)
$("#e_tips_"+id).data('editor', editor);
var h = '您上次有已保存的数据,是否<a style="cursor: pointer;" class="link-color-blue" onclick="md_rec_data(\'content\',\''+ mdu + '\',\'' + id + '\')">恢复</a> ? / <a style="cursor: pointer;" class="link-color-blue" onclick="md_clear_data(\'content\',\''+ mdu + '\',\'' + id + '\')">不恢复</a>';
$("#e_tips_"+id).html(h);
}
setInterval(function() {
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
h = h < 10 ? '0' + h : h;
m = m < 10 ? '0' + m : m;
s = s < 10 ? '0' + s : s;
if(editor.getValue().trim() != ""){
md_add_data("content",mdu,editor.getValue());
var id1 = "#e_tip_"+id;
var id2 = "#e_tips_"+id;
$(id1).html(" 数据已于 " + h + ':' + m + ':' + s +" 保存 ");
$(id2).html("");
}
},10000);
}else{
$("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!');
}
}
function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
var editorName = window.editormd(id, {
width: width,
height: high,
path: path, // "/editormd/lib/"
syncScrolling: "single",
tex: true,
tocm: true,
emoji: true,
taskList: true,
codeFold: true,
searchReplace: true,
htmlDecode: "style,script,iframe",
sequenceDiagram: true,
autoFocus: false,
toolbarIcons: function () {
// Or return editormd.toolbarModes[name]; // full, simple, mini
// Using "||" set icons align right.
return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"]
},
toolbarCustomIcons: {
testIcon: "<a type=\"inline\" class=\"latex\" ><div class='zbg'></div></a>",
testIcon1: "<a type=\"latex\" class=\"latex\" ><div class='zbg_latex'></div></a>"
},
//这个配置在simple.html中并没有但是为了能够提交表单使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中方便post提交表单。
saveHTMLToTextarea: true,
// 用于增加自定义工具栏的功能可以直接插入HTML标签不使用默认的元素创建图标
dialogMaskOpacity: 0.6,
placeholder: placeholder,
imageUpload: true,
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"],
imageUploadURL: imageUrl,//url
onload: function () {
// this.previewing();
$("#" + id + " [type=\"latex\"]").bind("click", function () {
editorName.cm.replaceSelection("```latex");
editorName.cm.replaceSelection("\n");
editorName.cm.replaceSelection("\n");
editorName.cm.replaceSelection("```");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line - 1, 0);
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");
$("[type=\"latex\"]").attr("title", "多行公式");
md_elocalStorage(editorName, `answers__${id}`, "Memoanswers");
callback && callback()
}
});
return editorName;
}
export default class TPManswer extends Component {
constructor(props) {
super(props)
this.state = {
choice_url: undefined,
practice_url: undefined,
go_back_url: undefined,
value: 1,
answer:"",
id:undefined,
checkpointId:undefined,
power: false,
prev_challenge: undefined,
next_challenge: undefined,
}
}
answerMD(initValue, id) {
this.contentChanged = false;
const placeholder = "";
// amp;
// 编辑时要传memoId
const imageUrl = `/api/attachments.json`;
// 创建editorMd
const answers_editormd = create_editorMD(id, '100%', 400, placeholder, imageUrl, () => {
setTimeout(() => {
answers_editormd.resize()
answers_editormd.cm && answers_editormd.cm.refresh()
}, 500)
if (initValue != undefined) {
answers_editormd.setValue(initValue)
}
answers_editormd.cm.on("change", (_cm, changeObj) => {
console.log('....contentChanged')
this.contentChanged = true;
})
});
this.answers_editormd = answers_editormd;
window.answers_editormd = answers_editormd;
}
componentDidMount() {
let id = this.props.match.params.shixunId;
let checkpointId=this.props.match.params.checkpointId;
let newchoice_url= "/shixuns/"+id+"/challenges/newquestion";
let newpractice_url= "/shixuns/"+id+"/challenges/new";
let newgo_back_url="/shixuns/"+id+"/challenges";
this.setState({
shixunId:id,
checkpointId:checkpointId
})
let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=2";
axios.get(url).then((response) => {
let newprev_challenge = response.data.prev_challenge;
let next_challenge = response.data.next_challenge;
if (newprev_challenge != undefined) {
if(newprev_challenge.st===0){
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint";
}else{
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion";
}
}
if (next_challenge != undefined) {
if(next_challenge.st===0){
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint";
}else{
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion";
}
}
this.setState({
answer:response.data.answer,
power: response.data.power,
choice_url: newchoice_url, // 导航中的新建选择题url
practice_url: newpractice_url, //string 导航中新建实践题url
go_back_url: newgo_back_url, //string 导航中的返回url
position: response.data.position, //int 关卡位置,导航栏中的第几关
prev_challenge: newprev_challenge,
next_challenge: next_challenge,
})
if(response.data.power===false){
this.props.showSnackbar("没有权限修改");
}
if(response.data.answer===undefined||response.data.answer===null){
this.answerMD("", "answerMD");
}else{
this.answerMD(response.data.answer, "answerMD");
}
}).catch((error) => {
console.log(error)
});
}
challenge_answer_submit=()=> {
let id = this.props.match.params.shixunId;
let{checkpointId}=this.state;
let url = "/shixuns/"+id+"/challenges/"+checkpointId+".json";
const answer_editormdvalue = this.answers_editormd.getValue();
axios.put(url,{
tab:2,
identifier:id,
id:checkpointId,
challenge:{
answer:answer_editormdvalue
}
}
).then((response) => {
this.props.showSnackbar(response.data.messages);
}).catch((error) => {
console.log(error)
});
}
render() {
let {
choice_url,
practice_url,
go_back_url,
position,
task_pass_default,
submit_url,
shixunId,
checkpointId,
power,
prev_challenge,
next_challenge,
} = this.state;
let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint";
let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2";
let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3";
// console.log(this.props)
return (
<React.Fragment>
<div className="educontent mt30 mb30">
<div className="padding10-20 mb10 edu-back-white clearfix">
<span className="fl ring-blue mr10 mt7">
<img src={getImageUrl("images/educoder/icon/code.svg")} data-tip-down="实训任务" className="fl mt2 ml2"/>
</span>
<span className="font-16 task-hide fl TPMtaskName">{position}</span>
<Link to={go_back_url === undefined ? "" : go_back_url}
className="color-grey-6 fr font-16 ml30">返回</Link>
{prev_challenge === undefined ? "" :
<a href={prev_challenge} className="fr color-blue mr15 mt3">上一关</a>
}
{next_challenge === undefined ? "" :
<a href={next_challenge} className="fr color-blue mr15 mt3">下一关</a>
}
<Link to={practice_url === undefined ? "" : practice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增代码编辑类型的任务">+&nbsp;实践类型</Link>
<Link to={choice_url === undefined ? "" : choice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增选择题类型的任务">+&nbsp;选择题类型</Link>
</div>
<div className="challenge_nav clearfix edu-back-white">
<li>
<Link to={tab1url}>本关任务</Link>
</li>
<li >
<Link to={tab2url}>评测设置</Link>
</li>
<li className="active">
<Link to={tab3url}>参考答案</Link>
</li>
</div>
<div className="edu-back-white mb10 clearfix">
<div className="padding40-20">
<p className="color-grey-6 font-16 mb30">参考答案</p>
<div className="df">
<div className="padding10-20 edu-back-greyf5 radius4" id="answerMD">
<textarea style={{display: 'none'}} id="evaluate_script_show" name="content"> </textarea>
<div className="CodeMirror cm-s-defualt">
</div>
</div>
</div>
<p id="e_tip_Memoanswers" className="edu-txt-right color-grey-cd font-12"></p>
<p id="e_tips_Memoanswers" className="edu-txt-right color-grey-cd font-12"></p>
</div>
</div>
<div className="clearfix mt20" style={{display:this.props.identity>3||this.props.identity===undefined||power===false?"none":"block"}}>
<a className="defalutSubmitbtn fl mr20"
onClick={this.challenge_answer_submit}>提交</a>
<a href={"/shixuns/" + shixunId + "/challenges"} className="defalutCancelbtn fl">取消</a>
</div>
</div>
</React.Fragment>
)
}
}
import React, {Component} from 'react';
import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd';
import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
// import "antd/dist/antd.css";
import { getImageUrl, toPath, getUrl } from 'educoder';
import axios from 'axios';
import './css/TPMchallengesnew.css';
let origin = getUrl();
let path = getUrl("/editormd/lib/")
const $ = window.$;
let timeout;
let currentValue;
const Option = Select.Option;
const RadioGroup = Radio.Group;
// 恢复数据
function md_rec_data(k,mdu,id, editor){
if(window.sessionStorage.getItem(k+mdu) !== null){
editor.setValue(window.sessionStorage.getItem(k+mdu));
md_clear_data(k,mdu,id);
}
}
// 保存数据
function md_add_data(k,mdu,d){
window.sessionStorage.setItem(k+mdu,d);
}
// 清空保存的数据
function md_clear_data(k,mdu,id){
window.sessionStorage.removeItem(k+mdu);
var id1 = "#e_tip_"+id;
var id2 = "#e_tips_"+id;
if(k == 'content'){
$(id2).html("");
}else{
$(id1).html("");
}
}
function md_elocalStorage(editor,mdu,id){
if (window.sessionStorage){
var oc = window.sessionStorage.getItem('content'+mdu);
if(oc !== null ){
console.log("#e_tips_"+id)
$("#e_tips_"+id).data('editor', editor);
var h = '您上次有已保存的数据,是否<a style="cursor: pointer;" class="link-color-blue" onclick="md_rec_data(\'content\',\''+ mdu + '\',\'' + id + '\')">恢复</a> ? / <a style="cursor: pointer;" class="link-color-blue" onclick="md_clear_data(\'content\',\''+ mdu + '\',\'' + id + '\')">不恢复</a>';
$("#e_tips_"+id).html(h);
}
setInterval(function() {
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
h = h < 10 ? '0' + h : h;
m = m < 10 ? '0' + m : m;
s = s < 10 ? '0' + s : s;
if(editor.getValue().trim() != ""){
md_add_data("content",mdu,editor.getValue());
var id1 = "#e_tip_"+id;
var id2 = "#e_tips_"+id;
$(id1).html(" 数据已于 " + h + ':' + m + ':' + s +" 保存 ");
$(id2).html("");
}
},10000);
}else{
$("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!');
}
}
function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
var editorName = window.editormd(id, {
width: width,
height: high,
path: path, // "/editormd/lib/"
syncScrolling: "single",
tex: true,
tocm: true,
emoji: true,
taskList: true,
codeFold: true,
searchReplace: true,
htmlDecode: "style,script,iframe",
sequenceDiagram: true,
autoFocus: false,
toolbarIcons: function () {
// Or return editormd.toolbarModes[name]; // full, simple, mini
// Using "||" set icons align right.
return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"]
},
toolbarCustomIcons: {
testIcon: "<a type=\"inline\" class=\"latex\" ><div class='zbg'></div></a>",
testIcon1: "<a type=\"latex\" class=\"latex\" ><div class='zbg_latex'></div></a>"
},
//这个配置在simple.html中并没有但是为了能够提交表单使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中方便post提交表单。
saveHTMLToTextarea: true,
// 用于增加自定义工具栏的功能可以直接插入HTML标签不使用默认的元素创建图标
dialogMaskOpacity: 0.6,
placeholder: placeholder,
imageUpload: true,
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"],
imageUploadURL: imageUrl,//url
onload: function () {
// this.previewing();
$("#" + id + " [type=\"latex\"]").bind("click", function () {
editorName.cm.replaceSelection("```latex");
editorName.cm.replaceSelection("\n");
editorName.cm.replaceSelection("\n");
editorName.cm.replaceSelection("```");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line - 1, 0);
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");
$("[type=\"latex\"]").attr("title", "多行公式");
md_elocalStorage(editorName, `answers__${id}`, "Memoanswers");
callback && callback()
}
});
return editorName;
}
export default class TPManswer extends Component {
constructor(props) {
super(props)
this.state = {
choice_url: undefined,
practice_url: undefined,
go_back_url: undefined,
value: 1,
answer:"",
id:undefined,
checkpointId:undefined,
power: false,
prev_challenge: undefined,
next_challenge: undefined,
}
}
answerMD(initValue, id) {
this.contentChanged = false;
const placeholder = "";
// amp;
// 编辑时要传memoId
const imageUrl = `/api/attachments.json`;
// 创建editorMd
const answers_editormd = create_editorMD(id, '100%', 400, placeholder, imageUrl, () => {
setTimeout(() => {
answers_editormd.resize()
answers_editormd.cm && answers_editormd.cm.refresh()
}, 500)
if (initValue != undefined) {
answers_editormd.setValue(initValue)
}
answers_editormd.cm.on("change", (_cm, changeObj) => {
console.log('....contentChanged')
this.contentChanged = true;
})
});
this.answers_editormd = answers_editormd;
window.answers_editormd = answers_editormd;
}
componentDidMount() {
let id = this.props.match.params.shixunId;
let checkpointId=this.props.match.params.checkpointId;
let newchoice_url= "/shixuns/"+id+"/challenges/newquestion";
let newpractice_url= "/shixuns/"+id+"/challenges/new";
let newgo_back_url="/shixuns/"+id+"/challenges";
this.setState({
shixunId:id,
checkpointId:checkpointId
})
let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=2";
axios.get(url).then((response) => {
let newprev_challenge = response.data.prev_challenge;
let next_challenge = response.data.next_challenge;
if (newprev_challenge != undefined) {
if(newprev_challenge.st===0){
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint";
}else{
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion";
}
}
if (next_challenge != undefined) {
if(next_challenge.st===0){
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint";
}else{
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion";
}
}
this.setState({
answer:response.data.answer,
power: response.data.power,
choice_url: newchoice_url, // 导航中的新建选择题url
practice_url: newpractice_url, //string 导航中新建实践题url
go_back_url: newgo_back_url, //string 导航中的返回url
position: response.data.position, //int 关卡位置,导航栏中的第几关
prev_challenge: newprev_challenge,
next_challenge: next_challenge,
})
if(response.data.power===false){
this.props.showSnackbar("没有权限修改");
}
if(response.data.answer===undefined||response.data.answer===null){
this.answerMD("", "answerMD");
}else{
this.answerMD(response.data.answer, "answerMD");
}
}).catch((error) => {
console.log(error)
});
}
challenge_answer_submit=()=> {
let id = this.props.match.params.shixunId;
let{checkpointId}=this.state;
let url = "/shixuns/"+id+"/challenges/"+checkpointId+".json";
const answer_editormdvalue = this.answers_editormd.getValue();
axios.put(url,{
tab:2,
identifier:id,
id:checkpointId,
challenge:{
answer:answer_editormdvalue
}
}
).then((response) => {
this.props.showSnackbar(response.data.messages);
}).catch((error) => {
console.log(error)
});
}
render() {
let {
choice_url,
practice_url,
go_back_url,
position,
task_pass_default,
submit_url,
shixunId,
checkpointId,
power,
prev_challenge,
next_challenge,
} = this.state;
let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint";
let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2";
let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3";
// console.log(this.props)
return (
<React.Fragment>
<div className="educontent mt30 mb30">
<div className="padding10-20 mb10 edu-back-white clearfix">
<span className="fl ring-blue mr10 mt7">
<img src={getImageUrl("images/educoder/icon/code.svg")} data-tip-down="实训任务" className="fl mt2 ml2"/>
</span>
<span className="font-16 task-hide fl TPMtaskName">{position}</span>
<Link to={go_back_url === undefined ? "" : go_back_url}
className="color-grey-6 fr font-15 mt3">返回</Link>
{prev_challenge === undefined ? "" :
<a href={prev_challenge} className="fr color-blue mr15 mt4">上一关</a>
}
{next_challenge === undefined ? "" :
<a href={next_challenge} className="fr color-blue mr15 mt4">下一关</a>
}
<Link to={practice_url === undefined ? "" : practice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增代码编辑类型的任务">+&nbsp;实践类型</Link>
<Link to={choice_url === undefined ? "" : choice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增选择题类型的任务">+&nbsp;选择题类型</Link>
</div>
<div className="challenge_nav clearfix edu-back-white">
<li>
<Link to={tab1url}>本关任务</Link>
</li>
<li >
<Link to={tab2url}>评测设置</Link>
</li>
<li className="active">
<Link to={tab3url}>参考答案</Link>
</li>
</div>
<div className="edu-back-white mb10 clearfix">
<div className="padding40-20">
<p className="color-grey-6 font-16 mb30">参考答案</p>
<div className="df">
<div className="padding10-20 edu-back-greyf5 radius4" id="answerMD">
<textarea style={{display: 'none'}} id="evaluate_script_show" name="content"> </textarea>
<div className="CodeMirror cm-s-defualt">
</div>
</div>
</div>
<p id="e_tip_Memoanswers" className="edu-txt-right color-grey-cd font-12"></p>
<p id="e_tips_Memoanswers" className="edu-txt-right color-grey-cd font-12"></p>
</div>
</div>
<div className="clearfix mt20" style={{display:this.props.identity>3||this.props.identity===undefined||power===false?"none":"block"}}>
<a className="defalutSubmitbtn fl mr20"
onClick={this.challenge_answer_submit}>提交</a>
<a href={"/shixuns/" + shixunId + "/challenges"} className="defalutCancelbtn fl">取消</a>
</div>
</div>
</React.Fragment>
)
}
}

@ -1,345 +1,345 @@
import React, {Component} from 'react';
import {Input, InputNumber, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd';
import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
// import "antd/dist/antd.css";
import { getImageUrl, toPath, getUrl } from 'educoder';
import axios from 'axios';
import './css/TPMchallengesnew.css';
import TPMMDEditor from './TPMMDEditor';
let origin = getUrl();
let path = getUrl("/editormd/lib/")
const $ = window.$;
let timeout;
let currentValue;
const Option = Select.Option;
const RadioGroup = Radio.Group;
// const testAnswers = [{
// "id": 4337,
// "name": "解题思路1",
// "contents": "答案的解题思路1",
// "level": 1,
// "score": 25
// },
// {
// "id": 4338,
// "name": "解题思路2",
// "contents": "答案的解题思路2",
// "level": 2,
// "score": 25
// }]
export default class TPManswer extends Component {
constructor(props) {
super(props)
this.state = {
choice_url: undefined,
practice_url: undefined,
go_back_url: undefined,
value: 1,
answer:"",
id:undefined,
checkpointId:undefined,
power: false,
prev_challenge: undefined,
next_challenge: undefined,
answers: [] //testAnswers
}
}
componentDidMount() {
let id = this.props.match.params.shixunId;
let checkpointId=this.props.match.params.checkpointId;
let newchoice_url= "/shixuns/"+id+"/challenges/newquestion";
let newpractice_url= "/shixuns/"+id+"/challenges/new";
let newgo_back_url="/shixuns/"+id+"/challenges";
this.setState({
shixunId:id,
checkpointId:checkpointId
})
let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=2";
axios.get(url).then((response) => {
let newprev_challenge = response.data.prev_challenge;
let next_challenge = response.data.next_challenge;
if (newprev_challenge != undefined) {
if(newprev_challenge.st===0){
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint";
}else{
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion";
}
}
if (next_challenge != undefined) {
if(next_challenge.st===0){
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint";
}else{
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion";
}
}
this.setState({
answer:response.data.answer,
power: response.data.power,
choice_url: newchoice_url, // 导航中的新建选择题url
practice_url: newpractice_url, //string 导航中新建实践题url
go_back_url: newgo_back_url, //string 导航中的返回url
position: response.data.position, //int 关卡位置,导航栏中的第几关
prev_challenge: newprev_challenge,
next_challenge: next_challenge,
})
if(response.data.power===false){
this.props.showSnackbar("没有权限修改");
}
// if(response.data.answer===undefined||response.data.answer===null){
// this.answerMD("", "answerMD");
// }else{
// this.answerMD(response.data.answer, "answerMD");
// }
}).catch((error) => {
console.log(error)
});
let urlAnswer = `/shixuns/${id}/challenges/${checkpointId}/answer.json`;
axios.get(urlAnswer).then((response) => {
if (response.data) {
this.setState({ answers: response.data })
}
})
}
challenge_answer_submit=()=> {
// `levelSection${index}`
// this.refs.md0
const { answers } = this.state;
const answersParams = answers.slice(0)
console.log(answersParams)
let isValidate = true;
let totalScore = 0;
answersParams.forEach( (item, index) => {
if (!isValidate) {
return;
}
const sectionId = `#levelSection${index}`;
const mdContnet = this.refs[`md${index}`].getValue().trim();;
item.contents = mdContnet;
item.name = item.name.trim()
totalScore += item.score;
delete item.id;
if (!item.name) {
this.props.showSnackbar("请先填写参考答案名称");
isValidate = false;
} else if (!mdContnet) {
this.props.showSnackbar("请先填写参考答案内容");
isValidate = false;
}
if (!isValidate) {
$("html, body").animate({ scrollTop: $(`${sectionId}`).offset().top - 100})
}
})
if (!isValidate) {
return;
}
if (totalScore != 100) {
this.props.showSnackbar("请先保证占比和为100%");
return;
}
let id = this.props.match.params.shixunId;
let {checkpointId} = this.state;
let url = `/shixuns/${id}/challenges/${checkpointId}/crud_answer.json`;
axios.post(url,{
challenge_answer: answersParams
}
).then((response) => {
if (response.data) {
if (response.data.message) {
this.props.showSnackbar(response.data.message);
}
}
}).catch((error) => {
console.log(error)
});
}
onNameChange = (e, index) => {
const newAnswer = Object.assign({}, this.state.answers[index])
newAnswer.name = e.target.value
const newAnswers = this.state.answers.slice(0)
newAnswers[index] = newAnswer
this.setState({ answers: newAnswers})
}
onScoreChange = (val, index) => {
const newAnswer = Object.assign({}, this.state.answers[index])
newAnswer.score = val
const newAnswers = this.state.answers.slice(0)
newAnswers[index] = newAnswer
this.setState({ answers: newAnswers})
}
addAnswer = () => {
const newAnswers = this.state.answers.slice(0)
newAnswers.push({
"name": `解题思路${newAnswers.length + 1}`,
"contents": "",
"score": 10
})
this.setState({ answers: newAnswers })
}
delanswers=(index)=>{
let {answers}=this.state;
let newanswers=answers;
newanswers.splice(index,1)
this.setState({
answers:newanswers
})
}
render() {
let {
choice_url,
practice_url,
go_back_url,
position,
task_pass_default,
submit_url,
shixunId,
checkpointId,
power,
prev_challenge,
next_challenge,
answers,
} = this.state;
let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint";
let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2";
let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3";
// console.log(this.props)
return (
<React.Fragment>
<div className="educontent mt30 mb30 tpmAnswer">
<div className="padding10-20 mb10 edu-back-white clearfix">
<span className="fl ring-blue mr10 mt7">
<img src={getImageUrl("images/educoder/icon/code.svg")} data-tip-down="实训任务" className="fl mt2 ml2"/>
</span>
<span className="font-16 task-hide fl TPMtaskName">{position}</span>
<Link to={go_back_url === undefined ? "" : go_back_url}
className="color-grey-6 fr font-16 ml30">返回</Link>
{prev_challenge === undefined ? "" :
<a href={prev_challenge} className="fr color-blue mr15 mt3">上一关</a>
}
{next_challenge === undefined ? "" :
<a href={next_challenge} className="fr color-blue mr15 mt3">下一关</a>
}
<Link to={practice_url === undefined ? "" : practice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增代码编辑类型的任务">+&nbsp;实践类型</Link>
<Link to={choice_url === undefined ? "" : choice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增选择题类型的任务">+&nbsp;选择题类型</Link>
</div>
<div className="challenge_nav clearfix edu-back-white">
<li>
<Link to={tab1url}>本关任务</Link>
</li>
<li >
<Link to={tab2url}>评测设置</Link>
</li>
<li className="active">
<Link to={tab3url}>参考答案</Link>
</li>
</div>
<div className="edu-back-white mb10 clearfix">
<div className="padding30-20">
<p className=" font-12" style={{ paddingBottom: '5px'
, color: '#666666'}}>
可以将参考答案分级设置让学员自行选择级别每级查看后按照比例扣分值学员已完成任务再查看则不影响原因已获得的成绩
</p>
<p className=" font-12 "
style={{ maxWidth: "782px"
, color: '#999999'}}>
示例级别1扣减分值占比25%级别2扣减分值占比35%级别3扣减分值占比40%则学员选择查看级别1的答案将被扣减25%的分值
选择查看级别2的答案将被扣减60%的分值选择查看级别3的答案将被扣减100%的分值
</p>
<style>{`
.tpmAnswer .ant-input { width: 230px }
.tpmAnswer .score.ant-input-number { width: 54px; }
.levelSection { margin-top: 16px }
`}</style>
{
answers.map((answer, index) => {
return <div className="levelSection" id={`levelSection${index}`}>
<span className="mr4 color-orange pt10">*</span>
<p className="color-grey-6 font-16 mb30 mt10" style={{ display: "inline" }}>级别{index + 1}</p>
<a className="fr sample_icon_remove mr30 mt8" onClick={()=>this.delanswers(index)}>
<i className="fa fa-times-circle color-grey-c font-16 fl" ></i>
</a>
<div className=" color-grey-6 font-16" style={{ marginLeft: "9px", margin: '8px 9px'}}>
<div className=" ">
<span>名称</span>
<Input value={answer.name} onChange={(e) => this.onNameChange(e, index)}></Input>
<span style={{ marginLeft: "20px"}} >扣减分值占比</span>
<InputNumber className="score" step={1} min={1} max={100} defaultValue={answer.score}
onChange={(e) => this.onScoreChange(e, index)} ></InputNumber>%
</div>
<div className="mt10">
<span>参考答案</span>
<TPMMDEditor ref={`md${index}`} mdID={index} initValue={answer.contents}></TPMMDEditor>
</div>
</div>
</div>
})
}
<div className="clearfix mt20" style={{display:this.props.identity>3||this.props.identity===undefined||power===false?"none":"block"}}>
<a href={"javascript:void(0)"} className="defalutCancelbtn fl" onClick={this.addAnswer}>新增</a>
</div>
</div>
</div>
<div className="clearfix mt20" style={{display:this.props.identity>3||this.props.identity===undefined||power===false?"none":"block"}}>
<a className="defalutSubmitbtn fl mr20"
onClick={this.challenge_answer_submit}>提交</a>
<a href={"/shixuns/" + shixunId + "/challenges"} className="defalutCancelbtn fl">取消</a>
</div>
</div>
</React.Fragment>
)
}
}
import React, {Component} from 'react';
import {Input, InputNumber, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd';
import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
// import "antd/dist/antd.css";
import { getImageUrl, toPath, getUrl } from 'educoder';
import axios from 'axios';
import './css/TPMchallengesnew.css';
import TPMMDEditor from './TPMMDEditor';
let origin = getUrl();
let path = getUrl("/editormd/lib/")
const $ = window.$;
let timeout;
let currentValue;
const Option = Select.Option;
const RadioGroup = Radio.Group;
// const testAnswers = [{
// "id": 4337,
// "name": "解题思路1",
// "contents": "答案的解题思路1",
// "level": 1,
// "score": 25
// },
// {
// "id": 4338,
// "name": "解题思路2",
// "contents": "答案的解题思路2",
// "level": 2,
// "score": 25
// }]
export default class TPManswer extends Component {
constructor(props) {
super(props)
this.state = {
choice_url: undefined,
practice_url: undefined,
go_back_url: undefined,
value: 1,
answer:"",
id:undefined,
checkpointId:undefined,
power: false,
prev_challenge: undefined,
next_challenge: undefined,
answers: [] //testAnswers
}
}
componentDidMount() {
let id = this.props.match.params.shixunId;
let checkpointId=this.props.match.params.checkpointId;
let newchoice_url= "/shixuns/"+id+"/challenges/newquestion";
let newpractice_url= "/shixuns/"+id+"/challenges/new";
let newgo_back_url="/shixuns/"+id+"/challenges";
this.setState({
shixunId:id,
checkpointId:checkpointId
})
let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=2";
axios.get(url).then((response) => {
let newprev_challenge = response.data.prev_challenge;
let next_challenge = response.data.next_challenge;
if (newprev_challenge != undefined) {
if(newprev_challenge.st===0){
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint";
}else{
newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion";
}
}
if (next_challenge != undefined) {
if(next_challenge.st===0){
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint";
}else{
next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion";
}
}
this.setState({
answer:response.data.answer,
power: response.data.power,
choice_url: newchoice_url, // 导航中的新建选择题url
practice_url: newpractice_url, //string 导航中新建实践题url
go_back_url: newgo_back_url, //string 导航中的返回url
position: response.data.position, //int 关卡位置,导航栏中的第几关
prev_challenge: newprev_challenge,
next_challenge: next_challenge,
})
if(response.data.power===false){
this.props.showSnackbar("没有权限修改");
}
// if(response.data.answer===undefined||response.data.answer===null){
// this.answerMD("", "answerMD");
// }else{
// this.answerMD(response.data.answer, "answerMD");
// }
}).catch((error) => {
console.log(error)
});
let urlAnswer = `/shixuns/${id}/challenges/${checkpointId}/answer.json`;
axios.get(urlAnswer).then((response) => {
if (response.data) {
this.setState({ answers: response.data })
}
})
}
challenge_answer_submit=()=> {
// `levelSection${index}`
// this.refs.md0
const { answers } = this.state;
const answersParams = answers.slice(0)
console.log(answersParams)
let isValidate = true;
let totalScore = 0;
answersParams.forEach( (item, index) => {
if (!isValidate) {
return;
}
const sectionId = `#levelSection${index}`;
const mdContnet = this.refs[`md${index}`].getValue().trim();;
item.contents = mdContnet;
item.name = item.name.trim()
totalScore += item.score;
delete item.id;
if (!item.name) {
this.props.showSnackbar("请先填写参考答案名称");
isValidate = false;
} else if (!mdContnet) {
this.props.showSnackbar("请先填写参考答案内容");
isValidate = false;
}
if (!isValidate) {
$("html, body").animate({ scrollTop: $(`${sectionId}`).offset().top - 100})
}
})
if (!isValidate) {
return;
}
if (totalScore != 100) {
this.props.showSnackbar("请先保证占比和为100%");
return;
}
let id = this.props.match.params.shixunId;
let {checkpointId} = this.state;
let url = `/shixuns/${id}/challenges/${checkpointId}/crud_answer.json`;
axios.post(url,{
challenge_answer: answersParams
}
).then((response) => {
if (response.data) {
if (response.data.message) {
this.props.showSnackbar(response.data.message);
}
}
}).catch((error) => {
console.log(error)
});
}
onNameChange = (e, index) => {
const newAnswer = Object.assign({}, this.state.answers[index])
newAnswer.name = e.target.value
const newAnswers = this.state.answers.slice(0)
newAnswers[index] = newAnswer
this.setState({ answers: newAnswers})
}
onScoreChange = (val, index) => {
const newAnswer = Object.assign({}, this.state.answers[index])
newAnswer.score = val
const newAnswers = this.state.answers.slice(0)
newAnswers[index] = newAnswer
this.setState({ answers: newAnswers})
}
addAnswer = () => {
const newAnswers = this.state.answers.slice(0)
newAnswers.push({
"name": `解题思路${newAnswers.length + 1}`,
"contents": "",
"score": 10
})
this.setState({ answers: newAnswers })
}
delanswers=(index)=>{
let {answers}=this.state;
let newanswers=answers;
newanswers.splice(index,1)
this.setState({
answers:newanswers
})
}
render() {
let {
choice_url,
practice_url,
go_back_url,
position,
task_pass_default,
submit_url,
shixunId,
checkpointId,
power,
prev_challenge,
next_challenge,
answers,
} = this.state;
let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint";
let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2";
let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3";
// console.log(this.props)
return (
<React.Fragment>
<div className="educontent mt30 mb30 tpmAnswer">
<div className="padding10-20 mb10 edu-back-white clearfix">
<span className="fl ring-blue mr10 mt7">
<img src={getImageUrl("images/educoder/icon/code.svg")} data-tip-down="实训任务" className="fl mt2 ml2"/>
</span>
<span className="font-16 task-hide fl TPMtaskName">{position}</span>
<Link to={go_back_url === undefined ? "" : go_back_url}
className="color-grey-6 fr font-15 mt3">返回</Link>
{prev_challenge === undefined ? "" :
<a href={prev_challenge} className="fr color-blue mr15 mt4">上一关</a>
}
{next_challenge === undefined ? "" :
<a href={next_challenge} className="fr color-blue mr15 mt4">下一关</a>
}
<Link to={practice_url === undefined ? "" : practice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增代码编辑类型的任务">+&nbsp;实践类型</Link>
<Link to={choice_url === undefined ? "" : choice_url}
className="fr color-blue mr15 mt4"
style={{display:this.props.status===2||this.props.status===1?'none':'block'}}
data-tip-down="新增选择题类型的任务">+&nbsp;选择题类型</Link>
</div>
<div className="challenge_nav clearfix edu-back-white">
<li>
<Link to={tab1url}>本关任务</Link>
</li>
<li >
<Link to={tab2url}>评测设置</Link>
</li>
<li className="active">
<Link to={tab3url}>参考答案</Link>
</li>
</div>
<div className="edu-back-white mb10 clearfix">
<div className="padding30-20">
<p className=" font-12" style={{ paddingBottom: '5px'
, color: '#666666'}}>
可以将参考答案分级设置让学员自行选择级别每级查看后按照比例扣分值学员已完成任务再查看则不影响原因已获得的成绩
</p>
<p className=" font-12 "
style={{ maxWidth: "782px"
, color: '#999999'}}>
示例级别1扣减分值占比25%级别2扣减分值占比35%级别3扣减分值占比40%则学员选择查看级别1的答案将被扣减25%的分值
选择查看级别2的答案将被扣减60%的分值选择查看级别3的答案将被扣减100%的分值
</p>
<style>{`
.tpmAnswer .ant-input { width: 230px }
.tpmAnswer .score.ant-input-number { width: 54px; }
.levelSection { margin-top: 16px }
`}</style>
{
answers.map((answer, index) => {
return <div className="levelSection" id={`levelSection${index}`}>
<span className="mr4 color-orange pt10">*</span>
<p className="color-grey-6 font-16 mb30 mt10" style={{ display: "inline" }}>级别{index + 1}</p>
<a className="fr sample_icon_remove mr30 mt8" onClick={()=>this.delanswers(index)}>
<i className="fa fa-times-circle color-grey-c font-16 fl" ></i>
</a>
<div className=" color-grey-6 font-16" style={{ marginLeft: "9px", margin: '8px 9px'}}>
<div className=" ">
<span>名称</span>
<Input value={answer.name} onChange={(e) => this.onNameChange(e, index)}></Input>
<span style={{ marginLeft: "20px"}} >扣减分值占比</span>
<InputNumber className="score" step={1} min={1} max={100} defaultValue={answer.score}
onChange={(e) => this.onScoreChange(e, index)} ></InputNumber>%
</div>
<div className="mt10">
<span>参考答案</span>
<TPMMDEditor ref={`md${index}`} mdID={index} initValue={answer.contents}></TPMMDEditor>
</div>
</div>
</div>
})
}
<div className="clearfix mt20" style={{display:this.props.identity>3||this.props.identity===undefined||power===false?"none":"block"}}>
<a href={"javascript:void(0)"} className="defalutCancelbtn fl" onClick={this.addAnswer}>新增</a>
</div>
</div>
</div>
<div className="clearfix mt20" style={{display:this.props.identity>3||this.props.identity===undefined||power===false?"none":"block"}}>
<a className="defalutSubmitbtn fl mr20"
onClick={this.challenge_answer_submit}>提交</a>
<a href={"/shixuns/" + shixunId + "/challenges"} className="defalutCancelbtn fl">取消</a>
</div>
</div>
</React.Fragment>
)
}
}

@ -765,14 +765,14 @@ export default class TPMevaluation extends Component {
</span>
<span className="font-16 task-hide fl TPMtaskName">{position}</span>
<Link to={go_back_url === undefined ? "" : go_back_url}
className="color-grey-6 fr font-16 ml30">返回</Link>
className="color-grey-6 fr font-15 mt3">返回</Link>
{prev_challenge === undefined ? "" :
<a href={prev_challenge} className="fr color-blue mr15 mt3">上一关</a>
<a href={prev_challenge} className="fr color-blue mr15 mt4">上一关</a>
}
{next_challenge === undefined ? "" :
<a href={next_challenge} className="fr color-blue mr15 mt3">下一关</a>
<a href={next_challenge} className="fr color-blue mr15 mt4">下一关</a>
}
<Link to={practice_url === undefined ? "" : practice_url}

File diff suppressed because it is too large Load Diff

@ -635,7 +635,7 @@ class Newshixuns extends Component {
this.setState({
opers: true
})
e.stopPropagation();//阻止冒泡
}
bigopens = (e) => {
@ -644,21 +644,21 @@ class Newshixuns extends Component {
operss: false,
opensmail: false
})
e.stopPropagation();//阻止冒泡
}
bigopensmal = (e) => {
this.setState({
opensmail: true
})
e.stopPropagation();//阻止冒泡
}
sbigopen = (e) => {
this.setState({
operss: true
})
e.stopPropagation();//阻止冒泡
}
// sbigopens=()=>{
@ -1196,6 +1196,7 @@ class Newshixuns extends Component {
showToday={false}
showTime
locale={locale}
style={{"width": "184px"}}
format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开启时间"
onChange={this.onChangeTimePicker}

Loading…
Cancel
Save