|
@@ -1,23 +1,36 @@
|
|
|
import React from 'react';
|
|
|
-import { Form, Input, Tabs, DatePicker } from 'antd';
|
|
|
+import { Form, Input, Tabs, Row, Col, Button, DatePicker, List, Icon, Checkbox } from 'antd';
|
|
|
import './index.less';
|
|
|
+import DragList from '@src/components/DragList';
|
|
|
+import Editor from '@src/components/Editor';
|
|
|
import Page from '@src/containers/Page';
|
|
|
import Block from '@src/components/Block';
|
|
|
import Select from '@src/components/Select';
|
|
|
|
|
|
-import { formatFormError, generateSearch } from '@src/services/Tools';
|
|
|
+import { formatFormError, generateSearch, getMap } from '@src/services/Tools';
|
|
|
import { asyncSMessage } from '@src/services/AsyncTools';
|
|
|
+import { TextbookType, QuestionStyleType } from '../../../../Constant';
|
|
|
import { Preview } from '../../../stores/preview';
|
|
|
-import { Exercise } from '../../../stores/exercise';
|
|
|
-import { User } from '../../../stores/user';
|
|
|
+import { Textbook } from '../../../stores/textbook';
|
|
|
+import { System } from '../../../stores/system';
|
|
|
import config from './index';
|
|
|
|
|
|
+const QuestionStyleTypeMap = getMap(QuestionStyleType, 'value', 'label');
|
|
|
+
|
|
|
export default class extends Page {
|
|
|
- init() {
|
|
|
- Exercise.allStruct().then(result => {
|
|
|
- result = result.filter(row => row.level === 2).map(row => { row.title = `${row.titleZh}/${row.titleEn}`; row.value = row.id; return row; });
|
|
|
- this.setState({ exercise: result });
|
|
|
- });
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ this.placeList = [];
|
|
|
+ this.placeSetting = null;
|
|
|
+ this.uuid = [];
|
|
|
+
|
|
|
+ const { id } = this.params;
|
|
|
+
|
|
|
+ if (id) {
|
|
|
+ config.title = '编辑机经题目';
|
|
|
+ } else {
|
|
|
+ config.title = '添加机经题目';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
initData() {
|
|
@@ -25,36 +38,125 @@ export default class extends Page {
|
|
|
const { form } = this.props;
|
|
|
let handler;
|
|
|
if (id) {
|
|
|
- config.title = '编辑预习作业';
|
|
|
handler = Preview.get({ id });
|
|
|
} else {
|
|
|
- config.title = '添加预习作业';
|
|
|
- handler = Promise.resolve({});
|
|
|
+ handler = Promise.resolve({ question: { content: { number: 1, type: 'single', typeset: 'one', questions: [], steps: [] } } });
|
|
|
}
|
|
|
handler
|
|
|
.then(result => {
|
|
|
+ const { questionNoIds } = result;
|
|
|
+ result.time = [result.startTime, result.endTime];
|
|
|
+ this.uuid[0] = -1;
|
|
|
+ result.question.content.questions.forEach((row, index) => {
|
|
|
+ const keys = [];
|
|
|
+ this.uuid[index] = 0;
|
|
|
+ if (row.select && row.select.length > 0) {
|
|
|
+ for (; this.uuid[index] < row.select.length; this.uuid[index] += 1) {
|
|
|
+ keys.push(this.uuid[index]);
|
|
|
+ form.getFieldDecorator(`question.content.questions[${index}].select[${this.uuid}]`);
|
|
|
+ form.getFieldDecorator(`question.content.questions[${index}].answer[${this.uuid}]`);
|
|
|
+ }
|
|
|
+ const answerMap = {};
|
|
|
+ row.answer.forEach(r => {
|
|
|
+ answerMap[r] = true;
|
|
|
+ });
|
|
|
+ row.answer = row.select.map(r => answerMap[r] || false);
|
|
|
+ } else if (row.answer && row.answer.length > 0) {
|
|
|
+ for (; this.uuid[index] < row.answer.length; this.uuid[index] += 1) {
|
|
|
+ keys.push(this.uuid);
|
|
|
+ form.getFieldDecorator(`question.content.questions[${index}].answer[${this.uuid}]`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ form.getFieldDecorator(`question.content.questions[${index}].keys`);
|
|
|
+ row.keys = keys;
|
|
|
+ return row;
|
|
|
+ });
|
|
|
+ result.question.content.steps.forEach((row, index) => {
|
|
|
+ form.getFieldDecorator(`question.content.steps[${index}].title`);
|
|
|
+ form.getFieldDecorator(`question.content.steps[${index}].stem`);
|
|
|
+ });
|
|
|
+
|
|
|
+ form.getFieldDecorator('question.content.step');
|
|
|
+ form.getFieldDecorator('question.content.number');
|
|
|
+ form.getFieldDecorator('question.content.type');
|
|
|
+ form.getFieldDecorator('question.content.typeset');
|
|
|
form.setFieldsValue(result);
|
|
|
- generateSearch('userIds', { mode: 'multiple' }, this, (search) => {
|
|
|
- return User.list(search);
|
|
|
+ generateSearch('setId', {}, this, (search) => {
|
|
|
+ return System.listRank(search);
|
|
|
}, (row) => {
|
|
|
return {
|
|
|
- title: `${row.nickname}(${row.mobile})`,
|
|
|
+ title: row.title,
|
|
|
value: row.id,
|
|
|
};
|
|
|
- }, result.userIds || [], null);
|
|
|
+ }, result.setId, null);
|
|
|
+ this.setState({ questionNoIds });
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ refreshPlace(type) {
|
|
|
+ let handler = null;
|
|
|
+ if (this.placeSetting) {
|
|
|
+ handler = Promise.resolve(this.placeSetting);
|
|
|
+ } else {
|
|
|
+ handler = System.getPlace();
|
|
|
+ }
|
|
|
+ handler.then(result => {
|
|
|
+ this.placeSetting = result;
|
|
|
+ this.placeList = result[type] || [];
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ removeQuestion(index, k) {
|
|
|
+ const { form } = this.props;
|
|
|
+ const keys = form.getFieldValue(`question.content.questions[${index}].keys`);
|
|
|
+ if (keys.length === 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ form.setFieldsValue({
|
|
|
+ [`question.content.questions[${index}].keys`]: keys.filter(key => key !== k),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ addQuestion(index) {
|
|
|
+ const { form } = this.props;
|
|
|
+ const keys = form.getFieldValue(`question.content.questions[${index}].keys`) || [];
|
|
|
+ this.uuid[index] += 1;
|
|
|
+ const nextKeys = keys.concat(this.uuid[index]);
|
|
|
+ form.setFieldsValue({
|
|
|
+ [`question.content.questions[${index}].keys`]: nextKeys,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ orderQuestion(index, oldIndex, newIndex) {
|
|
|
+ const { form } = this.props;
|
|
|
+ const keys = form.getFieldValue(`question.content.questions[${index}].keys`) || [];
|
|
|
+ const tmp = keys[oldIndex];
|
|
|
+ keys[oldIndex] = keys[newIndex];
|
|
|
+ keys[newIndex] = tmp;
|
|
|
+ form.setFieldsValue({
|
|
|
+ [`question.content.questions[${index}].keys`]: keys,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ changeQuestion(index, k, value) {
|
|
|
+ const { form } = this.props;
|
|
|
+ let answer = form.getFieldValue(`question.content.answer[${index}].single`) || [];
|
|
|
+ answer = answer.map(() => !value);
|
|
|
+ answer[k] = !!value;
|
|
|
+ form.setFieldsValue({ [`question.content.answer[${index}].single`]: answer });
|
|
|
+ }
|
|
|
+
|
|
|
submit() {
|
|
|
const { form } = this.props;
|
|
|
form.validateFields((err) => {
|
|
|
if (!err) {
|
|
|
const data = form.getFieldsValue();
|
|
|
+ [data.startTime, data.endTime] = data.time;
|
|
|
let handler;
|
|
|
if (data.id) {
|
|
|
- handler = Preview.edit(data);
|
|
|
+ handler = Textbook.editQuestion(data);
|
|
|
} else {
|
|
|
- handler = Preview.add(data);
|
|
|
+ handler = Textbook.addQuestion(data);
|
|
|
}
|
|
|
handler.then(() => {
|
|
|
asyncSMessage('保存成功');
|
|
@@ -65,24 +167,12 @@ export default class extends Page {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- searchQuestion(values) {
|
|
|
- console.log(values);
|
|
|
- }
|
|
|
-
|
|
|
- renderBase() {
|
|
|
+ renderAttr() {
|
|
|
const { getFieldDecorator } = this.props.form;
|
|
|
- return <Block>
|
|
|
+ return <Block flex>
|
|
|
+ <h1>基本信息</h1>
|
|
|
<Form>
|
|
|
{getFieldDecorator('id')(<input hidden />)}
|
|
|
- <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='选择课程'>
|
|
|
- {getFieldDecorator('category', {
|
|
|
- rules: [
|
|
|
- { required: true, message: '请选择课程' },
|
|
|
- ],
|
|
|
- })(
|
|
|
- <Select select={this.state.exercise} placeholder='请选择课程' />,
|
|
|
- )}
|
|
|
- </Form.Item>
|
|
|
<Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='起止时间'>
|
|
|
{getFieldDecorator('time', {
|
|
|
rules: [
|
|
@@ -92,35 +182,179 @@ export default class extends Page {
|
|
|
<DatePicker.RangePicker />,
|
|
|
)}
|
|
|
</Form.Item>
|
|
|
- <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='作业标题'>
|
|
|
- {getFieldDecorator('title', {
|
|
|
+ <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='换库表'>
|
|
|
+ {getFieldDecorator('setId', {
|
|
|
rules: [
|
|
|
- { required: true, message: '请输入作业标题' },
|
|
|
+ { required: true, message: '请选择换库表' },
|
|
|
],
|
|
|
})(
|
|
|
- <Input placeholder='请输入作业标题' />,
|
|
|
+ <Select {...this.state.setId} placeholder='请选择换库表' />,
|
|
|
)}
|
|
|
</Form.Item>
|
|
|
- <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='指定做题人'>
|
|
|
- {getFieldDecorator('userIds', {
|
|
|
+ <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='题型'>
|
|
|
+ {getFieldDecorator('question.questionType', {
|
|
|
rules: [
|
|
|
- { required: true, message: '请指定做题人' },
|
|
|
+ { required: true, message: '请选择题型' },
|
|
|
],
|
|
|
})(
|
|
|
- <Select {...this.state.userIds} placeholder='请指定做题人' />,
|
|
|
+ <Select select={TextbookType} placeholder='请选择题型' onChange={(v) => {
|
|
|
+ this.refreshPlace(v);
|
|
|
+ }} />,
|
|
|
)}
|
|
|
</Form.Item>
|
|
|
- <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='选择作业题'>
|
|
|
- {getFieldDecorator('questionIds', {
|
|
|
+ <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='考点'>
|
|
|
+ {getFieldDecorator('question.place', {
|
|
|
rules: [
|
|
|
- { required: true, message: '请选择作业题' },
|
|
|
+ { required: true, message: '请选择考点' },
|
|
|
],
|
|
|
})(
|
|
|
- <Select select={[]} mode='tags' maxTagCount={200} notFoundContent={null} placeholder='输入题目id, 逗号分隔' tokenSeparators={[',', ',']} onSelect={(values) => {
|
|
|
- this.searchQuestion(values);
|
|
|
+ <Select select={this.placeList} placeholder='请选择考点' onChange={(v) => {
|
|
|
+ this.refreshPart(v);
|
|
|
}} />,
|
|
|
)}
|
|
|
</Form.Item>
|
|
|
+ <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='题目id'>
|
|
|
+ {getFieldDecorator('title', {
|
|
|
+ rules: [
|
|
|
+ { required: true, message: '请输入题目id' },
|
|
|
+ ],
|
|
|
+ })(
|
|
|
+ <Input placeholder='请输入题目id' />,
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </Block>;
|
|
|
+ }
|
|
|
+
|
|
|
+ renderBase() {
|
|
|
+ const { getFieldDecorator } = this.props.form;
|
|
|
+ return <Block flex>
|
|
|
+ <h1>题干信息</h1>
|
|
|
+ <Form>
|
|
|
+ {getFieldDecorator('question.id')(<input hidden />)}
|
|
|
+ {getFieldDecorator('question.stem', {
|
|
|
+ })(
|
|
|
+ <Editor modules={{
|
|
|
+ toolbar: {
|
|
|
+ container: [
|
|
|
+ ['image'],
|
|
|
+ [{ header: '1' }, { header: '2' }],
|
|
|
+ ['bold', 'underline', 'blockquote'],
|
|
|
+ [{ list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }],
|
|
|
+ ],
|
|
|
+ handlers: {
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }} placeholder='请输入内容' onUpload={(file) => System.uploadImage(file)} />,
|
|
|
+ )}
|
|
|
+
|
|
|
+ {getFieldDecorator('question.content.type')(<input hidden />)}
|
|
|
+ {getFieldDecorator('question.content.number')(<input hidden />)}
|
|
|
+ {getFieldDecorator('question.content.typeset')(<input hidden />)}
|
|
|
+ </Form>
|
|
|
+ </Block>;
|
|
|
+ }
|
|
|
+
|
|
|
+ renderSelect() {
|
|
|
+ const { getFieldDecorator, getFieldValue } = this.props.form;
|
|
|
+ const number = getFieldValue('question.content.number');
|
|
|
+ const type = getFieldValue('question.content.type');
|
|
|
+ const result = [];
|
|
|
+ let handler = null;
|
|
|
+ switch (type) {
|
|
|
+ case 'single':
|
|
|
+ handler = (index) => this.renderSelectSingle(index);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ for (let index = 0; index < Number(number); index += 1) {
|
|
|
+ result.push(<Block flex className={type}>
|
|
|
+ <h1>选项信息({QuestionStyleTypeMap[type]})</h1>
|
|
|
+ <Form>
|
|
|
+ {type !== 'inline' && (
|
|
|
+ <Form.Item>
|
|
|
+ {getFieldDecorator(`question.content.questions[${index}].description`, {
|
|
|
+ })(
|
|
|
+ <Editor placeholder='选项问题说明' />,
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ )}
|
|
|
+ {handler(index)}
|
|
|
+ </Form>
|
|
|
+ </Block>);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ renderSelectSingle(index) {
|
|
|
+ const { getFieldDecorator, getFieldValue } = this.props.form;
|
|
|
+ getFieldDecorator(`question.content.questions[${index}].keys`);
|
|
|
+ const keys = getFieldValue(`question.content.questions[${index}].keys`) || [];
|
|
|
+ return [
|
|
|
+ <DragList
|
|
|
+ loading={false}
|
|
|
+ dataSource={keys || []}
|
|
|
+ handle={'.icon'}
|
|
|
+ onMove={(oldIndex, newIndex) => {
|
|
|
+ this.orderQuestion(index, oldIndex, newIndex);
|
|
|
+ }}
|
|
|
+ renderItem={(k) => (
|
|
|
+ <List.Item actions={[<Icon type='bars' className='icon' />]}>
|
|
|
+ <Row key={k} style={{ width: '100%' }}>
|
|
|
+ <Col span={1}>
|
|
|
+ {getFieldDecorator(`question.answer.questions[${index}].single[${k}]`, {
|
|
|
+ valuePropName: 'checked',
|
|
|
+ })(
|
|
|
+ <Checkbox onChange={(value) => {
|
|
|
+ this.changeQuestion(index, k, value);
|
|
|
+ }} />,
|
|
|
+ )}
|
|
|
+ </Col>
|
|
|
+ <Col span={23}>
|
|
|
+ <Form.Item
|
|
|
+ key={k}
|
|
|
+ hidden
|
|
|
+ >
|
|
|
+ {getFieldDecorator(`question.content.questions[${index}].select[${k}]`, {
|
|
|
+ rules: [{
|
|
|
+ required: true,
|
|
|
+ whitespace: true,
|
|
|
+ message: '请填写选项信息',
|
|
|
+ }],
|
|
|
+ })(
|
|
|
+ <Input />,
|
|
|
+ )}
|
|
|
+ {keys.length > 1 ? (
|
|
|
+ <Icon
|
|
|
+ type='minus-circle-o'
|
|
|
+ disabled={keys.length === 1}
|
|
|
+ onClick={() => this.removeQuestion(index, k)}
|
|
|
+ />
|
|
|
+ ) : null}
|
|
|
+ </Form.Item>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ </List.Item>
|
|
|
+ )}
|
|
|
+ />,
|
|
|
+ <Form.Item>
|
|
|
+ <Button type='dashed' onClick={() => this.addQuestion(index)} >
|
|
|
+ <Icon type='plus' /> 新增
|
|
|
+ </Button>
|
|
|
+ </Form.Item>,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ renderQX() {
|
|
|
+ const { getFieldDecorator } = this.props.form;
|
|
|
+ return <Block flex>
|
|
|
+ <Form>
|
|
|
+ <Form.Item label='千行解析'>
|
|
|
+ {getFieldDecorator('qxContent', {
|
|
|
+ })(
|
|
|
+ <Editor placeholder='输入内容' />,
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
</Form>
|
|
|
</Block>;
|
|
|
}
|
|
@@ -146,6 +380,17 @@ export default class extends Page {
|
|
|
renderView() {
|
|
|
return <div flex >
|
|
|
{this.renderTab()}
|
|
|
+ {this.renderAttr()}
|
|
|
+ {this.renderBase()}
|
|
|
+ {this.renderSelect()}
|
|
|
+ {this.renderQX()}
|
|
|
+ <Row type="flex" justify="center">
|
|
|
+ <Col>
|
|
|
+ <Button type="primary" onClick={() => {
|
|
|
+ this.submit();
|
|
|
+ }}>保存</Button>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
</div>;
|
|
|
}
|
|
|
}
|