|
|
import React, {Component} from 'react';
|
|
|
|
|
|
import {Input, InputNumber, Select, Radio, Checkbox, Popconfirm, message, Modal, Tooltip} 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.status === 401) {
|
|
|
|
|
|
} else 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 (answersParams.length != 0 && 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);
|
|
|
}
|
|
|
if (response.data.status == 1) {
|
|
|
$("html").animate({ scrollTop: 0 })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}).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})
|
|
|
}
|
|
|
answerOnChange = (val, index) => {
|
|
|
if (!this.state.answers[index]) {
|
|
|
// 1、2、3删除2会走到这里
|
|
|
return;
|
|
|
}
|
|
|
const newAnswer = Object.assign({}, this.state.answers[index])
|
|
|
newAnswer.contents = 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
|
|
|
}, () => {
|
|
|
for(let i = index; i < newanswers.length; i ++) {
|
|
|
this.refs[`md${i}`].setValue(newanswers[i].contents)
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
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="新增代码编辑类型的任务">+ 实践类型</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="新增选择题类型的任务">+ 选择题类型</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}`} style={{ clear: 'both' }}>
|
|
|
<span className="mr4 color-orange pt10">*</span>
|
|
|
<p className="color-grey-6 font-16 mb30 mt10" style={{ display: "inline" }}>级别{index + 1}</p>
|
|
|
<Tooltip title="删除">
|
|
|
<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>
|
|
|
</Tooltip>
|
|
|
<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}
|
|
|
onChange={(val) => this.answerOnChange(val, index)}></TPMMDEditor>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
})
|
|
|
}
|
|
|
|
|
|
<div className="clearfix mt20" style={{display:this.props.identity>4||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>4||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>
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|