import React from 'react'; import { Form, Input, InputNumber, Tabs, Switch, Checkbox, Row, Col, Button, Tag, Dropdown, Menu } from 'antd'; import './index.less'; import Page from '@src/containers/Page'; import Block from '@src/components/Block'; import Editor from '@src/components/Editor'; // import ContextMenuLayout from '@src/layouts/ContextMenuLayout'; // import Select from '@src/components/Select'; // import FileUpload from '@src/components/FileUpload'; import { formatFormError, generateUUID } from '@src/services/Tools'; import { asyncSMessage } from '@src/services/AsyncTools'; import { SentenceOption } from '../../../../Constant'; // import { Preview } from '../../../stores/preview'; import { Exercise } from '../../../stores/exercise'; import { Sentence } from '../../../stores/sentence'; import { System } from '../../../stores/system'; import config from './index'; const stopWords = [',', '.', ':', '!', ';', '?', '\\', '/', '`', '\'', '', '。', ',', '?', '!', '“', '”']; const htmlReg = /[.,!?。,!?“”]*<[^>]+>[.,!?。,!?“”]*/i; const sReg = /[.,!?。,!?“”]+/i; // const uuidReg = /@(.*)@(.*)/i; export default class extends Page { constructor(props) { super(props); this.targetWord = null; this.uuidMap = {}; this.uuidList = []; const { id } = this.params; if (id) { config.title = '编辑长难句题目'; } else { config.title = '添加长难句题目'; } } initState() { return { currentKey: 'subject' }; } 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 }); }); } initData() { const { id } = this.params; const { form } = this.props; this.uuidMap = {}; this.uuidList = []; this.targetWord = null; let handler; if (id) { handler = Sentence.getQuestion({ id }); this.setState({ mode: 'setting' }); } else { // "

The furthest distance in the world  

Is not between life and death 

But when I stand in front of you 

Yet you don\"t know that I love you

" handler = Promise.resolve({ no: 1, question: { stem: '' } }); } handler .then(result => { result.isPaper = !!result.isPaper; result.isTrail = !!result.isTrail; result.question.questionType = 'sentence'; result.question.answer = result.question.answer || {}; form.getFieldDecorator('question.answer.subject'); form.getFieldDecorator('question.answer.predicate'); form.getFieldDecorator('question.answer.object'); form.getFieldDecorator('question.answer.options'); form.getFieldDecorator('question.qxContent'); form.getFieldDecorator('question.stem'); form.getFieldDecorator('question.questionType'); form.getFieldDecorator('question.place'); form.getFieldDecorator('question.chineseContent'); form.getFieldDecorator('question.id'); form.getFieldDecorator('questionId'); form.getFieldDecorator('title'); form.getFieldDecorator('isPaper'); form.getFieldDecorator('isTrail'); form.getFieldDecorator('no'); form.getFieldDecorator('id'); form.setFieldsValue(result); const { stem } = result.question; const { subject, predicate, object } = result.question.answer; this.setState({ data: result, subject, predicate, object, stem }); // 生成uuid列表 this.uuidList = (stem || '').replace(/]*)["']>([^<>]*)<\/span>/g, '@@$1_@_$2@@').split('@@').filter(row => row.indexOf('_@_') >= 0).map(row => { const [uuid, content] = row.split('_@_'); this.uuidMap[uuid] = content; return uuid; }); console.log(this.uuidList, this.uuidMap); }); } submit() { const { form } = this.props; const { mode } = this.state; if (mode !== 'setting') { asyncSMessage('请先退出编辑模式', 'warn'); return; } form.validateFields((err) => { if (!err) { const data = form.getFieldsValue(); data.isTrail = data.isTrail ? 1 : 0; data.isPaper = data.isPaper ? 1 : 0; data.question.stem = this.state.stem; data.question.description = data.question.stem.replace(/<[^>]+>/g, ''); data.question.answer = data.question.answer || {}; let handler; if (!data.id) { handler = Sentence.addQuestion(data); } else { handler = Sentence.editQuestion(data); } handler.then((result) => { asyncSMessage('保存成功'); if (data.id) { linkTo(`/subject/sentence/question/${data.id}`); } else { linkTo(`/subject/sentence/question/${result.id}`); } }).catch((e) => { if (e.result) form.setFields(formatFormError(data, e.result)); else { asyncSMessage(e.message, 'error'); } }); } }); } removeAnswer(key, index) { const { setFieldsValue, getFieldValue } = this.props.form; const data = getFieldValue(`question.answer.${key}`) || []; if (data.length > index) { data.splice(index, 1); } setFieldsValue({ [`question.answer.${key}`]: data }); this.setState({ [key]: data }); } addAnswer(key, uuid, text) { const { setFieldsValue, getFieldValue } = this.props.form; const data = getFieldValue(`question.answer.${key}`) || []; data.push([{ text, uuid }]); setFieldsValue({ [`question.answer.${key}`]: data }); this.setState({ [key]: data }); } appendAnswer(key, index, uuid, text) { const { setFieldsValue, getFieldValue } = this.props.form; const data = getFieldValue(`question.answer.${key}`) || []; data[index].push({ text, uuid }); setFieldsValue({ [`question.answer.${key}`]: data }); this.setState({ [key]: data }); } renderContextMenu() { const { getFieldValue } = this.props.form; const { currentKey } = this.state; const uuid = this.targetWord.getAttribute('uuid'); const text = this.targetWord.innerText; const data = getFieldValue(`question.answer.${currentKey}`) || []; const items = []; items.push({ title: '新答案', command: 'new' }); data.forEach((row, i) => { // 过滤已经在的答案 if (row.filter(r => r.uuid !== uuid).length !== row.length) return; items.push({ title: `插入: ${row.map(r => r.text).join(', ')}`, command: 'append', i }); }); return ( this.clickContentMenu(currentKey, k, uuid, text)}> {items.map((item, i) => { return {item.title || item.name}; })} ); } clickContentMenu(key, k, uuid, text) { const item = k.item.props; switch (item.command) { case 'new': this.addAnswer(key, uuid, text); break; case 'append': this.appendAnswer(key, item.i, uuid, text); break; default: } } generateContent(content) { const { setFieldsValue } = this.props.form; // 处理编辑器未清除的标签: 主要是包含空格的标签属性 content = content.replace(/<[^>]+\s+[^>]+>([^<>]*)<\/[^>]+>/g, '$1'); this.index = 0; const list = ['

