Merge branch 'dev_chen' of http://bdgit.educoder.net/Hjqreturn/educoder into dev_chen

dev_chen
cxt 5 years ago
commit a9ba796967

@ -33,6 +33,12 @@ module ApplicationHelper
Base64.urlsafe_encode64(content)
end
# 替换换行和tab键
def regexp_msg content
return nil if content.blank?
content.gsub(/\n/, '<br/>').gsub(/\t/, "&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;")
end
def graduation_navigation graduation
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
end

@ -1,7 +1,7 @@
json.status 0
json.message "返回成功"
json.data do
json.(@hack_user, :id, :status, :error_line, :error_msg, :expected_output,
json.(@hack_user, :id, :status, :error_line, :expected_output, :error_msg,
:input, :output, :execute_time, :execute_memory, :created_at, :code)
json.language @hack_user.language
json.name @hack_user.hack.name

@ -15012,6 +15012,18 @@
}
}
},
"react-zmage": {
"version": "0.8.5-beta.31",
"resolved": "https://registry.npm.taobao.org/react-zmage/download/react-zmage-0.8.5-beta.31.tgz",
"integrity": "sha1-kc+7Hs+Y0fYFEdDFfZEt4K+53ZY=",
"requires": {
"classnames": "^2.2.6",
"lodash.memoize": "^4.1.2",
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-dom": "^16.6.3"
}
},
"read-pkg": {
"version": "1.1.0",
"resolved": "http://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz",

@ -439,7 +439,7 @@ class App extends Component {
window.addEventListener('error', (event) => {
const msg = `${event.type}: ${event.message}`;
console.log(msg)
// console.log(msg)
});
}
//修改登录方法

@ -46,7 +46,7 @@ debugType = "admin";
// 老师
// debugType="teacher";
// 学生
//debugType="student";
debugType="student";

@ -6,39 +6,44 @@ export function isImageExtension(fileName) {
}
export function markdownToHTML(oldContent, selector) {
window.$('#md_div').html('')
// markdown to html
if (selector && oldContent && oldContent.startsWith('<p')) { // 普通html处理
window.$('#' + selector).addClass('renderAsHtml')
window.$('#' + selector).html(oldContent)
} else {
try {
$("#"+selector).html('')
// selector ||
var markdwonParser = window.editormd.markdownToHTML(selector || "md_div", {
markdown: oldContent, // .replace(/▁/g,"▁▁▁"),
emoji: true,
htmlDecode: "style,script,iframe", // you can filter tags decode
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true // 默认不解析
});
console.log(oldContent)
console.log(selector)
if(oldContent){
window.$('#md_div').html('')
// markdown to html
if (selector && oldContent && oldContent.startsWith('<p')) { // 普通html处理
window.$('#' + selector).addClass('renderAsHtml')
window.$('#' + selector).html(oldContent)
} else {
try {
$("#"+selector).html('')
// selector ||
var markdwonParser = window.editormd.markdownToHTML(selector || "md_div", {
markdown: oldContent, // .replace(/▁/g,"▁▁▁"),
emoji: true,
htmlDecode: "style,script,iframe", // you can filter tags decode
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true // 默认不解析
});
} catch(e) {
console.error(e)
}
// selector = '.' + selector
if (selector) {
return;
}
const content = window.$('#md_div').html()
if (selector) {
window.$(selector).html(content)
} catch(e) {
console.error(e)
}
// selector = '.' + selector
if (selector) {
return;
}
const content = window.$('#md_div').html()
if (selector) {
window.$(selector).html(content)
}
return content
}
return content
}
}
function _doDownload(options) {
$.fileDownload(getUrl() + "/api" + options.url, {
@ -57,7 +62,7 @@ export function downloadFile(options) {
_doDownload(options)
});
}
}
export function appendFileSizeToUploadFile(item) {
@ -67,13 +72,13 @@ export function appendFileSizeToUploadFileAll(fileList) {
return fileList.map(item => {
if (item.name.indexOf(uploadNameSizeSeperator) == -1) {
return Object.assign({}, item, {name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}`})
}
}
return item
})
})
}
export const uploadNameSizeSeperator = '  '
export const sortDirections = ["ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
export const sortDirections = ["ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", ]

@ -59,6 +59,8 @@ export { default as ActionBtn } from './course/ActionBtn'
export { default as MarkdownToHtml } from './components/markdown/MarkdownToHtml'
export { default as QuillForEditor } from './quillForEditor'
export { default as DMDEditor } from './components/markdown/DMDEditor'
export { default as Clappr } from './components/media/Clappr'

@ -28,7 +28,6 @@ export default ({ src, videoId, logWatchHistory, courseId = null }) => {
const suf = src.split('.').pop()
const isFlv = suf === 'flv'
const el = useRef()
const deviceMatch = navigator.userAgent.toLowerCase().match(regex)
const device = deviceMatch ? deviceMatch[0] : 'pc'

@ -1,30 +1,14 @@
import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import {getUrl, ActionBtn, markdownToHTML} from 'educoder';
import SingleDisplay from './new/SingleDisplay'
import JudgeDisplay from './new/JudgeDisplay'
import NullDisplay from './new/NullDisplay'
import MainDisplay from './new/MainDisplay'
import ShixunDisplay from './new/ShixunDisplay'
import ShixunProgramming from './new/ShixunProgramming'
import './new/common.css'
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
class ExerciseDisplay extends Component{
constructor(props){
@ -51,7 +35,7 @@ class ExerciseDisplay extends Component{
}
}
componentDidMount = () => {
const Id = this.props.match.params.Id
const Id = this.props.match.params.Id
if (Id) {
const url = `/${this.props.urlPath || 'exercises'}/${Id}.json`
axios.get(url)
@ -87,20 +71,7 @@ class ExerciseDisplay extends Component{
}
}
render() {
// let { question_title, question_score, question_type, question_choices, standard_answer,
// question_id, question_number, index, displayCount,
// multi_count
// } = this.props;
const { exercise_questions,exercise,exercise_types} = this.state;
// // const { getFieldDecorator } = this.props.form;
// const isAdmin = this.props.isAdmin()
// const courseId=this.props.match.params.coursesId;
// const isEdit = this.isEdit
// const qNumber = `question_${index}`;
// let length = 5;
// const qName = qNameArray[question_type]
const commonHandler = {}
return(
@ -153,42 +124,48 @@ class ExerciseDisplay extends Component{
</div>
{ exercise_questions.map((item, index) => {
if (item.question_type == 0 || item.question_type == 1) {
return <SingleDisplay {...this.props} {...item} index={index} {...commonHandler}
return <SingleDisplay {...this.props} {...item} index={index} {...commonHandler} {...this.state}
displayCount={exercise_questions.length} showActionButton={false} key={index}
></SingleDisplay>
} else if (item.question_type == 2) {
return <JudgeDisplay
showActionButton={false} key={index}
return <JudgeDisplay
showActionButton={false} key={index} {...this.state}
{...this.props} {...item} index={index} {...commonHandler} ></JudgeDisplay>
} else if (item.question_type == 3) {
return <NullDisplay
showActionButton={false} key={index}
return <NullDisplay
showActionButton={false} key={index} {...this.state}
{...this.props} {...item} index={index} {...commonHandler} ></NullDisplay>
} else if (item.question_type == 4) {
return <MainDisplay
showActionButton={false} key={index}
//
return <MainDisplay
showActionButton={false} key={index} {...this.state}
{...this.props} {...item} index={index} {...commonHandler} ></MainDisplay>
} else if (item.question_type == 5) {
return <ShixunDisplay Testpapersettinghomepage
showActionButton={false} key={index}
showActionButton={false} key={index} {...this.state}
{...this.props} {...item} index={index} {...commonHandler} ></ShixunDisplay>
}else if (item.question_type == 6) {
return <ShixunProgramming Testpapersettinghomepage
showActionButton={false} key={index} {...this.state}
{...this.props} {...item} index={index} {...commonHandler} ></ShixunProgramming>
}else{
return <div></div>
}
return <div></div>
})}
</div>
)

@ -1,94 +1,56 @@
import React,{ Component } from "react";
import React, { Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
// import './board.css'
// import "../common/formCommon.css"
import { CBreadcrumb } from 'educoder';
// import { RouteHOC } from './common.js'
// import { Q_TYPE_SINGLE, Q_TYPE_MULTI, Q_TYPE_JUDGE, Q_TYPE_NULL, Q_TYPE_MAIN, Q_TYPE_SHIXUN } from './new/common'
// import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
// import CBreadcrumb from '../common/CBreadcrumb'
import {getUrl, ActionBtn, CBreadcrumb} from 'educoder';
// import SingleEditor from './new/SingleEditor'
// import SingleDisplay from './new/SingleDisplay'
// import JudgeEditor from './new/JudgeEditor'
// import JudgeDisplay from './new/JudgeDisplay'
// import NullEditor from './new/NullEditor'
// import NullDisplay from './new/NullDisplay'
// import MainEditor from './new/MainEditor'
// import MainDisplay from './new/MainDisplay'
// import ShixunEditor from './new/ShixunEditor'
// import ShixunDisplay from './new/ShixunDisplay'
import update from 'immutability-helper'
import './new/common.css'
import '../css/Courses.css'
import ExerciseNewCommon from './ExerciseNewCommon'
const { TextArea } = Input;
class ExerciceNew extends Component{
constructor(props){
class ExerciceNew extends Component {
constructor(props) {
super(props);
this.state = {
left_banner_id: null
}
}
componentDidMount = () => {
}
initData = (data) => {
this.setState({left_banner_id: data.left_banner_id})
this.setState({ left_banner_id: data.left_banner_id })
}
componentDidMount() {
document.title = this.props.coursedata && this.props.coursedata.name;
}
render() {
let { left_banner_id } = this.state;
let { left_banner_id } = this.state;
const { current_user } = this.props
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit;
document.title=this.props.coursedata&&this.props.coursedata.name;
return(
<div className="newMain exerciseNew">
<div className="edu-class-container edu-position courseForm">
{ current_user && <CBreadcrumb items={[
{ to: current_user&&current_user.first_category_url, name: this.props.coursedata ? this.props.coursedata.name : ''},
{ to: `/classrooms/${courseId}/exercises/${left_banner_id}`, name: '试卷列表' },
{ name: this.isEdit ? '编辑试卷' : '新建试卷'}
]}></CBreadcrumb> }
<p className="clearfix mt20 mb20">
<span className="fl font-24 color-grey-3">{this.isEdit ? "编辑" : "新建"}试卷</span>
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
// () => this.props.history.length == 1 ? : this.props.history.goBack()
onClick={() => this.props.history.push(`/classrooms/${courseId}/exercises/${left_banner_id}`)}>
返回
const courseId = this.props.match.params.coursesId;
return (
<div className="newMain exerciseNew">
<div className="edu-class-container edu-position courseForm">
{current_user && <CBreadcrumb items={[
{ to: current_user && current_user.first_category_url, name: this.props.coursedata ? this.props.coursedata.name : '' },
{ to: `/classrooms/${courseId}/exercises/${left_banner_id}`, name: '试卷列表' },
{ name: this.isEdit ? '编辑试卷' : '新建试卷' }
]}></CBreadcrumb>}
<p className="clearfix mt20 mb20">
<span className="fl font-24 color-grey-3">{this.isEdit ? "编辑" : "新建"}试卷</span>
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
onClick={() => this.props.history.push(`/classrooms/${courseId}/exercises/${left_banner_id}`)}>
返回
</a>
</p>
<ExerciseNewCommon
{...this.props}
{...this.state}
isEdit={this.isEdit}
initData={this.initData}
></ExerciseNewCommon>
</div>
</p>
<ExerciseNewCommon
{...this.props}
{...this.state}
isEdit={this.isEdit}
initData={this.initData}
></ExerciseNewCommon>
</div>
)
}
</div>
)
}
}
// RouteHOC()
export default (ExerciceNew);
export default ExerciceNew;

@ -1,19 +1,10 @@
import React,{ Component } from "react";
import React, { Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import { Q_TYPE_SINGLE, Q_TYPE_MULTI, Q_TYPE_JUDGE, Q_TYPE_NULL, Q_TYPE_MAIN, Q_TYPE_SHIXUN } from './new/common'
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
import { Tooltip } from 'antd'
import { Q_TYPE_SINGLE, Q_TYPE_MULTI, Q_TYPE_JUDGE, Q_TYPE_NULL, Q_TYPE_MAIN, Q_TYPE_SHIXUN } from './new/common'
import axios from 'axios'
// import './board.css'
import "../common/formCommon.css"
// import { RouteHOC } from './common.js'
import CBreadcrumb from '../common/CBreadcrumb'
import {getUrl, ActionBtn} from 'educoder';
import { ActionBtn } from 'educoder';
import SingleEditor from './new/SingleEditor'
import SingleDisplay from './new/SingleDisplay'
@ -27,22 +18,20 @@ import ShixunEditor from './new/ShixunEditor'
import ShixunDisplay from './new/ShixunDisplay'
import ShixunChooseModal from '../coursesPublic/ShixunChooseModal'
import ExerciseForm from './exercise-new-form'
import update from 'immutability-helper'
import './new/common.css'
import '../css/Courses.css'
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const TITLE_MAX_LENGTH = 60;
class ExerciseNewCommon extends Component{
constructor(props){
class ExerciseNewCommon extends Component {
constructor(props) {
super(props);
this.state = {
exercise_questions: [],
exercise_name: '',
is_md: false,
exercise_description: '',
exercise_types: {},
editMode: !this.props.match.params.Id,
@ -50,30 +39,30 @@ class ExerciseNewCommon extends Component{
}
// 已发布试卷编辑保存的确认弹框
changeScore = (question_id,answerArray) =>{
changeScore = (question_id, answerArray) => {
this.props.confirm({
content:'修改了标准答案',
subContent:"是否重新计算学生答题的成绩?",
onOk:()=>{
this.sureChangeScore(question_id,answerArray)
content: '修改了标准答案',
subContent: "是否重新计算学生答题的成绩?",
onOk: () => {
this.sureChangeScore(question_id, answerArray)
},
onCancel:()=>{
onCancel: () => {
this.addSuccess();
}
})
}
// 已发布试卷修改答案确认修改分数
sureChangeScore = (question_id,answerArray) =>{
let url=`/exercise_questions/${question_id}/update_scores.json`
axios.post((url),{
standard_answers:answerArray
}).then((result)=>{
if(result){
sureChangeScore = (question_id, answerArray) => {
let url = `/exercise_questions/${question_id}/update_scores.json`
axios.post((url), {
standard_answers: answerArray
}).then((result) => {
if (result) {
this.props.showNotification(`${result.data.message}`);
this.addSuccess();
}
}).catch((error)=>{
}).catch((error) => {
console.log(error);
})
}
@ -82,7 +71,7 @@ class ExerciseNewCommon extends Component{
const Id = this.props.match.params.Id
this.isEdit = this.props.isEdit || !!Id
if (this.isEdit) {
const url = this.props.exercise_url ? `/${this.props.exercise_url }/${Id}.json` : `/exercises/${Id}/edit.json`
const url = this.props.exercise_url ? `/${this.props.exercise_url}/${Id}.json` : `/exercises/${Id}/edit.json`
axios.get(url)
.then((response) => {
if (response.data.exercise) {
@ -101,7 +90,7 @@ class ExerciseNewCommon extends Component{
console.log(error);
});
} else {
const courseId=this.props.match.params.coursesId;
const courseId = this.props.match.params.coursesId;
const newUrl = `/courses/${courseId}/exercises/new.json`
axios.get(newUrl)
@ -120,63 +109,54 @@ class ExerciseNewCommon extends Component{
componentDidMount = () => {
this.fetchExercise()
}
// handleSubmit = (e) => {
//
// }
onSaveExercise = () => {
const { exercise_name, exercise_description } = this.state;
onSaveExercise = (data) => {
const exercise_id = this.props.match.params.Id
const courseId = this.props.match.params.coursesId
if (this.isEdit) {
// /exercise_banks/:id.json
const editUrl = `/${this.props.exercise_url ? this.props.exercise_url : 'exercises'}/${exercise_id}.json`
axios.put(editUrl, {
exercise_name,
exercise_description
})
axios.put(editUrl, { ...data })
.then((response) => {
if (response.data.status == 0) {
this.setState({editMode: false})
this.setState({ ...data, editMode: false })
this.props.showNotification('试卷编辑成功')
}
})
.catch(function (error) {
console.log(error);
console.log(error);
});
} else {
const url = `/courses/${courseId}/exercises.json`
axios.post(url, {
exercise_name,
exercise_description
...data
})
.then((response) => {
if (response.data.status == 0) {
this.setState({editMode: false})
this.props.showNotification('试卷新建成功')
const exercise_id = response.data.data.exercise_id;
this.isEdit = true;
this.props.history.replace(`/classrooms/${courseId}/exercises/${exercise_id}/edit`);
this.setState({ ...data, editMode: false })
this.props.showNotification('试卷新建成功')
const exercise_id = response.data.data.exercise_id;
this.isEdit = true;
this.props.history.replace(`/classrooms/${courseId}/exercises/${exercise_id}/edit`);
}
})
.catch(function (error) {
console.log(error);
console.log(error);
});
}
}
exercise_name_change = (e) => {
this.setState({exercise_name: e.target.value})
this.setState({ exercise_name: e.target.value })
}
exercise_description_change = (e) => {
this.setState({exercise_description: e.target.value})
this.setState({ exercise_description: e.target.value })
}
// #问题的类型0为单选题1为多选题2为判断题3为填空题4为主观题5为实训题
_checkIsEditing = () => {
if (this.editingId && $(this.editingId).length ) {
if (this.editingId && $(this.editingId).length) {
this.props.showNotification('请先保存或取消当前正在编辑的问题。')
$("html").animate({ scrollTop: $(this.editingId).offset().top - 100})
$("html").animate({ scrollTop: $(this.editingId).offset().top - 100 })
return true
}
return false
@ -186,7 +166,7 @@ class ExerciseNewCommon extends Component{
// 找到编辑或新建的item新建就删掉item编辑就isNew改为false
const { exercise_questions } = this.state
let index = -1;
for(let i = 0; i < exercise_questions.length; i++) {
for (let i = 0; i < exercise_questions.length; i++) {
if (exercise_questions[i].isNew == true) {
index = i;
break;
@ -195,14 +175,14 @@ class ExerciseNewCommon extends Component{
if (exercise_questions[index].question_id) { // 编辑
this.setState(
(prevState) => ({
exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: false}}})
exercise_questions: update(prevState.exercise_questions, { [index]: { isNew: { $set: false } } })
// update(prevState.exercise_questions, {$splice: [[index, 1]]})
})
)
} else { // 新建
this.setState(
(prevState) => ({
exercise_questions : update(prevState.exercise_questions, {$splice: [[index, 1]]})
exercise_questions: update(prevState.exercise_questions, { $splice: [[index, 1]] })
})
)
}
@ -241,10 +221,6 @@ class ExerciseNewCommon extends Component{
this.refs.shixunChooseModal.setVisible(true)
this.question_id_to_insert_after = question_id_to_insert_after;
return;
// 拉取实训items
this.addEditingQuestion(Q_TYPE_SHIXUN, question_id_to_insert_after, {
shixun_id: 50
})
}
editQestion = (index) => {
if (this._checkIsEditing()) {
@ -254,7 +230,7 @@ class ExerciseNewCommon extends Component{
this.setState(
(prevState) => ({
exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: true}}})
exercise_questions: update(prevState.exercise_questions, { [index]: { isNew: { $set: true } } })
})
)
}
@ -264,16 +240,16 @@ class ExerciseNewCommon extends Component{
}
const url = `/${this.props.exercise_url_questions || 'exercise_questions'}/${question_id}/up_down.json`
axios.post(url, { opr: isUp ? 'up' : 'down'})
.then((response) => {
if (response.data.status == 0) {
// this.props.showNotification('移动成功')
this.fetchExercise()
}
})
.catch(function (error) {
console.log(error);
});
axios.post(url, { opr: isUp ? 'up' : 'down' })
.then((response) => {
if (response.data.status == 0) {
// this.props.showNotification('移动成功')
this.fetchExercise()
}
})
.catch(function (error) {
console.log(error);
});
}
onSortDown = (index, question_id) => {
this.onSort(index, question_id, false)
@ -304,7 +280,7 @@ class ExerciseNewCommon extends Component{
}
const _indexBefore = question_id_to_insert_after ? this.findIndexById(question_id_to_insert_after) : this.state.exercise_questions.length - 1
for (let i = _indexBefore; i >= 0; i--) {
if(this.state.exercise_questions[i].question_type == question_type) {
if (this.state.exercise_questions[i].question_type == question_type) {
init_question_score = this.state.exercise_questions[i].question_score
break;
}
@ -315,7 +291,7 @@ class ExerciseNewCommon extends Component{
let init_question_score = this.getInitScore(question_type, question_id_to_insert_after)
let questionObj = {
let questionObj = {
question_type: question_type, // 需要这个通过类型判断
init_question_score: init_question_score,
isNew: true, // 新建或编辑用是否有id区分是新建还是编辑
@ -336,13 +312,13 @@ class ExerciseNewCommon extends Component{
this.editingId = `#question_${newIndex}`
this.setState({ exercise_questions: new_exercise_questions }, () => {
setTimeout(() => {
$(this.editingId).length && $("html").animate({ scrollTop: $(this.editingId).offset().top - 100})
$(this.editingId).length && $("html").animate({ scrollTop: $(this.editingId).offset().top - 100 })
}, 500)
})
}
findIndexById = (id) => {
const { exercise_questions } = this.state
for(let i = 0; i < exercise_questions.length; i++) {
for (let i = 0; i < exercise_questions.length; i++) {
if (exercise_questions[i].question_id == id) {
return i;
}
@ -354,24 +330,15 @@ class ExerciseNewCommon extends Component{
onOk: () => {
const url = `/${this.props.exercise_url_questions || 'exercise_questions'}/${question_id}.json`
axios.delete(url)
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('删除成功')
this.fetchExercise()
// const { exercise_questions } = this.state
// const index = this.findIndexById(question_id)
// this.setState(
// (prevState) => ({
// exercise_questions : update(prevState.exercise_questions, {$splice: [[index, 1]]})
// })
// )
}
})
.catch(function (error) {
console.log(error);
});
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('删除成功')
this.fetchExercise()
}
})
.catch(function (error) {
console.log(error);
});
}
})
}
@ -393,40 +360,33 @@ class ExerciseNewCommon extends Component{
const editUrl = this.props.exercise_url_questions ? `/${this.props.exercise_url_questions}/${question_id}.json` : `/exercise_questions/${question_id}.json`
return editUrl;
}
onCancel = () => {
this.setState({
editMode: false
})
}
render() {
let { exercise_name, exercise_description, course_id, exercise_types,
exercise_questions, left_banner_id } = this.state;
// if (this.isEdit && !exercise_types) {
// return ''
// }
// const { getFieldDecorator } = this.props.form;
let { exercise_name, exercise_description, exercise_types, exercise_questions, is_md } = this.state;
const { q_counts, q_scores, q_doubles, q_doubles_scores, q_judges, q_judges_scores,
q_mains, q_mains_scores, q_nulls, q_nulls_scores, q_shixuns, q_shixuns_scores, q_singles, q_singles_scores} = exercise_types;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
// sm: { span: 8 },
sm: { span: 24 },
},
wrapperCol: {
xs: { span: 24 },
// sm: { span: 16 },
sm: { span: 24 },
},
};
q_mains, q_mains_scores, q_nulls, q_nulls_scores, q_shixuns, q_shixuns_scores, q_singles, q_singles_scores } = exercise_types;
const exerciseFormOpt = {
exercise_name,
exercise_description,
is_md,
onCancel: this.onCancel,
isEdit: this.isEdit,
onSaveHandler: this.onSaveExercise
}
const { current_user } = this.props
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const exercise_id = this.props.match.params.Id
const isEdit = this.isEdit
const commonHandler = {
onQestionDelete: this.onQestionDelete,
addSuccess: this.addSuccess,
addQuestion: this.addQuestion,
onEditorCancel: this.onEditorCancel,
changeScore:this.changeScore,
changeScore: this.changeScore,
editQestion: this.editQestion,
onSortDown: this.onSortDown,
onSortUp: this.onSortUp,
@ -438,16 +398,18 @@ class ExerciseNewCommon extends Component{
getEditQuestionUrl: this.getEditQuestionUrl,
exercise_url: this.props.exercise_url,
}
return(
<React.Fragment>
<ShixunChooseModal
ref="shixunChooseModal"
chooseShixun={this.chooseShixun}
{...this.props}
singleChoose={true}
shixunsUrl={this.props.shixunsUrl}
></ShixunChooseModal>
<style>{`
console.log(this.props)
console.log(this.state)
return (
<React.Fragment>
<ShixunChooseModal
ref="shixunChooseModal"
chooseShixun={this.chooseShixun}
{...this.props}
singleChoose={true}
shixunsUrl={this.props.shixunsUrl}
></ShixunChooseModal>
<style>{`
.courseForm .formBlock {
padding: 20px 30px 30px 30px;
border-bottom: 1px solid #EDEDED;
@ -460,166 +422,106 @@ class ExerciseNewCommon extends Component{
`}</style>
{!this.state.editMode && <div className="padding20-30" style={{ background: '#fff'}}>
<div className="displayTitle font-16">
<span>{exercise_name}</span>
<a className="fr mr6" onClick={() => { this.setState({editMode: true}) }} style={{ lineHeight: '32px'}}>
<Tooltip title="编辑"><i className="iconfont icon-bianjidaibeijing font-20 color-green"></i></Tooltip>
</a>
</div>
<div className="displayDescription color-grey-9" dangerouslySetInnerHTML={{__html: exercise_description}}
style={{whiteSpace: 'pre-wrap'}}
></div>
</div>}
{this.state.editMode && <Form {...formItemLayout}
// onSubmit={this.handleSubmit}
>
<div className="formBlock" style={{paddingBottom: '2px',borderBottom:"none"}}>
<Form.Item
label="试卷标题"
required
className="topicTitle "
>
{/* {getFieldDecorator('subject', {
rules: [{
required: true, message: '请输入标题',
}, {
max: 20, message: '最大限制为20个字符',
}],
})( */}
<style>
{
`
.exercicenewinputysl .ant-input{
border-right: none !important;
height: 40px !important;
}
`
}
</style>
<Input placeholder={`请输入试卷标题,最大限制${TITLE_MAX_LENGTH}个字符`} maxLength={TITLE_MAX_LENGTH} className="mt5 exercicenewinputysl" value={exercise_name}
onChange={this.exercise_name_change} addonAfter={`${exercise_name ? exercise_name.length : 0}/${TITLE_MAX_LENGTH}`}
/>
{/* )} */}
</Form.Item>
<Form.Item
label="&nbsp;&nbsp;试卷须知"
>
{/* {getFieldDecorator('select_board_id', {
// initialValue: '3779',
})( */}
<TextArea placeholder="请在此输入本次试卷答题的相关说明最大限制100个字符" className="mt5" style={{height:"120px"}} value={exercise_description}
onChange={this.exercise_description_change}
/>
{/* )} */}
</Form.Item>
<Form.Item>
{/* defalutSubmitbtn */}
<a className="task-btn task-btn-orange fr mt4" style={{height: '30px', width: '70px'}}
onClick={this.onSaveExercise}
>保存</a>
{ this.isEdit && <a onClick={() => this.setState({editMode: false})} className="defalutCancelbtn fr mt4"
style={{height: '30px', width: '70px', fontSize: '14px', lineHeight: '30px', marginRight: '16px'}}>取消</a>}
{/* <Button type="primary" onClick={this.onSaveExercise} className="fr">保存</Button> */}
</Form.Item>
</div>
{/* <div className="clearfix mt30 mb30">
<a className="defalutCancelbtn fl" onClick={() => {}}>取消</ a>
</div> */}
</Form>}
<p className="clearfix padding20-30 color-grey-9">
<span className="fl">
{ !!q_singles && <span className="mr20">单选题{q_singles}{q_singles_scores}</span>}
{ !!q_doubles && <span className="mr20">多选题{q_doubles}{q_doubles_scores}</span>}
{ !!q_judges && <span className="mr20">判断题{q_judges}{q_judges_scores}</span>}
{ !!q_nulls && <span className="mr20">填空题{q_nulls}{q_nulls_scores}</span>}
{ !!q_mains && <span className="mr20">简答题{q_mains}{q_mains_scores}</span>}
{ !!q_shixuns && <span className="mr20">实训题{q_shixuns}{q_shixuns_scores}</span> }
</span>
<span className="fr">
{ !!q_counts &&
<span>
合计 <span className="color-blue">{q_counts}</span>
{!this.state.editMode && <div className="padding20-30" style={{ background: '#fff' }}>
<div className="displayTitle font-16">
<span>{exercise_name}</span>
<a className="fr mr6" onClick={() => { this.setState({ editMode: true }) }} style={{ lineHeight: '32px' }}>
<Tooltip title="编辑"><i className="iconfont icon-bianjidaibeijing font-20 color-green"></i></Tooltip>
</a>
</div>
<div className="displayDescription color-grey-9" dangerouslySetInnerHTML={{ __html: exercise_description }}
style={{ whiteSpace: 'pre-wrap' }}
></div>
</div>}
{this.state.editMode && <ExerciseForm {...exerciseFormOpt} />}
<p className="clearfix padding20-30 color-grey-9">
<span className="fl">
{!!q_singles && <span className="mr20">单选题{q_singles}{q_singles_scores}</span>}
{!!q_doubles && <span className="mr20">多选题{q_doubles}{q_doubles_scores}</span>}
{!!q_judges && <span className="mr20">判断题{q_judges}{q_judges_scores}</span>}
{!!q_nulls && <span className="mr20">填空题{q_nulls}{q_nulls_scores}</span>}
{!!q_mains && <span className="mr20">简答题{q_mains}{q_mains_scores}</span>}
{!!q_shixuns && <span className="mr20">实训题{q_shixuns}{q_shixuns_scores}</span>}
</span>
<span className="fr">
{!!q_counts &&
<span>
合计 <span className="color-blue">{q_counts}</span>
<span className={`${q_scores > 100 ? 'color-red font-bd' : 'color-orange'}`}>{q_scores}</span>
</span>
}
</span>
</p>
<div className="edu-back-white">
{ exercise_questions.map((item, index) => {
if (item.question_type == 0 || item.question_type == 1) {
if (item.isNew) {
return <SingleEditor {...this.props} {...item} index={index} {...commonHandler}></SingleEditor>
} else {
return <SingleDisplay {...this.props} {...item} index={index} {...commonHandler}
displayCount={exercise_questions.length}
></SingleDisplay>
}
} else if (item.question_type == 2) {
if (item.isNew) {
return <JudgeEditor {...this.props} {...item} index={index} {...commonHandler}></JudgeEditor>
} else {
return <JudgeDisplay {...this.props} {...item} index={index} {...commonHandler} ></JudgeDisplay>
}
} else if (item.question_type == 3) {
if (item.isNew) {
return <NullEditor {...this.props} {...item} index={index} {...commonHandler}></NullEditor>
} else {
return <NullDisplay {...this.props} {...item} index={index} {...commonHandler} ></NullDisplay>
}
} else if (item.question_type == 4) {
if (item.isNew) {
return <MainEditor {...this.props} {...item} index={index} {...commonHandler} ></MainEditor>
} else {
return <MainDisplay {...this.props} {...item} index={index} {...commonHandler} ></MainDisplay>
}
} else if (item.question_type == 5) {
if (item.isNew) {
return <ShixunEditor {...this.props} {...item} index={index} {...commonHandler}
chooseShixunSuccess={this.chooseShixunSuccess}
></ShixunEditor>
} else {
return <ShixunDisplay {...this.props} {...item} index={index} {...commonHandler} ></ShixunDisplay>
}
}
return <div></div>
})}
}
</span>
</p>
<div className="edu-back-white">
{exercise_questions.map((item, index) => {
if (item.question_type == 0 || item.question_type == 1) {
if (item.isNew) {
return <SingleEditor {...this.props} {...item} index={index} {...commonHandler}></SingleEditor>
} else {
return <SingleDisplay {...this.props} {...item} index={index} {...commonHandler}
displayCount={exercise_questions.length}
></SingleDisplay>
}
} else if (item.question_type == 2) {
if (item.isNew) {
return <JudgeEditor {...this.props} {...item} index={index} {...commonHandler}></JudgeEditor>
} else {
return <JudgeDisplay {...this.props} {...item} index={index} {...commonHandler} ></JudgeDisplay>
}
} else if (item.question_type == 3) {
if (item.isNew) {
return <NullEditor {...this.props} {...item} index={index} {...commonHandler}></NullEditor>
} else {
return <NullDisplay {...this.props} {...item} index={index} {...commonHandler} ></NullDisplay>
}
} else if (item.question_type == 4) {
if (item.isNew) {
return <MainEditor {...this.props} {...item} index={index} {...commonHandler} ></MainEditor>
} else {
return <MainDisplay {...this.props} {...item} index={index} {...commonHandler} ></MainDisplay>
}
} else if (item.question_type == 5) {
if (item.isNew) {
return <ShixunEditor {...this.props} {...item} index={index} {...commonHandler}
chooseShixunSuccess={this.chooseShixunSuccess}
></ShixunEditor>
} else {
return <ShixunDisplay {...this.props} {...item} index={index} {...commonHandler} ></ShixunDisplay>
}
}
return <div></div>
})}
{!commonHandler.exerciseIsPublish && <div className="problemShow padding30">
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_SINGLE)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block'}}></i>
{!commonHandler.exerciseIsPublish && <div className="problemShow padding30">
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_SINGLE)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block' }}></i>
</ActionBtn>
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_JUDGE)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block'}}></i>
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_JUDGE)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block' }}></i>
</ActionBtn>
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_NULL)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block'}}></i>
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_NULL)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block' }}></i>
</ActionBtn>
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_MAIN)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block'}}></i>
<ActionBtn style="green" className="mr20" onClick={() => this.addQuestion(null, Q_TYPE_MAIN)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block' }}></i>
</ActionBtn>
<ActionBtn style="green" className="mr20" onClick={() => this.addShixun(null)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block'}}></i>
<ActionBtn style="green" className="mr20" onClick={() => this.addShixun(null)}>
<i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block' }}></i>
</ActionBtn>
{exercise_id && !this.props.hidePreviewButton && <ActionBtn style="blue" className="fr" onClick={() => this.goToPreview()}>
{/* <i className="iconfont icon-tianjiafangda color-white font-14 mr5" style={{ marginTop: '-1px', display: 'inline-block'}}></i> */}
试卷预览
{exercise_id && !this.props.hidePreviewButton && <ActionBtn style="blue" className="fr" onClick={() => this.goToPreview()}>
试卷预览
</ActionBtn>}
{this.props.bottomSection && this.props.bottomSection}
</div>}
</div>
</React.Fragment>
)
}
{this.props.bottomSection && this.props.bottomSection}
</div>}
</div>
</React.Fragment>
)
}
}
// RouteHOC()
export default (ExerciseNewCommon);

@ -10,12 +10,13 @@ import moment from 'moment';
import { WordsBtn,markdownToHTML,ActionBtn,getImageUrl, MarkdownToHtml } from 'educoder';
import Modals from '../../modals/Modals';
import CoursesListType from '../coursesPublic/CoursesListType';
import QuillForEditor from "../../../common/quillForEditor";
import Multiple from './question/multiple';
import Single from './question/single';
import FillEmpty from './question/fillEmpty';
import SimpleAnswer from './question/simpleAnswer';
import ShixunAnswer from './question/shixunAnswer';
import QuestionModalPicture from '../../question/component/QuestionModalPicture'
import update from 'immutability-helper';
@ -37,7 +38,7 @@ const tagArray = [
const $ = window.$;
const statudmap={1:"未发布",2:"已发布",3:"已截止"}
const type=["单选题","多选题","判断题","填空题","简答题","实训题"]
const type=["单选题","多选题","判断题","填空题","简答题","实训题","编程题"]
const format="YYYY-MM-DD HH:mm"
class ExerciseReviewAndAnswer extends Component{
@ -86,8 +87,12 @@ class ExerciseReviewAndAnswer extends Component{
// 加载效果
isSpin:false,
// 调分数组
ajustSore:undefined
}
ajustSore:undefined,
//是否是md编辑器
is_md:false,
url: "",
}
}
componentDidUpdate (prevProps) {
// 需要等get_user_info执行完才能getInfo
@ -102,6 +107,18 @@ class ExerciseReviewAndAnswer extends Component{
//window.addEventListener('scroll', this.handleScroll);
}
handleShowUploadImage = (url) => {
// console.log('==============>>>>>>>>>>>>',url);
// setUrl(url);
this.setState({
url:url
})
}
handleClose=()=>{
this.setState({
url:'',
})
}
remainTime=(time)=>{
// let { time } = this.state;
@ -206,6 +223,7 @@ class ExerciseReviewAndAnswer extends Component{
data:result.data,
e_ReviewInfo:result.data,
exercise:result.data.exercise,
is_md:result.data.exercise.is_md,
exercise_types:result.data.exercise_scores.exercise_types,
exercise_scores:result.data.exercise_scores,
exercise_start_at:result.data.exercise_answer_user.start_at,
@ -633,7 +651,9 @@ class ExerciseReviewAndAnswer extends Component{
Loadtype,
exerciseTotalScore,
isSpin,
ajustSore
ajustSore,
is_md,
url
}=this.state
let isAdmin = this.props.isAdmin();
let isStudent =this.props.isStudent();
@ -670,8 +690,15 @@ class ExerciseReviewAndAnswer extends Component{
.standardAnswer.editormd-html-preview,.answerStyle.editormd-html-preview{
width:100%!important
}
.ql-editor{
padding:0px !important
}
`}</style>
{/*<p style={{height:"60px"}}></p>*/}
{url?
<QuestionModalPicture {...this.props} {...this.state} handleClose={()=>this.handleClose()}></QuestionModalPicture>
:
""
}
<Modals
modalsType={Modalstype}
modalsTopval={Modalstopval}
@ -745,6 +772,10 @@ class ExerciseReviewAndAnswer extends Component{
exercise_types && exercise_types.q_shixuns > 0 &&
<span className="color-grey-9 mr15">实训题 {exercise_types.q_shixuns} , {exercise_types && exercise_types.q_shixuns_scores} </span>
}
{
exercise_types && exercise_types.q_pros > 0 &&
<span className="color-grey-9 mr15">编程题 {exercise_types.q_pros} , {exercise_types && exercise_types.q_pros_scores} </span>
}
<span className="color-grey-3 fr"><span className="color-orange-tip"> {exercise_types &&exercise_types.q_scores} </span></span>
<span className="color-grey-3 fr">合计<span className="color-blue"> {exercise_types &&exercise_types.q_counts} </span></span>
</p>
@ -831,6 +862,28 @@ class ExerciseReviewAndAnswer extends Component{
{
exercise_questions && exercise_questions.map((item,key)=>{
let list = ajustSore && ajustSore.filter(obj => obj.id === item.question_id);
let titename="";
if(is_md===true){
console.log(is_md);
titename=(item.question_type == 5 ? item.shixun_name : item.question_title);
}else{
try {
titename = JSON.parse(item.question_title);
}catch (e) {
titename={"ops":[{"insert":item.question_title}]};
}
if(titename===undefined){
titename={"ops":[{"insert":item.question_title}]};
}
try {
// JSON.parse 转换的时候如果是数字字符串就转成整数了
if(titename>=0){
titename={"ops":[{"insert":item.question_title}]};
}
}catch (e) {
}
}
return(
<div className="bor-top-greyE pt30 pb30" id={"Anchor_"+parseInt(key+1)}>
<p className="clearfix font-16 pl30 pr30">
@ -869,9 +922,19 @@ class ExerciseReviewAndAnswer extends Component{
</p>
<li className="break_word mt15 mb15 pl30 pr30">
{/* <p className="standardAnswer markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML1(item.question_type == 5 ? item.shixun_name : item.question_title).replace(/▁/g,"▁▁▁")}}></p> */}
<MarkdownToHtml content={(item.question_type == 5 ? item.shixun_name : item.question_title)} selector={'answer_' + key}
className="standardAnswer"
></MarkdownToHtml>
{
is_md===true?
<MarkdownToHtml content={titename} selector={'answer_' + key}
className="standardAnswer"
></MarkdownToHtml>
:
<QuillForEditor
readOnly={true}
value={titename}
showUploadImage={this.handleShowUploadImage}
/>
}
</li>
{
// 选择题和判断题共用
@ -879,12 +942,14 @@ class ExerciseReviewAndAnswer extends Component{
<Single
{...this.props}
{...this.state}
is_md={is_md}
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
changeOption={(index,ids)=>this.changeOption(index,ids)}
changeQuestionStatus={(No,flag)=>this.changeQuestionStatus(No,flag)}
index={key}
handleShowUploadImage={(u)=>this.handleShowUploadImage(u)}
></Single>
}
{
@ -893,13 +958,14 @@ class ExerciseReviewAndAnswer extends Component{
<Multiple
{...this.props}
{...this.state}
exercise={exercise}
is_md={is_md}
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
changeOption={(index,ids)=>this.changeOption(index,ids)}
changeQuestionStatus={(No,flag)=>this.changeQuestionStatus(No,flag)}
index={key}
handleShowUploadImage={(u)=>this.handleShowUploadImage(u)}
></Multiple>
}
{
@ -910,10 +976,11 @@ class ExerciseReviewAndAnswer extends Component{
{...this.state}
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
is_md={is_md}
user_exercise_status={user_exercise_status}
changeQuestionStatus={(No,flag)=>this.changeQuestionStatus(No,flag)}
index={key}
handleShowUploadImage={(u)=>this.handleShowUploadImage(u)}
></FillEmpty>
}
{
@ -922,13 +989,15 @@ class ExerciseReviewAndAnswer extends Component{
<SimpleAnswer
{...this.props}
{...this.state}
exercise={exercise}
is_md={is_md}
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
changeQuestionStatus={(No,flag)=>this.changeQuestionStatus(No,flag)}
changeA_flag={(index,status)=>this.changeA_flag(index,status)}
index={key}
></SimpleAnswer>
handleShowUploadImage={(u)=>this.handleShowUploadImage(u)}
></SimpleAnswer>
}
{
// 实训题
@ -936,12 +1005,13 @@ class ExerciseReviewAndAnswer extends Component{
<ShixunAnswer
{...this.props}
{...this.state}
exercise={exercise}
is_md={is_md}
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
id={this.state.Id}
index={key}
handleShowUploadImage={(u)=>this.handleShowUploadImage(u)}
></ShixunAnswer>
}

@ -0,0 +1,101 @@
import React, { useState } from 'react'
import { Input, Form, Radio } from 'antd'
import './index.scss'
import { QuillForEditor } from 'educoder'
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor'
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 24 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 24 },
},
}
const { TextArea } = Input
const TITLE_MAX_LENGTH = 60
function EditorTip() {
return <p className='editor-tip'>编辑器选择<span> (请在下方选择一个您想使用的编辑器) </span></p>
}
const quillOpt = [
'bold',
'italic',
'underline', // 线
{ align: [] }, //
{ list: 'ordered' }, //
{ list: 'bullet' }, //
{ script: 'sub' }, // x2
{ script: 'super' }, // (x2)
{ 'color': [] }, //
{ 'background': [] }, //
'blockquote', //
'image', //
'formula', //
'clean' //
]
export default ({ exercise_name = '', exercise_description, is_md, onSaveHandler, isEdit, onCancel }) => {
const [data, setData] = useState({
exercise_name,
exercise_description,
is_md
})
function onChange(prop, value) {
setData({ ...data, [prop]: value })
}
function onNameChange(e) {
onChange('exercise_name', e.target.value)
}
function onDescChange(e) {
onChange('exercise_description', e.target.value)
}
function onEditorChange(e) {
onChange('is_md', e.target.value)
}
function onSave() {
onSaveHandler(data)
}
return (
<Form {...formItemLayout}>
<div className='exercise-new-form'>
<Form.Item label="试卷标题" required className="topicTitle " >
<Input placeholder={`请输入试卷标题,最大限制${TITLE_MAX_LENGTH}个字符`} maxLength={TITLE_MAX_LENGTH} className="mt5 exercicenewinputysl" value={data.exercise_name}
onChange={onNameChange} addonAfter={`${data.exercise_name.length}/${TITLE_MAX_LENGTH}`}
/>
</Form.Item>
<Form.Item label="&nbsp;&nbsp;试卷须知" >
<TextArea placeholder="请在此输入本次试卷答题的相关说明最大限制100个字符" className="mt5" style={{ height: "120px" }} value={data.exercise_description} onChange={onDescChange} />
</Form.Item>
<Form.Item label={<EditorTip />} colon={false}>
<Radio.Group onChange={onEditorChange} value={data.is_md}>
<Radio value={true}>Markdown 编辑器</Radio>
<Radio value={false}>富文本编辑器</Radio>
</Radio.Group>
</Form.Item>
<Form.Item>
{data.is_md ? <TPMMDEditor height={183} placeholder="体验过程输入的内容不会保存" refreshTimeout={1500} className="courseMessageMD" />
: <QuillForEditor placeholder='体验过程输入的内容不会保存' options={quillOpt} style={{ height: 123 }} />}
</Form.Item>
<Form.Item>
<a className="task-btn task-btn-orange fr mt4" onClick={onSave} >保存</a>
{isEdit && <a onClick={onCancel} className="defalutCancelbtn fr mt4">取消</a>}
</Form.Item>
</div>
</Form >
)
}

@ -0,0 +1,47 @@
.exercise-new-form {
padding: 20px 30px 2px 30px;
background: #fff;
.ant-input {
border-right: none;
height: 40px;
}
.task-btn-orange {
height: 30px;
width: 70px;
}
.defalutCancelbtn {
height: '30px';
width: '70px';
font-size: '14px';
line-height: '30px';
margin-right: '16px';
}
.editor-tip {
font-size: 16px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: rgba(51, 51, 51, 1);
padding-left: 12px;
line-height: 22px;
span {
font-size: 14px;
font-weight: normal;
font-family: MicrosoftYaHei;
color: rgba(136, 136, 136, 1);
line-height: 19px;
}
}
.ant-form-item label {
overflow: hidden;
}
.ant-form-item-label {
height: 40px;
}
}

@ -1,24 +1,8 @@
import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import { qNameArray } from './common'
import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml } from 'educoder';
import { Radio } from 'antd';
import { MarkdownToHtml } from 'educoder';
import QestionDisplayHeader from './QestionDisplayHeader'
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
class JudgeDisplay extends Component{
constructor(props){
@ -31,7 +15,7 @@ class JudgeDisplay extends Component{
}
}
componentDidMount = () => {
const Id = this.props.match.params.Id
const Id = this.props.match.params.Id
this.isEdit = !!Id
if (Id) {
const url = `/exercises/${Id}/edit.json`
@ -47,23 +31,12 @@ class JudgeDisplay extends Component{
}
}
render() {
let { question_title, question_score, question_type, question_choices, standard_answer,
question_id, question_number, index, displayCount
let { question_choices,
question_id, index
} = this.props;
// const { getFieldDecorator } = this.props.form;
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit
const qNumber = `question_${index}`;
// TODO show模式 isNew为false isEdit为false
// [true, false, true] -> [0, 2]
// const answerTagArray = standard_answer.map((item, index) => { return item == true ? tagArray[index] : -1 }).filter(item => item != -1);
let length = 5;
const qName = qNameArray[question_type]
return(
<div className="bor-bottom-greyE padding20-30" id={qNumber} _id={question_id}>
<style>{`
@ -87,16 +60,15 @@ class JudgeDisplay extends Component{
return (
<div key={optionIndex} className="fl mr30 df">
<Radio disabled className="lineh-25" checked={item.standard_boolean}></Radio>
{/* <span>{item.choice_text}</span> */}
<MarkdownToHtml content={item.choice_text} selector={'judge_' + (index + 1) + optionIndex}
<MarkdownToHtml content={item.choice_text} selector={'judge_' + (index + 1) + optionIndex}
className=""
></MarkdownToHtml>
{/* <span style={{ display: 'inline-block'}} className="markdown-body"
dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}
</div>)
})}
</div>
</div>
)

@ -1,24 +1,8 @@
import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import { qNameArray } from './common'
import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml} from 'educoder';
import { MarkdownToHtml,QuillForEditor} from 'educoder';
import QestionDisplayHeader from './QestionDisplayHeader'
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
class MainDisplay extends Component{
constructor(props){
@ -31,23 +15,14 @@ class MainDisplay extends Component{
componentDidMount = () => {
}
render() {
let { question_title, question_score, question_type, standard_answer,
question_id, question_number, index, displayCount
let {standard_answer,
question_id, index
} = this.props;
// const { getFieldDecorator } = this.props.form;
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit
const qNumber = `question_${index}`;
// TODO show模式 isNew为false isEdit为false
// [true, false, true] -> [0, 2]
// const answerTagArray = standard_answer.map((item, index) => { return item == true ? tagArray[index] : -1 }).filter(item => item != -1);
let length = 5;
const qName = qNameArray[question_type]
return(
<div className="bor-bottom-greyE padding20-30" id={qNumber} _id={question_id}>
<style>{`
@ -64,24 +39,25 @@ class MainDisplay extends Component{
`}</style>
<QestionDisplayHeader {...this.props}></QestionDisplayHeader>
{ standard_answer[0] &&
{ standard_answer[0] &&
<React.Fragment>
<div style={{color: '#05101A'}} className="font-16 mb5 font-bd">参考答案</div>
<MarkdownToHtml content={standard_answer[0]} selector={'answer_' + qNumber}
{!this.props.exercise||this.props.exercise&&this.props.exercise.is_md?<MarkdownToHtml content={standard_answer[0]} selector={'answer_' + qNumber}
className=""
></MarkdownToHtml>
{/* <div className="mainQuestionDisplay markdown-body"
dangerouslySetInnerHTML={{__html: markdownToHTML1(standard_answer[0])}}
>
</div> */}
</React.Fragment>
></MarkdownToHtml>:<QuillForEditor
readOnly={true}
style={{ float: 'left', display: 'inline-block' ,padding:'0px',margin: '2px 0px 0px'}}
value={standard_answer[0]?JSON.parse(standard_answer[0]):""}
// showUploadImage={this.handleShowUploadImage}
/>}
</React.Fragment>
}
</div>
)
}
}
// RouteHOC()
export default (MainDisplay);

@ -1,24 +1,7 @@
import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import { qNameArray } from './common'
import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml} from 'educoder';
import {QuillForEditor,MarkdownToHtml} from 'educoder';
import QestionDisplayHeader from './QestionDisplayHeader'
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
class NullDisplay extends Component{
constructor(props){
@ -31,7 +14,7 @@ class NullDisplay extends Component{
}
}
componentDidMount = () => {
const Id = this.props.match.params.Id
const Id = this.props.match.params.Id
this.isEdit = !!Id
if (Id) {
const url = `/exercises/${Id}/edit.json`
@ -47,16 +30,10 @@ class NullDisplay extends Component{
}
}
render() {
let { question_title, question_score, question_type, question_choices, standard_answer,
question_id, question_number, index, displayCount,
multi_count
let { question_type, standard_answer,
question_id,index,
} = this.props;
// const { getFieldDecorator } = this.props.form;
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit
const qNumber = `question_${index}`;
/**
is_ordered: true
@ -68,8 +45,7 @@ class NullDisplay extends Component{
question_type: 3
standard_answer: [{choice_id: 1, answer_text: ["2", "22"]}]
*/
let length = 5;
const qName = qNameArray[question_type]
return(
<div className="bor-bottom-greyE padding20-30" id={qNumber} _id={question_id}>
<style>{`
@ -98,31 +74,32 @@ class NullDisplay extends Component{
`}</style>
<QestionDisplayHeader {...this.props}></QestionDisplayHeader>
{/* <span>{index+1}</span>
<div className="answers">
{ answers.map((item, itemIndex) => {
return <span className="answer" key={itemIndex}>{item}</span>
})}
</div> */}
<div className="options">
{
{
standard_answer.map((answers, _index) => {
return <div className="df answerRow" key={_index}>
<span className="lineh-40">答案填空{_index+1}</span>
<div className="answers">
{ answers.answer_text.map((item, itemIndex) => {
return <MarkdownToHtml
return(
!this.props.exercise||this.props.exercise&&this.props.exercise.is_md?<MarkdownToHtml
className="answer" key={itemIndex}
content={item} selector={'null_' + (index + 1) + (_index + 1) + (itemIndex + 1)}
></MarkdownToHtml>
content={item} selector={'null_' + (index + 1) + (_index + 1) + (itemIndex + 1)}
></MarkdownToHtml>:<QuillForEditor
readOnly={true}
style={{ float: 'left', display: 'inline-block' ,padding:'0px',margin: '2px 0px 0px'}}
value={item?JSON.parse(item):""}
// showUploadImage={this.handleShowUploadImage}
/>
)
})}
{/* <span className="answer" key={itemIndex}>{item}</span> */}
</div>
</div>
})
}
</div>
</div>
)

@ -1,17 +1,8 @@
import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import {Tooltip} from 'antd';
import { qNameArray } from './common'
import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml} from 'educoder';
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
import {QuillForEditor, MarkdownToHtml} from 'educoder';
class QestionDisplayHeader extends Component{
constructor(props){
@ -19,24 +10,26 @@ class QestionDisplayHeader extends Component{
this.state = {
}
}
componentDidMount = () => {
}
render() {
let { question_title, question_score, question_type, question_choices, standard_answer,
question_id, question_number, index, displayCount,
let { question_title, question_score, question_type,
question_id, index, displayCount,
topRight, showActionButton, exerciseIsPublish
} = this.props;
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit
const qNumber = `question_${index}`;
// const isAdmin = this.props.isAdmin()
// const courseId=this.props.match.params.coursesId;
// const isEdit = this.isEdit
// const qNumber = `question_${index}`;
const qName = qNameArray[question_type]
console.log(this.props)
return(
<React.Fragment>
<div className="new_li">
@ -44,6 +37,9 @@ class QestionDisplayHeader extends Component{
.actionBtns {
height: 28px
}
.ql-editor{
padding:0px !important;
}
`}</style>
<div className="font-16 fl">
<span className="color-blue">{index+1}{qName}</span>
@ -80,11 +76,16 @@ class QestionDisplayHeader extends Component{
</React.Fragment>}
</div>
</div>
{ question_title &&
<MarkdownToHtml content={question_title} selector={'qtitle_' + (index + 1)} style={{ display: 'inline-block', width:'100%' , margin: '10px 0px 15px' }}
></MarkdownToHtml>
// <div className="markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML1(question_title)}}
{ question_title &&
!this.props.exercise||this.props.exercise&&this.props.exercise.is_md||this.props.question_type===6?<MarkdownToHtml content={question_title} selector={'qtitle_' + (index + 1)} style={{ display: 'inline-block', width:'100%' , margin: '10px 0px 15px' }}
></MarkdownToHtml>:<QuillForEditor
style={{ display: 'inline-block', width:'100%' , margin: '10px 0px 15px',padding:'0px'}}
readOnly={true}
value={question_title?JSON.parse(question_title):""}
// showUploadImage={this.handleShowUploadImage}
/>
// <div className="markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML1(question_title)}}
// style={{ display: 'inline-block', width:'100%' , margin: '10px 0px 15px' }}></div>
}
</React.Fragment>

@ -1,25 +1,7 @@
import React,{ Component } from "react";
import {Link} from 'react-router-dom';
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import { qNameArray } from './common'
import {getUrl, ActionBtn, markdownToHTML} from 'educoder';
import {QuillForEditor,markdownToHTML} from 'educoder';
import QestionDisplayHeader from './QestionDisplayHeader'
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
class ShixunDisplay extends Component{
constructor(props){
@ -32,17 +14,17 @@ class ShixunDisplay extends Component{
componentDidMount = () => {
}
render() {
let { question_title, question_score, question_type, standard_answer,
question_id, question_number, index, displayCount,
let { question_title,
question_id, index,
shixun_name, shixun, shixun_id, shixun_identifier
shixun_name, shixun, shixun_identifier
} = this.props;
// const { getFieldDecorator } = this.props.form;
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit
// const isAdmin = this.props.isAdmin()
// const courseId=this.props.match.params.coursesId;
// const isEdit = this.isEdit
const qNumber = `question_${index}`;
// TODO show模式 isNew为false isEdit为false
@ -102,8 +84,8 @@ class ShixunDisplay extends Component{
]
}
*/
let length = 5;
const qName = qNameArray[question_type]
// let length = 5;
// const qName = qNameArray[question_type]
return(
<div className="bor-bottom-greyE padding20-30" id={qNumber} _id={question_id}>
<style>{`
@ -121,12 +103,17 @@ class ShixunDisplay extends Component{
>实训详情</a>
}
></QestionDisplayHeader>
{/* <div style={{color: '#05101A', fontWeight: 'bold'}}>参考答案:</div> */}
<div className="mainQuestionDisplay color-grey-9 markdown-body"
{!this.props.exercise||this.props.exercise&&this.props.exercise.is_md?<div className="mainQuestionDisplay color-grey-9 markdown-body"
dangerouslySetInnerHTML={{__html: markdownToHTML(question_title)}}
>
</div>
</div>:<QuillForEditor
readOnly={true}
style={{ float: 'left', display: 'inline-block' ,padding:'0px',margin: '2px 0px 0px'}}
value={question_title?JSON.parse(question_title):""}
// showUploadImage={this.handleShowUploadImage}
/>}
{shixun.map((ch, index) => {
return <div>

@ -0,0 +1,67 @@
import React,{ Component } from "react";
import {MarkdownToHtml,QuillForEditor} from 'educoder';
import QestionDisplayHeader from './QestionDisplayHeader'
class ShixunProgramming extends Component{
constructor(props){
super(props);
this.state = {
}
}
componentDidMount = () => {
}
render() {
let { description,question_title,
question_id, index, shixun_identifier,hack_identifier
} = this.props;
const qNumber = `question_${index}`;
// console.log(this.props)
// console.log(this.state)
// question_id: 32336
// q_position: 4
// question_title: "C语言测试排序3333333333"
// question_type: 6
// question_score: "10.0"
return(
<div className="bor-bottom-greyE padding20-30" id={qNumber} _id={question_id}>
<style>{`
.mainQuestionDisplay {
margin-bottom:15px;
}
`}</style>
<QestionDisplayHeader {...this.props} question_title={question_title}
topRight={
<a target="_blank" href={`/problems/${hack_identifier}/edit`} className="mr30"
style={{color: '#4CACFF'}}
>实训详情</a>
}
></QestionDisplayHeader>
{description&&
!this.props.exercise||this.props.exercise&&this.props.exercise.is_md?<MarkdownToHtml content={description} selector={'qtitle_' + (index + 1)} style={{ display: 'inline-block', width:'100%' , margin: '10px 0px 15px' }}
></MarkdownToHtml>:<QuillForEditor
style={{ display: 'inline-block', width:'100%' , margin: '10px 0px 15px',padding:'0px'}}
readOnly={true}
value={description?JSON.parse(description):""}
// showUploadImage={this.handleShowUploadImage}
/>}
{/*{shixun.map((ch, index) => {*/}
{/* return <div>*/}
{/* {`第${index+1}关`} {ch.challenge_name} {ch.challenge_score}分*/}
{/* </div>*/}
{/*})}*/}
</div>
)
}
}
export default ShixunProgramming;

@ -1,31 +1,13 @@
import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Tooltip
} from 'antd';
import axios from 'axios'
import { Radio, Checkbox } from 'antd';
import QestionDisplayHeader from './QestionDisplayHeader'
import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml} from 'educoder';
const { TextArea } = Input;
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
import {MarkdownToHtml,QuillForEditor} from 'educoder';
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
const qNameArray = [
'单选题',
'多选题',
'判断题',
'填空题',
'简答题',
'实训题',
]
class SingleDisplay extends Component{
constructor(props){
super(props);
@ -53,25 +35,15 @@ class SingleDisplay extends Component{
}
}
render() {
let { question_title, question_score, question_type, question_choices, standard_answer,
question_id, question_number, index, displayCount, showActionButton
let { question_type, question_choices,
question_id, index,
} = this.props;
// const { getFieldDecorator } = this.props.form;
const isAdmin = this.props.isAdmin()
const courseId=this.props.match.params.coursesId;
const isEdit = this.isEdit
const qNumber = `question_${index}`;
// TODO show模式 isNew为false isEdit为false
// [true, false, true] -> [0, 2]
// const answerTagArray = standard_answer.map((item, index) => { return item == true ? tagArray[index] : -1 }).filter(item => item != -1);
let length = 5;
const qName = qNameArray[question_type]
const isPreviewPage = showActionButton == false
return(
<div className="bor-bottom-greyE padding20-30 singleDisplay" id={qNumber} _id={question_id}>
@ -85,6 +57,9 @@ class SingleDisplay extends Component{
.actionBtns {
height: 28px
}
.ql-editor{
padding:0px !important;
}
`}</style>
<QestionDisplayHeader {...this.props}></QestionDisplayHeader>
@ -103,11 +78,15 @@ class SingleDisplay extends Component{
flexDirection:"row",
}} key={optionIndex}>
<Radio disabled className="fl lineh-25 w50" checked={item.standard_boolean}>{prefix}</Radio>
<MarkdownToHtml content={item.choice_text} selector={'single_' + (index + 1) + '' + (optionIndex + 1)} style={{ float: 'left', display: 'inline-block' }}
{!this.props.exercise||this.props.exercise&&this.props.exercise.is_md?<MarkdownToHtml content={item.choice_text} selector={'single_' + (index + 1) + '' + (optionIndex + 1)} style={{ float: 'left', display: 'inline-block' }}
></MarkdownToHtml>:<QuillForEditor
readOnly={true}
style={{ float: 'left', display: 'inline-block',padding:'0px',margin: '2px 0px 0px'}}
value={item.choice_text?JSON.parse(item.choice_text):""}
// showUploadImage={this.handleShowUploadImage}
/>}
></MarkdownToHtml>
{/* <span style={{ display: 'inline-block'}} className="markdown-body fl"
dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}
</div>)
} else {
@ -117,11 +96,15 @@ class SingleDisplay extends Component{
flexDirection:"row",
}} key={optionIndex}>
<Checkbox disabled className="fl lineh-25 w50" checked={item.standard_boolean}>{prefix}</Checkbox>
<MarkdownToHtml content={item.choice_text} selector={'single_' + (index + 1)+ '' + (optionIndex + 1)} style={{ float: 'left', display: 'inline-block' }}
{!this.props.exercise||this.props.exercise&&this.props.exercise.is_md?<MarkdownToHtml content={item.choice_text} selector={'single_' + (index + 1)+ '' + (optionIndex + 1)} style={{ float: 'left', display: 'inline-block' }}
></MarkdownToHtml>:<QuillForEditor
readOnly={true}
style={{ float: 'left', display: 'inline-block' ,padding:'0px',margin: '2px 0px 0px'}}
value={item.choice_text?JSON.parse(item.choice_text):""}
// showUploadImage={this.handleShowUploadImage}
/>}
></MarkdownToHtml>
{/* <span style={{ display: 'inline-block'}} className="markdown-body fl"
dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}
</div>)
}
})}
@ -131,5 +114,5 @@ class SingleDisplay extends Component{
)
}
}
// RouteHOC()
export default (SingleDisplay);

@ -4,6 +4,7 @@ export const Q_TYPE_JUDGE = 2 // 判断
export const Q_TYPE_NULL = 3 // 填空
export const Q_TYPE_MAIN = 4 // 填空
export const Q_TYPE_SHIXUN = 5 // 实训
export const Q_TYPE_SHIXUN_BIANCHENG = 6 // 编程题
export const qNameArray = [
'单选题',
@ -12,4 +13,5 @@ export const qNameArray = [
'填空题',
'简答题',
'实训题',
'编程题'
]

@ -1,6 +1,7 @@
import React,{ Component } from "react";
import {Checkbox,Radio, Input} from "antd";
import {markdownToHTML, MarkdownToHtml} from 'educoder'
import QuillForEditor from "../../../../common/quillForEditor";
import axios from 'axios'
const tagArray = [
@ -33,29 +34,70 @@ class Multiple extends Component{
console.log(error);
})
}
render(){
let {
questionType ,
let {
questionType ,
exercise,
user_exercise_status
user_exercise_status,
is_md
}=this.props
let isStudent =this.props.isStudent();
console.log(questionType);
return(
<div className="pl30 pr30 singleDisplay">
<style>
{
`
.multiple .ql-editor p{
line-height: 25px !important;
}
`
}
</style>
<Checkbox.Group className="with100" disabled={ user_exercise_status == 1 ? true : false } onChange={this.saveId} value={questionType.user_answer}>
{
questionType.question_choices && questionType.question_choices.map((item,key)=>{
let prefix = `${tagArray[key]}.`
let titename="";
if(is_md===true){
titename=item.choice_text;
}else{
try {
titename = JSON.parse(item.choice_text);
}catch (e) {
titename={"ops":[{"insert":item.choice_text}]};
}
// JSON.parse 有些异常数据是undefined
if(titename===undefined){
titename={"ops":[{"insert":item.choice_text}]};
}
try {
// JSON.parse 转换的时候如果是数字字符串就转成整数了
if(titename>=0){
titename={"ops":[{"insert":item.choice_text}]};
}
}catch (e) {
}
}
return(
<p className="clearfix mb15 df">
<Checkbox className="lineh-15 df mr8 setRadioStyle" value={item.choice_id}>
<Checkbox className="lineh-15 df mr8 setRadioStyle multiple" value={item.choice_id}>
<span className="fl mr3 lineh-25">{prefix}</span>
<MarkdownToHtml content={item.choice_text} selector={'multiple_' + (this.props.index + 1) + (key + 1)}
className="flex1" style={{display:"inline-block"}}
></MarkdownToHtml>
{
is_md?
<MarkdownToHtml content={titename} selector={'multiple_' + (this.props.index + 1) + (key + 1)}
className="flex1" style={{display:"inline-block"}}
></MarkdownToHtml>
:
<QuillForEditor
readOnly={true}
value={titename}
showUploadImage={this.props.handleShowUploadImage}
/>
}
</Checkbox>
</p>
)
@ -64,7 +106,7 @@ class Multiple extends Component{
</Checkbox.Group>
{
// 答案公开,且试卷已经截止
isStudent && exercise && exercise.answer_open==true && exercise.exercise_status == 3 &&
isStudent && exercise && exercise.answer_open==true && exercise.exercise_status == 3 &&
<p className="bor-top-greyE pt20 mt10 font-16">参考答案
{questionType.standard_answer.map((i,k)=>{
return(
@ -78,4 +120,4 @@ class Multiple extends Component{
)
}
}
export default Multiple
export default Multiple

@ -1,5 +1,6 @@
import React,{ Component } from "react";
import {Checkbox,Radio, Input} from "antd";
import QuillForEditor from "../../../../common/quillForEditor";
import {markdownToHTML, MarkdownToHtml} from 'educoder'
import axios from 'axios'
@ -30,36 +31,80 @@ class single extends Component{
})
}
render(){
let {
questionType ,
let {
questionType ,
exercise,
user_exercise_status
user_exercise_status,
is_md
}=this.props
let isStudent =this.props.isStudent();
let isJudge = questionType.question_type == 2
return(
<div className="pl30 pr30 singleDisplay">
<style>
{
`
.single .ql-editor p{
line-height: 25px !important;
}
`
}
</style>
<Radio.Group className="with100" disabled={ user_exercise_status == 1 ? true : false } value={questionType.user_answer[0]} onChange={this.changeItem}>
{
questionType.question_choices && questionType.question_choices.map((item,key)=>{
let prefix = isJudge ? undefined : `${tagArray[key]}.`
let titename="";
if(is_md===true){
titename=item.choice_text;
}else{
try {
titename = JSON.parse(item.choice_text);
}catch (e) {
titename={"ops":[{"insert":item.choice_text}]};
}
// JSON.parse 有些异常数据是undefined
if(titename===undefined){
titename={"ops":[{"insert":item.choice_text}]};
}
try {
// JSON.parse 转换的时候如果是数字字符串就转成整数了
if(titename>=0){
titename={"ops":[{"insert":item.choice_text}]};
}
}catch (e) {
}
}
return(
<p className={parseInt(questionType.question_type) == 0 ? "clearfix mb15" : "fl mr40"}>
<Radio className="df lineh-25 setRadioStyle" value={item.choice_id}>
<Radio className="df lineh-25 setRadioStyle single" value={item.choice_id}>
<span className="fl mr3 lineh-25">{prefix}</span>
<MarkdownToHtml content={item.choice_text} selector={'single_' + (this.props.index + 1) + (key + 1)}
className="flex1" style={{display:"inline-block"}}
></MarkdownToHtml>
{
is_md?
<MarkdownToHtml content={titename} selector={'single_' + (this.props.index + 1) + (key + 1)}
className="flex1" style={{display:"inline-block"}}
></MarkdownToHtml>
:
<QuillForEditor
readOnly={true}
value={titename}
showUploadImage={this.props.handleShowUploadImage}
/>
}
</Radio>
</p>
)
})
}
</Radio.Group>
{
{
// 答案公开,且试卷已经截止
isStudent && exercise && exercise.answer_open==true && (exercise.exercise_status == 3 || user_exercise_status == 1) &&
isStudent && exercise && exercise.answer_open==true && (exercise.exercise_status == 3 || user_exercise_status == 1) &&
<p className="bor-top-greyE pt20 mt10 font-16">参考答案
{questionType.standard_answer.map((i,k)=>{
return(
@ -73,4 +118,4 @@ class single extends Component{
)
}
}
export default single
export default single

@ -18,7 +18,7 @@ import LoadingSpin from '../../../common/LoadingSpin';
import Contentquestionbank from "./Contentquestionbank";
import Listjihe from "./Listjihe";
import Certifiedprofessional from "../../modals/Certifiedprofessional";
import QuestionModalPicture from '../component/QuestionModalPicture.js'
import QuestionModalPicture from '../component/QuestionModalPicture'
const { TabPane } = Tabs;
const Search = Input.Search;
class Contentpart extends Component {

@ -20,6 +20,7 @@ import Bottomsubmit from "../../modules/modals/Bottomsubmit";
import Seeoagertit from "./component/Seeoagertit";
import Paperlibraryseeid_item from './component/Paperlibraryseeid_item';
import QuestionModal from "../question/component/QuestionModal";
import SendTopicsModel from "./component/SendTopicsModel";
//人工组卷预览
class Paperlibraryseeid extends Component {
constructor(props) {
@ -33,6 +34,8 @@ class Paperlibraryseeid extends Component {
titiless:"",
boolok:"知道了",
exercise_id:0,
SendTop:false,
paramsid:null,
}
@ -100,32 +103,18 @@ class Paperlibraryseeid extends Component {
// titilesm: "功能正在内测中,敬请期待",
// titiless: "",
// })
let id = this.props.match.params.id;
let url=`/examination_banks/${id}/send_to_course.json`;
var data={
course_id:1309
};
this.getwangluodata(url,data);
// let id = this.props.match.params.id;
// let url=`/examination_banks/${id}/send_to_course.json`;
// var data={
// course_id:1309
// };
// this.getwangluodata(url,data);
// 2413
this.submitInfos(true);
}
getwangluodata=(url,data)=>{
axios.post(url,data).then((response) => {
if (response) {
// console.log("组卷发送");
// console.log(response);
if(response.data){
if(response.data.status===0){
this.setState({
exercise_id:response.data.exercise_id
})
}
}
}
});
}
setitem_type = (item_type) => {
@ -152,15 +141,24 @@ class Paperlibraryseeid extends Component {
})
}
submitInfos=(bool)=>{
this.setState({
SendTop:bool,
paramsid:this.props.match.params.id
})
}
render() {
let {paperlibrartdata,defaultActiveKey,titilesm,titiless,boolok,modalsType} = this.state;
let {paperlibrartdata,defaultActiveKey,titilesm,titiless,boolok,modalsType,SendTop,paramsid} = this.state;
const params = this.props && this.props.match && this.props.match.params;
// console.log("params");
// console.log(params);
let urlsysl=`/paperlibrary?defaultActiveKey=${defaultActiveKey}`;
return (
<div>
{SendTop===true?
<SendTopicsModel paramsid={paramsid} visible={SendTop} mypaper={true} {...this.state} {...this.props} submitInfos={(b)=>this.submitInfos(b)}></SendTopicsModel>:""
}
{
modalsType===true?
<QuestionModal {...this.props}{...this.state} modalsType={modalsType} modalCancel={() => this.modalCancel()}

@ -18,6 +18,7 @@ import Contentquestionbank from "./Contentquestionbank";
import LoadingSpin from '../../../common/LoadingSpin';
import Listjihe from "./Listjihe";
import Certifiedprofessional from "../../modals/Certifiedprofessional";
import SendTopicsModel from "./SendTopicsModel";
const { TabPane } = Tabs;
const Search = Input.Search;
class Contentpart extends Component {
@ -29,7 +30,8 @@ class Contentpart extends Component {
mydisplay:false,
occupation:2,
isysladmins:false,
SendTop:false,
paramsid:null,
}
}
@ -205,13 +207,15 @@ class Contentpart extends Component {
}
submitInfos=(bool,id)=>{
this.setState({
SendTop:bool,
paramsid:id
})
}
render() {
let {page,defaultActiveKeyss,mydisplay}=this.state;
let {page,defaultActiveKeyss,mydisplay,SendTop,paramsid}=this.state;
let {defaultActiveKey,defaultActiveKeybool}=this.props;
let defaultActiveKeys=defaultActiveKey+'';
@ -277,7 +281,7 @@ class Contentpart extends Component {
:""
}
{
mydisplay===true?
mydisplay===true||SendTop===true?
<style>
{
`
@ -291,6 +295,9 @@ class Contentpart extends Component {
:""
}
{SendTop===true?
<SendTopicsModel paramsid={paramsid} visible={SendTop} mypaper={false} {...this.state} {...this.props} submitInfos={(b,id)=>this.submitInfos(b,id)}></SendTopicsModel>:""
}
<div className="w1200ms contentparttit" style={{
position: "relative",
}}>
@ -437,6 +444,7 @@ class Contentpart extends Component {
showmodelysl={(e)=>this.showmodelysl(e)}
Isitapopup={this.props.Isitapopup}
showmodelsInaudit={(e)=>this.props.showmodelsInaudit(e)}
submitInfos={(b,id)=>this.submitInfos(b,id)}
>
</Listjihe>

@ -182,7 +182,7 @@ class Listjihe extends Component {
{
defaultActiveKey===0||defaultActiveKey==="0"?
<div className="w50s xaxisreverseorder">
<p className="selection xiaoshou">
<p className="selection xiaoshou" onClick={()=>this.props.submitInfos(true,items.id)}>
<span className=" lh30">发送至课堂</span>
</p>
<p className="viewparsings xiaoshou mr25 " onClick={()=>this.props.showmodelysl(items.id)}>
@ -222,7 +222,7 @@ class Listjihe extends Component {
</div>
:Periofters===true?
<div className="w50s xaxisreverseorder">
<p className="selection xiaoshou">
<p className="selection xiaoshou" onClick={()=>this.props.submitInfos(true,items.id)}>
<span className=" lh30">发送至课堂</span>
</p>
<p className="viewparsings xiaoshou mr25 " onClick={()=>this.props.showmodelysl(items.id)}>
@ -243,7 +243,7 @@ class Listjihe extends Component {
</div>
:Perioftersbols===true?
<div className="w50s xaxisreverseorder">
<p className="selection xiaoshou">
<p className="selection xiaoshou" onClick={()=>this.props.submitInfos(true,items.id)}>
<span className=" lh30">发送至课堂</span>
</p>
{

@ -0,0 +1,196 @@
import React, {Component} from "react";
import {Modal, Radio, Input, Tooltip, Checkbox, Select, Row, Col, Spin} from "antd";
import axios from 'axios';
const {Search} = Input;
class SendTopicsModel extends Component {
constructor(props) {
super(props);
this.state = {
courses: [],
search: null,
Radiolist: undefined,
showcheck: false,
smallisSpin: false,
yslbanksMenu: undefined,
exercise_id: null,
}
}
componentDidMount() {
// console.log("SendTopicssssssssssss");
// console.log(this.props);
let {search} = this.state;
this.onupdatalist(search)
this.setState({
yslbanksMenu: this.props.banksMenu,
})
}
//获取的课堂
onupdatalist = (search) => {
let url = "/question_banks/my_courses.json";
axios.get(url, {
params: {
search
}
}).then((result) => {
this.setState({
courses: result.data.courses
})
}).catch((error) => {
console.log(error);
})
}
onSearchChange = (e) => {
this.setState({
search: e.target.value
})
// this.onupdatalist(e.target.value)
}
onSearch = (search) => {
this.onupdatalist(search)
}
onChange = (e) => {
console.log("SendTopics");
console.log(e);
this.setState({
Radiolist: e.target.value
})
}
submitInfo = () => {
if(this.state.Radiolist===undefined) {
this.setState({
showcheck: true,
smallisSpin: false
})
}
let url = `/examination_banks/${this.props.paramsid}/send_to_course.json`;
var data = {
course_id: this.state.Radiolist
};
this.getwangluodata(url, data);
}
getwangluodata = (url, data) => {
this.setState({
smallisSpin: true
})
axios.post(url, data).then((response) => {
if (response) {
if (response.data) {
if (response.data.status === 0) {
this.setState({
exercise_id: response.data.exercise_id
})
this.props.submitInfos(false, null);
if (this.props.mypaper) {
this.props.history.push("/paperlibrary?defaultActiveKey=0");
}
}
}
}
this.setState({
smallisSpin: false
})
}).catch((error) => {
console.log(error)
this.setState({
smallisSpin: false
})
});
}
render() {
let {courses, Radiolist, showcheck, smallisSpin} = this.state;
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
return (
<div>
<style>
{
`
.ant-modal-body{
padding:20px 40px;
}
.onSearchtopics input{
height:40px;
}
.over221{
height:221px;
overflow-y: auto;
}
`
}
</style>
<Modal
keyboard={false}
title="发送至课堂"
visible={this.props.visible}
closable={false}
footer={null}
destroyOnClose={true}
width={600}
>
<div className="newupload_conbox">
<div className="mb15 font-14 edu-txt-center color-orange-tip">
{this.props&&this.props.mypaper===true?
"温馨提示:当前试卷将会发送到指定课堂"
:
"温馨提示:选择的试卷将会发送到指定课堂"
}
</div>
<div className="mb5"
// onMouseLeave={this.closeList}
>
<Search
className="mb14 onSearchtopics"
placeholder="请输入课堂名称进行搜索"
onChange={this.onSearchChange}
onSearch={this.onSearch}
></Search>
</div>
<div className="edu-back-skyblue pl15 pr15 clearfix over221 pt5">
<Radio.Group onChange={this.onChange} value={Radiolist}>
{
courses && courses.map((item, key) => {
return (
<div className="mt5" key={key}>
<Radio style={radioStyle} value={item.course_id} key={item.course_id}>
{item.course_name}
</Radio>
</div>
)
})
}
</Radio.Group>
</div>
{showcheck === true ? <div className={"color-red mt10"}>请先选择课堂</div> : ""}
<div className="mt20 clearfix edu-txt-center">
<a onClick={() => this.props.submitInfos(false, null)} className="pop_close task-btn mr30 ">取消</a>
<a className="task-btn task-btn-orange" onClick={() => this.submitInfo()}>确定</a>
</div>
</div>
</Modal>
</div>
)
}
}
export default SendTopicsModel;
Loading…
Cancel
Save