import React from 'react'; import { Form, Input, Tabs, Row, Col, Button, 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 FileUpload from '@src/components/FileUpload'; import { formatFormError, generateSearch, getMap } from '@src/services/Tools'; import { asyncSMessage } from '@src/services/AsyncTools'; import { TextbookType, QuestionStyleType } from '../../../../Constant'; 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 { constructor(props) { super(props); this.placeList = []; this.placeSetting = null; this.uuid = []; const { id } = this.params; if (id) { config.title = '编辑机经题目'; } else { config.title = '添加机经题目'; } } init() { } initData() { const { id } = this.params; const { form } = this.props; let handler; if (id) { handler = Textbook.getQuestion({ id }); } else { let { libraryId } = this.state.search; libraryId = Number(libraryId || 0); handler = Textbook.getNextQuestion({ libraryId }).then(result => { return { libraryId: libraryId || '', no: result, question: { content: { number: 1, type: 'single', typeset: 'one', questions: [] } } }; }); } handler .then(result => { const { questionNoIds } = result; // result.time = [result.startTime, result.endTime]; this.uuid[0] = -1; let type = result.question.content.type || 'single'; if (type === 'inline') type = 'single'; 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.answer.questions[${index}].${type}[${this.uuid}]`); } } form.getFieldDecorator(`question.content.questions[${index}].keys`); row.keys = keys; return row; }); form.getFieldDecorator('question.content.number'); form.getFieldDecorator('question.content.type'); form.getFieldDecorator('question.content.typeset'); form.getFieldDecorator('question.stem'); form.getFieldDecorator('question.questionType'); form.getFieldDecorator('question.qxContent'); form.getFieldDecorator('question.place'); form.getFieldDecorator('question.id'); form.getFieldDecorator('questionId'); form.getFieldDecorator('libraryId'); form.getFieldDecorator('title'); form.getFieldDecorator('no'); form.getFieldDecorator('id'); form.setFieldsValue(result); generateSearch('libraryId', {}, this, (search) => { return Textbook.listLibrary(search); }, (row) => { return { title: `${row.startDate} - ${row.endDate || '至今'}`, value: row.id, }; }, result.libraryId, null); this.setState({ questionNoIds }); }); } refreshPlace(type) { let handler = null; if (this.placeSetting) { handler = Promise.resolve(this.placeSetting); } else { handler = System.getPlace(); } return handler.then(result => { this.placeSetting = result; this.placeList = result[type] || []; this.setState({ placeList: this.placeList }); }); } refreshNo(libraryId) { return Textbook.getNextQuestion({ libraryId }).then(result => { this.props.form.setFieldsValue({ no: result }); }); } 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`) || []; if (!this.uuid[index]) { this.uuid[index] = 1; } else { 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.answer.questions[${index}].single`) || []; answer = answer.map(() => !value); answer[k] = !!value; form.setFieldsValue({ [`question.answer.questions[${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 = Textbook.addQuestion(data); } else { handler = Textbook.editQuestion(data); } handler.then((result) => { asyncSMessage('保存成功'); if (data.id) { linkTo(`/subject/textbook/question/${data.id}`); } else { linkTo(`/subject/textbook/question/${result.id}`); } }).catch((e) => { if (e.result) form.setFields(formatFormError(data, e.result)); }); } }); } renderAttr() { const { id } = this.params; const { getFieldDecorator } = this.props.form; return <Block flex> <h1>基本信息</h1> <Form> {getFieldDecorator('id')(<input hidden />)} <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='题型' help='设定后,不允许修改'> {getFieldDecorator('question.questionType', { rules: [ { required: true, message: '请选择题型' }, ], })( <Select disabled={id} select={TextbookType} placeholder='请选择题型' onChange={(v) => { this.refreshPlace(v); }} />, )} </Form.Item> <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='换库表' help='设定后,不允许修改'> {getFieldDecorator('libraryId', { rules: [ { required: true, message: '请选择换库表' }, ], })( <Select disabled={id} {...this.state.libraryId} placeholder='请选择换库表' onChange={(v) => { this.refreshNo(v); }} />, )} </Form.Item> <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='题目序号'> {getFieldDecorator('no')( <Input disabled />, )} </Form.Item> <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='考点'> {getFieldDecorator('question.place', { rules: [ { required: true, message: '请选择考点' }, ], })( <Select select={this.state.placeList} placeholder='请选择考点' onChange={(v) => { this.refreshPart(v); }} />, )} </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('question.qxContent', { })( <Editor placeholder='输入内容' />, )} </Form.Item> </Form> </Block>; } renderTab() { return <Tabs activeKey='textbook' onChange={(tab) => { switch (tab) { case 'sentence': linkTo('/subject/sentence/question'); break; case 'base': linkTo('/subject/question'); break; default: } }}> <Tabs.TabPane key='base' tab='考试题型' /> <Tabs.TabPane key='sentence' tab='长难句' /> <Tabs.TabPane key='textbook' tab='数学机经' /> </Tabs>; } 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>; } }