', ' ', ',', '.', '!', '?', ' ', ':', ';']; const result = this.splitList(list, 0, content); // console.log(this.uuidList, this.uuidMap); // 对比答案,是否uuid存在 let { subject = [], predicate = [], object = [] } = this.state; let flag = false; subject = subject.map(row => { return row.filter(r => { if (this.uuidMap[r.uuid] === r.text) return true; flag = true; return false; }); }).filter(row => row.length); predicate = predicate.map(row => { return row.filter(r => { if (this.uuidMap[r.uuid] === r.text) return true; flag = true; return false; }); }).filter(row => row.length); object = object.map(row => { return row.filter(r => { if (this.uuidMap[r.uuid] === r.text) return true; flag = true; return false; }); }).filter(row => row.length); if (flag) { asyncSMessage('修改影响答案,请再次确认答案', 'warn'); setFieldsValue({ 'question.answer.subject': subject, 'question.answer.predicate': predicate, 'question.answer.object': object }); // console.log(subject, predicate, object); this.setState({ subject, predicate, object }); } return result; } splitList(list, index, content) { if (list.length === index) { return this.generateText(content); } const result = content.split(list[index]).map(row => { return this.splitList(list, index + 1, row); }); if (result.length === 0) return content; if (result.length === 1) return result[0]; return result.join(list[index]); } generateText(content) { if (content.indexOf(stopWords) >= 0) return content; // 判断是否包含html标签 const r = htmlReg.exec(content); if (r === null) { const sr = sReg.exec(content); if (sr === null) { return this.generateTag(content); } // 句尾标点符号 return `${this.generateTag(content.replace(sr[0], ''))}${sr[0]}`; } if (r.index === 0) { // 头部html标签 return `${r[0]}${this.generateTag(content.replace(r[0], ''))}`; } // 尾部html标签 return `${this.generateTag(content.replace(r[0], ''))}${r[0]}`; } generateTag(content) { // return `${content}`; // 处理uuid信息 // const r = uuidReg.exec(content); // if (r === null) { let uuid; if (this.uuidList.length <= this.index) { do { uuid = generateUUID(4); } while (this.uuidMap[uuid]); this.uuidMap[uuid] = content; this.uuidList.push(uuid); } else { uuid = this.uuidList[this.index]; this.uuidMap[uuid] = content; } this.index += 1; return `${content}`; // } // uuidMap[r[1]] = `${r[2]}`; // return `${r[2]}`; } renderTitle() { const { getFieldDecorator } = this.props.form; return

