import React from 'react'; import { Button } from 'antd'; import Input from '../../libs/Input'; import Checkbox from '../../libs/Checkbox'; import Radio from '../../libs/Radio'; import Dropdown from '../../libs/Dropdown'; // import Button from '../../libs/Button'; import ContentEditable from '../../libs/ContentEditable'; import ShakeTransition from '../../libs/Shake'; import Dialog from '../../libs/Dialog'; import uuid from '../../utils/utils'; import './index.scss'; const rowOptions = [1, 2, 3, 4]; class QuestionnairEditor extends React.PureComponent { constructor(props) { super(props); this.temp = ''; this.otherOptionInput = ''; this.answer = {}; } // static defaultProps = { // acitveAnswer: true, // } state = { toggleMutiOption: false, editor: { ...this.props.editor }, hover: false, inputShake: false, optionShake: [], hasOption: [], scoreShake: [], hasScore: [], hasTitle: true, dialogVisible: false, mutiOption: '', otherOptionInput: '', otherOptionForwards: '' }; /* 首先有点乱。。。 * 由于每次每个题目的操作实际上都是在操作整个题目数组,题目数组交给了题目组件的父组件来管理 * 所以每次题目操作完以后更新父组件的题目数组,父组件更新会触发题目组件的componentWillReceiveProps生命周期函数 */ componentWillReceiveProps(nextProps) { /* * 每次只能编辑一个题目,所以触发再次添加题目的操作,将会引起当前题目的抖动 * 连续点击产生连续抖动的效果,所以创建一个变量editorShake,来标志表格需要抖动 * 由于是更新数组,为了在抖动的效果下保留之前填写的数据,所以比较之前和新的editorShake是否相同 * 如果不同则说明只是要产生抖动,只更新editorShake变量 */ if (nextProps.editor.editorShake !== this.props.editor.editorShake) { this.setState({ editor: { ...this.state.editor, editorShake: nextProps.editor.editorShake } }); } else { this.setState({ editor: { ...this.state.editor, ...nextProps.editor } }); } } switchEditor = type => { switch (type) { case 'radio': return '单选题'; case 'dropdown': return '下拉题'; case 'checkbox': return '多选题'; case 'textarea': return '多行文本题'; case 'text': return '单行文本题'; case 'input': return '填空题'; default: return '错误'; } }; handleChange = (e, index) => { let value = e.target ? e.target.value : e; let key = e.target.name; let checked = e.target.checked; if (key === 'title' && value) { //控制题目input边框颜色 this.setState({ hasTitle: true }); } if (key === 'options') { let { options } = this.state.editor; let { hasOption } = this.state; hasOption[index] = true; this.setState({ hasOption: [...hasOption] }); let optionsTemp = options.concat(); optionsTemp[index] = value; value = optionsTemp; } if (key === 'scores') { let { scores } = this.state.editor; let { hasScore } = this.state; console.log('hasScore', hasScore); hasScore[index] = true; this.setState({ hasScore: [...hasScore] }); let scoresTemp = scores.concat(); scoresTemp[index] = value; value = scoresTemp; } if (key == 'warnFlag') { let { warnFlag } = this.state.editor; let warnFlagTemp = warnFlag.concat(); console.log('warnFlagTemp', warnFlagTemp) warnFlagTemp[index] = checked; value = warnFlagTemp; } if (key === 'required' || key === 'remark') { value = checked; } if (key === 'maxLength') { value = parseInt(value); } this.setState(prevState => ({ editor: { ...prevState.editor, [key]: value } })); }; //填写答案时触发的事件 handleAnswerChange = (e, index) => { let { type } = this.state.editor; let value = e.target.value; this.optionIndex = e.target.dataset.index; console.log('answer', this, this.answer, type, this.optionIndex); if (value === 'undefined') { value = this.otherOptionValue; } if (type === 'checkbox') { this.answer.checkbox = this.answer.checkbox || {}; this.answer.checkbox.optionValue = this.answer.checkbox.optionValue || []; this.answer.checkbox.optionIndex = this.answer.checkbox.optionIndex || []; let valueIn = this.answer.checkbox.optionValue.includes(value); let indexIn = this.answer.checkbox.optionIndex.includes(this.optionIndex); this.answer.checkbox.optionValue[this.optionIndex] = valueIn ? null : value; this.answer.checkbox.optionIndex[this.optionIndex] = indexIn ? null : this.optionIndex; // this.answer.checkbox.otherOptionValue = this.otherOptionValue; } else if (type === 'radio') { this.answer[type] = { optionValue: value, optionIndex: this.optionIndex // otherOptionValue: this.otherOptionValue }; } else { this.answer[type] = value; } const answerEditor = { ...this.state.editor, answer: this.answer }; console.log(answerEditor, this.props.index); this.props.onAnswer && this.props.onAnswer(answerEditor, this.props.index); }; //填写radio、checkbox'其他'选项时触发的方法 handleOtherOptionInputChange = e => { const { type, otherOptionForwards, otherOptionBackwards } = this.state.editor; this.otherOptionValue = e.target.innerHTML; this.allValue = otherOptionForwards + this.otherOptionValue + otherOptionBackwards; this.optionIndex = e.target.dataset.index; if (type === 'checkbox') { const length = this.answer.checkbox.optionValue.length; this.answer.checkbox.optionValue[length - 1] = this.answer.checkbox.optionValue[length - 1] === null ? null : this.allValue; this.answer.checkbox.otherOptionValue = this.allValue; } else if (type === 'radio') { this.answer[type] = { optionValue: this.allValue, optionIndex: this.optionIndex, otherOptionValue: this.allValue }; } else { this.answer[type] = this.allValue; } const answerEditor = { ...this.state.editor, answer: this.answer }; console.log(answerEditor, this.props.index); this.props.onAnswer && this.props.onAnswer(answerEditor, this.props.index); }; //新增选项 createOption = () => { this.setState(prevState => ({ editor: { ...prevState.editor, options: [...prevState.editor.options, ''] } })); }; //删除选项 deleteOption = index => { let options = [...this.state.editor.options]; options.splice(index, 1); this.setState(prevState => ({ editor: { ...prevState.editor, options } })); }; /* * 以下都是有关于批量编辑的事件 */ //点击打开批量编辑的弹窗 handleMutiOption = () => { this.setState({ dialogVisible: true, mutiOption: this.state.editor.options.join('\n') }); }; //批量编辑textarea中的change handleMutiTextarea = e => { this.mutiTextareaValue = e.target.value; this.setState({ mutiOption: e.target.value }); }; //关闭批量编辑的弹窗 closeDialog = () => { this.setState({ dialogVisible: false }); }; //打开批量编辑的弹窗 confirmDialog = () => { const options = this.mutiTextareaValue.split('\n'); this.setState(prevState => ({ dialogVisible: false, editor: { ...prevState.editor, options } })); }; //确认 confirm = () => { const { index, handleConfirm } = this.props; const { editor, inputShake } = this.state; if (!editor.title && editor.type !== 'input') { this.setState(prevState => ({ inputShake: !prevState.inputShake, hasTitle: false })); return; } //判断选项是否为空 if (['radio', 'checkbox', 'dropdown'].includes(editor.type)) { let empty = editor.options.some((item, index) => { if (item === '') { this.setState(prevState => { prevState.optionShake[index] = !prevState.optionShake[index]; prevState.hasOption[index] = false; return { optionShake: [...prevState.optionShake], hasOption: [...prevState.hasOption] }; }); return true; } }); let emptyScore = editor.scores.some((item, index) => { if (item === '') { this.setState(prevState => { prevState.scoreShake[index] = !prevState.scoreShake[index]; prevState.hasScore[index] = false; return { scoreShake: [...prevState.scoreShake], hasScore: [...prevState.hasScore] }; }); return true; } }); if (empty || emptyScore) { return; } } const newEditor = { ...editor, isEditor: false, isFirst: false }; if (handleConfirm) { handleConfirm(index, newEditor); } this.isFirst = false; this.temp = JSON.parse(JSON.stringify(this.state.editor)); }; //取消 cancel = () => { const { index, handleCancel } = this.props; if (handleCancel) { handleCancel(index); } this.setState({ editor: this.temp }); }; //编辑 edit = () => { const { index, handleEdit } = this.props; if (handleEdit) { handleEdit(index); } }; //复制 copy = () => { const { index, handleCopy } = this.props; if (handleCopy) { handleCopy(index); } }; //删除 remove = () => { const { index, handleRemove } = this.props; if (handleRemove) { handleRemove(index); } }; //鼠标进入 mouseEnter = () => { if (!this.props.drag && !this.props.acitveAnswer) { this.setState({ hover: true }); } }; //鼠标离开 mouseLeave = () => { if (!this.props.drag && !this.props.acitveAnswer) { this.setState({ hover: false }); } }; disableEnter = event => { if (event.which == 13) { event.cancelBubble = true; event.preventDefault(); event.stopPropagation(); } }; render() { const { index, curMoveItem, drag, acitveAnswer } = this.props; const { toggleMutiOption, editor, hover, inputShake, optionShake, hasOption, scoreShake, hasScore, hasTitle, dialogVisible, mutiOption } = this.state; let { type, isEditor, title, required, remark, remarkText, options, scores, rows, textareaHeight, maxLength, otherOption, otherOptionForwards, otherOptionBackwards, completionForwards, completionBackwards, editorShake, answer, warnFlag } = editor; this.answer = answer ? JSON.parse(JSON.stringify(answer)) : {}; this.otherOptionValue = answer ? this.answer[type].otherOptionValue : []; /* * * 以下元素为编辑状态下的元素 * */ //编辑状态下的题目 const ediTitleEl = (
); //编辑状态下的选项框 const optionsArr = options.map((option, index) => { return (
this.deleteOption(index)} >
); }); //编辑状态下的选项框和新建框 const ediOptionsEl = (
{optionsArr}
新建选项
); //编辑状态下的”其他“选项 const ediOtherOptionsEl = (
____
this.handleChange({ target: { value: false, name: 'otherOption' } }) } >
); //编辑状态下的填空题 const ediCompletionEl = (
____
); //添加"其他"选项 | 批量编辑 const ediCtrlOptionsEl = (
{/* | */}
); /* * * 以下元素为填写状态下的元素 * */ //填写状态下的填空 const subCompletionEl = (
{completionForwards}
{completionBackwards}
); //填写状态下的单选、多选其他选项 const subOtherOptionsEl = (
{otherOptionForwards}
{otherOptionBackwards}
); //填写状态下的单选、多选 const optionsCom = otherOption ? options.concat('undefined') : options; const subRadioEl = (
{optionsCom.map((data, index) => { return ( ); })}
); const subCheckboxEl = (
{optionsCom.map((data, index) => { return ( ); })}
); //填写状态下的下拉框 const subDropdownEl = ( ); const optionsEl = type === 'dropdown' ? subDropdownEl : type === 'radio' ? subRadioEl : subCheckboxEl; //填写状态下的单行文本、多行文本 const subTextEl = ( ); const subTextareaEl = (