{getFieldDecorator('id')()} {getFieldDecorator('no', { rules: [ { required: true, message: '请输入序号' }, // { // validator: (rule, value, callback) => { // if (this.partList.indexOf(value) >= 0) callback('该part已被使用'); // else callback(); // callback(); // }, // }, ], })( parseInt(v, 10) || 1} />, )} {getFieldDecorator('title', { rules: [ { required: true, message: '请输入名称' }, ], })( , )} {getFieldDecorator('isTrail', { valuePropName: 'checked', })( , )} {/* 不允许修改组卷逻辑 */} {getFieldDecorator('isPaper', { valuePropName: 'checked', })( , )}
; } renderBase() { const { getFieldDecorator, getFieldValue, setFieldsValue } = this.props.form; const { stem, mode } = this.state; return

题干信息: { if (value) { // console.log(stem); getFieldDecorator('question.stem'); setFieldsValue({ 'question.stem': stem }); this.setState({ mode: 'edit' }); } else { // 编辑器未修改会使用添加好uuid标签的结果 // 通过保留onChange获取到最后一次修改记录 this.setState({ mode: 'setting', stem: this.generateContent(this.stem || getFieldValue('question.stem') || '') }); } }} />

{getFieldDecorator('question.id')()} { {getFieldDecorator('question.stem')( { // console.log(content, delta, source, editor); // setFieldsValue({ 'question.stem': content }); // }} onChange={(content) => { this.stem = content; // console.log(this.stem); }} placeholder='请输入内容' />, )} } {mode === 'setting' && this.renderContextMenu()} trigger={['click']}>
{ this.targetWord = e.target; }} />} ; } renderAnswer() { const { getFieldDecorator } = this.props.form; const { subject = [], predicate = [], object = [], currentKey } = this.state; return

题目答案: 进入设置模式,选择主谓宾后,点击答案单词

value.target.checked && this.setState({ currentKey: 'subject' })} /> 主语 {getFieldDecorator('question.answer.subject', { rules: [{ required: true, message: '请输入主语' }], })()} {subject.map((row, index) => { return { this.removeAnswer('subject', index); }}>{row.map(r => r.text).join(', ')}; })}
value.target.checked && this.setState({ currentKey: 'predicate' })} /> 谓语 {getFieldDecorator('question.answer.predicate', { rules: [{ required: true, message: '请输入谓语' }], })()} {predicate.map((row, index) => { return { this.removeAnswer('predicate', index); }}>{row.map(r => r.text).join(', ')}; })}
value.target.checked && this.setState({ currentKey: 'object' })} /> 宾语 {getFieldDecorator('question.answer.object', { rules: [{ required: true, message: '请输入宾语' }], })()} {object.map((row, index) => { return { this.removeAnswer('object', index); }}>{row.map(r => r.text).join(', ')}; })}
; } renderOption() { const { getFieldDecorator } = this.props.form; return

选项信息(长难句)

{getFieldDecorator('question.answer.options', { rules: [{ required: true, message: '请输入选项信息' }], })( , )}
; } renderQX() { const { getFieldDecorator } = this.props.form; return
{getFieldDecorator('question.qxContent', { })( System.uploadImage(file)} />, )}
; } renderChinese() { const { getFieldDecorator } = this.props.form; return
{getFieldDecorator('question.chineseContent', { })( System.uploadImage(file)} />, )}
; } renderTab() { return { switch (tab) { case 'textbook': linkTo('/subject/textbook/question'); break; case 'base': linkTo('/subject/question'); break; default: } }}> ; } renderView() { return
{this.renderTab()} {this.renderTitle()} {this.renderBase()} {this.renderAnswer()} {this.renderOption()} {this.renderQX()} {this.renderChinese()}
; } }