import React, { Component } from 'react'; import Cropper from 'react-cropper'; import 'cropperjs/dist/cropper.css'; import './index.less'; import { Checkbox, Icon } from 'antd'; import FileUpload from '@src/components/FileUpload'; import Assets from '@src/components/Assets'; import scale from '@src/services/Scale'; import { asyncSMessage } from '@src/services/AsyncTools'; import AnswerButton from '../AnswerButton'; import { SelectInput, VerificationInput, DefaultInput, Input, Textarea } from '../Input'; import { MobileArea, TextbookFeedbackTarget, TextbookSubject, AskTarget } from '../../../Constant'; import Invite from '../Invite'; import Modal from '../Modal'; import { Common } from '../../stores/common'; import { User } from '../../stores/user'; import { My } from '../../stores/my'; import Select from '../Select'; import { formatDate, getMap } from '../../../../src/services/Tools'; const TextbookFeedbackTargetMap = getMap(TextbookFeedbackTarget, 'value', 'tip'); export class BindPhone extends Component { constructor(props) { super(props); this.validNumber = 0; this.props.data = this.props.data || {}; this.state = Object.assign({ step: 0, data: {}, empty: {} }, this.initState(this.props)); this.stepProp = { 0: { title: '绑定手机', onConfirm: props.onConfirm, }, 1: { title: '绑定手机', onConfirm: () => { this.submit(); }, onCancel: props.onCancel, confirmText: '提交', }, }; } initState(props) { if (!props.show || this.props.show) return {}; const data = Object.assign({}, props.data); if (!data.area) data.area = MobileArea[0].value; return { step: props.data.mobile ? 0 : 1, data, validError: '', empty: {} }; } componentWillReceiveProps(nextProps) { this.setState(this.initState(nextProps)); } onNext() { this.setState({ step: 1, validError: '', mobileError: '', empty: {} }); } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty, mobileError: null }); } validMobile() { const { data } = this.state; const { area, mobile } = data; if (!area || !mobile) return; this.validNumber += 1; const number = this.validNumber; if (mobile === this.props.data.mobile) { this.setState({ mobileError: '' }); return; } User.validMobile(area, mobile) .then(result => { if (number !== this.validNumber) return Promise.resolve(); if (result) { this.setState({ mobileError: '' }); return Promise.resolve(); } return Promise.reject(new Error('该手机已绑定其他账号,请更换手机号码')); }) .catch(err => { this.setState({ mobileError: err.message }); }); } sendValid() { const { data, mobileError } = this.state; const { area, mobile } = data; if (mobileError) return Promise.reject(); if (!area || !mobile) { this.setState({ empty: { area: !data.area, mobile: !data.mobile } }); return Promise.reject(); } return Common.sendSms(area, mobile) .then(result => { if (result) { asyncSMessage('发送成功'); this.setState({ mobileError: '', validError: '' }); } else { throw new Error('发送失败'); } }) .catch(err => { this.setState({ mobileError: err.message }); throw err; }); } submit() { const { data, validError, mobileError } = this.state; if (validError || mobileError) return; const { area, mobile, mobileVerifyCode } = data; if (!area || !mobile || !mobileVerifyCode) { this.setState({ empty: { area: !data.area, mobile: !data.mobile, mobileVerifyCode: !mobileVerifyCode } }); return; } My.bindMobile(area, mobile, mobileVerifyCode) .then(() => { asyncSMessage('操作成功'); this.setState({ step: 0, validError: '', mobileError: '' }); User.infoHandle(Object.assign(this.props.data, { area, mobile })); this.props.onConfirm(); }) .catch(err => { if (err.message.indexOf('验证码') >= 0) { this.setState({ validError: err.message }); } else { this.setState({ mobileError: err.message }); } }); } render() { const { show } = this.props; const { step = 0 } = this.state; return ( <Modal className="bind-phone-modal" show={show} width={630} {...this.stepProp[step]}> <div className="bind-phone-modal-wrapper">{this[`renderStep${step}`]()}</div> </Modal> ); } renderStep0() { const { data } = this.state; return ( <div className="step-0-layout t-2"> 已绑定手机 {data.mobile} <a onClick={() => this.onNext()}>修改</a> </div> ); } renderStep1() { return ( <div className="step-1-layout"> <div className="label">手机号</div> <div className="input-layout"> <SelectInput className="w-10" placeholder="请输入手机号" selectValue={this.state.data.area} select={MobileArea} value={this.state.data.mobile} error={this.state.mobileError} empty={this.state.empty.mobile} onSelect={value => { this.changeData('area', value); this.validMobile(); }} onChange={e => { this.changeData('mobile', e.target.value); this.validMobile(); }} /> <VerificationInput className="w-10" placeholder="请输入验证码" value={this.state.data.mobileVerifyCode} error={this.state.validError} empty={this.state.empty.mobileVerifyCode} onSend={() => { return this.sendValid(); }} onChange={e => { this.changeData('mobileVerifyCode', e.target.value); this.setState({ validError: '' }); }} /> </div> </div> ); } } export class BindEmail extends Component { constructor(props) { super(props); this.validNumber = 0; this.props.data = this.props.data || {}; this.state = Object.assign({ step: 0, data: {}, empty: {} }, this.initState(this.props)); this.stepProp = { 0: { title: '绑定邮箱', onConfirm: props.onConfirm, }, 1: { title: '绑定邮箱', onConfirm: () => { this.submit(); }, onCancel: props.onCancel, confirmText: '提交', }, }; } initState(props) { if (!props.show || this.props.show) return {}; return { step: props.data.email ? 0 : 1, data: Object.assign({}, props.data) }; } componentWillReceiveProps(nextProps) { this.setState(this.initState(nextProps)); } onNext() { this.setState({ step: 1, error: '', empty: {} }); } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty, error: null }); } validEmail() { const { data } = this.state; const { email } = data; if (!email) return; this.validNumber += 1; const number = this.validNumber; if (email === this.props.data.email) { this.setState({ error: '' }); return; } User.validEmail(email) .then(result => { if (number !== this.validNumber) return Promise.resolve(); if (result) { this.setState({ error: '' }); return Promise.resolve(); } return Promise.reject(new Error('该邮箱已绑定其他账号,请更换邮箱地址')); }) .catch(err => { this.setState({ error: err.message }); }); } submit() { const { data, error } = this.state; if (error) return; if (!data.email) { this.setState({ empty: { email: !data.email } }); return; } const { email } = data; My.bindEmail(email) .then(() => { asyncSMessage('操作成功'); this.setState({ step: 0, error: '' }); User.infoHandle(Object.assign(this.props.data, { email })); this.props.onConfirm(); }) .catch(e => { this.setState({ error: e.message }); }); } render() { const { show } = this.props; const { step = 0 } = this.state; return ( <Modal className="bind-email-modal" show={show} width={630} {...this.stepProp[step]}> <div className="bind-email-modal-wrapper">{this[`renderStep${step}`]()}</div> </Modal> ); } renderStep0() { const { data } = this.state; return ( <div className="step-0-layout t-2"> 已绑定邮箱 {data.email} <a onClick={() => this.onNext()}>修改</a> </div> ); } renderStep1() { return ( <div className="step-1-layout"> <div className="label">邮箱地址</div> <div className="input-layout"> <DefaultInput className="w-10" placeholder="请输入邮箱" value={this.state.data.email} error={this.state.error} empty={this.state.empty.email} onChange={e => { this.changeData('email', e.target.value); this.validEmail(); }} /> </div> </div> ); } } export class EditInfo extends Component { constructor(props) { super(props); this.props.data = this.props.data || {}; this.state = Object.assign({ data: {}, empty: {} }, this.initState(this.props)); } initState(props) { if (props.image && this.waitImage) { const { state } = this; Common.upload(props.image) .then(result => { const { data } = this.state; data.avatar = result.url; this.setState({ data, uploading: false }); }) .catch(e => { this.setState({ imageError: e.message }); }); state.uploading = true; this.waitImage = false; return state; } if (!props.show || this.props.show) return {}; return { data: Object.assign({}, props.data) }; } componentWillReceiveProps(nextProps) { this.setState(this.initState(nextProps)); } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty, nicknameError: null }); } strLen(str) { let len = 0; for (let i = 0; i < str.length; i += 1) { if (str.charCodeAt(i) > 255 || str.charCodeAt(i) < 0) len += 2; else len += 1; } return len; } // 将字符串拆成字符,并存到数组中 strToChars(str) { const chars = []; for (let i = 0; i < str.length; i += 1) { chars[i] = [str.substr(i, 1), this.isCHS(str, i)]; } return chars; } // 判断某个字符是否是汉字 isCHS(str, i) { if (str.charCodeAt(i) > 255 || str.charCodeAt(i) < 0) { return true; } return false; } // 截取字符串(从start字节到end字节) subCHString(str, start, end) { let len = 0; let s = ''; const chars = this.strToChars(str); for (let i = 0; i < str.length; i += 1) { if (chars[i][1]) { len += 2; } else { len += 1; } if (end < len) { return s; } if (start < len) { s += chars[i][0]; } } return s; } // 截取字符串(从start字节截取length个字节) subCHStr(str, start, length) { return this.subCHString(str, start, start + length); } submit() { const { data, nicknameError } = this.state; if (nicknameError) return; if (!data.nickname) { this.setState({ empty: { nickname: !data.nickname } }); return; } const len = this.strLen(data.nickname); if (len < 2 || len > 14) { this.setState({ nicknameError: '用户名长度不足2个字符或超过14个字符' }); return; } const { nickname, avatar } = data; My.editInfo({ nickname, avatar }) .then(() => { asyncSMessage('操作成功'); User.infoHandle(Object.assign(this.props.data, { nickname, avatar })); this.props.onConfirm(); this.setState({ nicknameError: '' }); }) .catch(e => { this.setState({ nicknameError: e.message }); }); } render() { const { show, onCancel, onSelectImage } = this.props; return ( <Modal className="edit-info-modal" show={show} width={630} title="修改资料" confirmText="保存" onCancel={onCancel} onConfirm={() => { this.submit(); }} > <div className="edit-info-modal-wrapper"> <div className="edit-info-modal-block"> <div className="label">用户名</div> <div className="input-layout"> <DefaultInput className="w-10" placeholder="2-14个字符。" value={this.state.data.nickname || ''} error={this.state.nicknameError} empty={this.state.empty.nickname} onChange={e => { this.changeData('nickname', e.target.value); }} /> </div> </div> <div className="edit-info-modal-block"> <div className="label">头像</div> <div className="input-layout"> <FileUpload uploading={this.state.uploading} value={this.state.data.avatar} onUpload={({ file }) => { this.waitImage = true; onSelectImage(file); return Promise.reject(); }} /> {this.state.imageError || ''} </div> </div> </div> </Modal> ); } } export class RealAuth extends Component { constructor(props) { super(props); this.state = { data: {} }; } render() { const { show, onConfirm } = this.props; return ( <Modal className="real-auth-modal" show={show} width={630} title="实名认证" confirmText="好的,知道了" btnAlign="center" onConfirm={onConfirm} > <div className="real-auth-modal-wrapper"> <div className="real-auth-text"> <div className="t1">完成实名认证即可领取:</div> <div className="t2">6个月VIP权限 和 5折机经优惠劵。</div> <div className="t3">扫码关注公众号,点击“我的-实名认证”</div> </div> <div className="real-auth-qrcode"> <Assets name="qrcode" /> </div> </div> </Modal> ); } } export class EditAvatar extends Component { constructor(props) { super(props); this.state = Object.assign({ data: {} }, this.initState(this.props)); } initState(props) { if (props.image) this.loadImage(props.image); if (!props.show || this.props.show) return {}; return { data: {} }; } componentWillReceiveProps(nextProps) { this.setState(this.initState(nextProps)); } loadImage(file) { this.defaultZoomValue = 1; if (window.FileReader) { const reader = new FileReader(); reader.readAsDataURL(file); // 渲染文件 reader.onload = arg => { this.setState({ image: arg.target.result, fileName: file.name, zoomValue: 1 }); }; } else { const img = new Image(); img.onload = function () { const canvas = document.createElement('canvas'); canvas.height = img.height; canvas.width = img.width; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); this.setState({ image: canvas.toDataURL() }); }; img.src = '1.gif'; } } computerZoom() { const data = this.cropRef.getImageData(); this.defaultZoomValue = 200 / parseFloat(Math.max(data.naturalWidth, data.naturalHeight)); } crop() { // image in dataUrl // console.log(this.cropRef.getCroppedCanvas().toDataURL()) // const canvas = this.cropRef.getCroppedCanvas(); // const avatar = scale(this.props.crop, canvas, 'png-src'); // let scaleCanvas = this.cropRef.getCroppedCanvas(this.props.crop) // this.setState({ avatar }); } select() { const { fileName } = this.state; const { onConfirm } = this.props; const canvas = this.cropRef.getCroppedCanvas(); const scaleCanvas = scale(this.props.crop, canvas); // let scaleCanvas = this.cropRef.getCroppedCanvas(this.props.crop) scaleCanvas.toBlob(blob => { const file = new File([blob], fileName); onConfirm(file); }); } render() { const { show, onCancel } = this.props; const { image } = this.state; return ( <Modal className="edit-avatar-modal" show={show} width={630} title="调整头像" confirmText="保存头像" onConfirm={() => { this.select(); }} onCancel={onCancel} > <div className="edit-avatar-modal-wrapper"> <div className="edit-avatar-o"> <Cropper ref={ref => { this.cropRef = ref; }} src={image} ready={() => { this.computerZoom(); }} style={{ height: 360, width: 360 }} // Cropper.js options aspectRatio={1} viewMode={0} // autoCropArea={0.8} preview=".img-preview" // dragMode='move' guides={false} movable={false} rotatable={false} scalable={false} // zoom={(value) => { // console.log('zoom', value); // const zoomValue = value * this.defaultZoomValue / 50; // this.cropRef.zoomTo(zoomValue); // }} cropmove={() => { this.crop(); }} toggleDragModeOnDblclick={false} cropBoxResizable /> </div> <div className="edit-avatar-r"> <div className="text">头像预览</div> <div className="img-preview" style={{ width: 100, height: 100, overflow: 'hidden' }} /> </div> </div> </Modal> ); } } export class InviteModal extends Component { constructor(props) { super(props); this.state = { data: {} }; } render() { const { show, onClose, data } = this.props; return ( <Modal className="invite-modal" show={show} width={630} title="邀请好友" onClose={onClose}> <div className="invite-modal-wrapper"> <div className="tip">每邀请一位小伙伴加入“千行GMAT”, 您的VIP权限会延长7天,可累加 无上限!赶紧行动吧~</div> <Invite data={data} /> </div> </Modal> ); } } // 模考选择下载 export class DownloadModal extends Component { constructor(props) { super(props); this.state = { checkMap: {} }; } onConfirm() { const { onConfirm, data } = this.props; if (onConfirm) onConfirm(); const { checkMap } = this.state; Object.keys(checkMap).forEach(key => { if (!checkMap[key]) return; const link = data[`${key}`]; if (link) { openLink(`${link}&download=true`); } }); this.setState({ checkList: [] }); } render() { const { show, data = {}, onCancel } = this.props; const { checkMap = {} } = this.state; const quantVersion = data.quantVersion || 0; const irVersion = data.irVersion || 0; const rcVersion = data.rcVersion || 0; return ( <Modal className="download-modal" show={show} width={570} title="下载" confirmText="下载" onConfirm={() => this.onConfirm()} onCancel={onCancel} > <div className="download-modal-wrapper"> <div className="t-2 t-s-18 m-b-1">请选择下载科目</div> <div className="m-b-1"> {quantVersion > 0 && ( <div className="t-2 t-s-16"> <Checkbox checked={checkMap.quant} onChange={() => { checkMap.quant = !checkMap.quant; this.setState({ checkMap }); }} /> <span className="m-l-5">数学</span> <span className="t-8"> (版本{quantVersion} 最后更新:{formatDate(data.quantTime, 'YYYY-MM-DD HH:mm:ss')}) </span> </div> )} {irVersion > 0 && ( <div className="t-2 t-s-16"> <Checkbox checked={checkMap.ir} onChange={() => { checkMap.ir = !checkMap.ir; this.setState({ checkMap }); }} /> <span className="m-l-5">逻辑</span> <span className="t-8"> (版本{irVersion} 最后更新:{formatDate(data.irTime, 'YYYY-MM-DD HH:mm:ss')}) </span> </div> )} {rcVersion > 0 && ( <div className="t-2 t-s-16"> <Checkbox checked={checkMap.rc} onChange={() => { checkMap.rc = !checkMap.rc; this.setState({ checkMap }); }} /> <span className="m-l-5">阅读</span> <span className="t-8"> (版本{rcVersion} 最后更新:{formatDate(data.rcTime, 'YYYY-MM-DD HH:mm:ss')}) </span> </div> )} </div> </div> </Modal> ); } } // 模考开通确认 export class OpenConfirmModal extends Component { render() { const { show, onConfirm, onCancel, data = {} } = this.props; return ( <Modal className="open-confirm-modal" show={show} width={570} title="开通确认" confirmText="开通" cancelText="暂不开通" onConfirm={onConfirm} onCancel={onCancel} > <div className="open-confirm-modal-wrapper m-b-2"> <div className="t-2 t-s-18">您正在开通「{data.title}」。</div> <div className="t-2 t-s-18">模考有效期至:{data.endTime && formatDate(data.endTime, 'YYYY-MM-DD')}</div> </div> </Modal> ); } } // 模考重置确认 export class RestartConfirmModal extends Component { render() { const { show, onConfirm, onCancel } = this.props; return ( <Modal className="restart-confirm-modal" show={show} width={570} title="重置确认" confirmText="立即重置" cancelText="暂不重置" onConfirm={onConfirm} onCancel={onCancel} > <div className="restart-confirm-modal-wrapper m-b-2"> <div className="t-2 t-s-18">重置后,可进行新一轮的模考。 </div> <div className="t-2 t-s-18 m-b-2">本轮模考的成绩和报告可在本页面或「我的报告」查看。 </div> <div className="t-2 t-s-18 m-b-1">只有 1 次重置机会。</div> </div> </Modal> ); } } export class FeedbackErrorDataModal extends Component { constructor(props) { super(props); this.state = { data: { position: ['', '', ''], content: '', originContent: '' } }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } changeDataIndex(field, index, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field][index] = value; if (value) empty[`${field}[${index}]`] = !value; this.setState({ data, empty }); } onConfirm() { const { onConfirm } = this.props; const { data } = this.state; if (!data.position[0] || !data.position[1] || !data.position[2] || !data.content || !data.originContent) { this.setState({ empty: { 'position[0]': !data.position[0], 'position[1]': !data.position[1], 'position[2]': !data.position[2], content: !data.content, originContent: !data.originContent, }, }); return Promise.reject(); } return My.addFeedbackErrorData( data.dataId, data.title, data.position.join(','), data.originContent, data.content, ).then(() => { this.setState({ data: { position: ['', '', ''], content: '', originContent: '' } }); if (onConfirm) onConfirm(); }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { position: ['', '', ''], content: '', originContent: '' } }); if (onCancel) onCancel(); } render() { const { show } = this.props; const { data, empty = {} } = this.state; return ( <Modal show={show} title="纠错" btnType="link" width={630} onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()} > <div className="t-2 m-b-1 t-s-16"> 定位: <Input value={data.position[0]} className="t-c b-c-1 m-r-5" style={{ width: 56 }} empty={empty['position[0]']} onChange={e => { this.changeDataIndex('position', 0, e.target.value); }} /> <span className="require">页</span> <Input value={data.position[1]} className="t-c b-c-1 m-r-5" style={{ width: 56 }} empty={empty['position[1]']} onChange={e => { this.changeDataIndex('position', 1, e.target.value); }} /> <span className="require">行</span> , 题号 <Input value={data.position[2]} className="t-c b-c-1" style={{ width: 56 }} empty={empty['position[2]']} onChange={e => { this.changeDataIndex('position', 2, e.target.value); }} /> </div> <div className="t-2 t-s-16">错误内容是:</div> <Textarea value={data.originContent} className="b-c-1 w-10 p-10" rows={10} placeholder={'可简单描述您发现的问题'} empty={empty.originContent} onChange={e => { this.changeData('originContent', e.target.value); }} /> <div className="t-2 t-s-16">应该更改为:</div> <Textarea value={data.content} className="b-c-1 w-10 p-10" rows={10} placeholder={'提供您认为正确的内容即可'} empty={empty.content} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class AskCourseModal extends Component { constructor(props) { super(props); this.state = { data: { position: [], content: '', originContent: '' } }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm() { const { course, courseNo, onConfirm } = this.props; const { data } = this.state; if (!data.content || !data.originContent) { this.setState({ empty: { content: !data.content, originContent: !data.originContent } }); return Promise.reject(); } return My.addCourseAsk(course.id, courseNo.id, data.position.join(','), data.originContent, data.content).then( () => { this.setState({ data: { position: [], content: '', originContent: '' } }); if (onConfirm) onConfirm(); }, ); } onCancel() { const { onCancel } = this.props; this.setState({ data: { position: [], content: '', originContent: '' } }); if (onCancel) onCancel(); } render() { const { show, selectList, courseNo, getContainer } = this.props; const { data, empty = {} } = this.state; return ( <Modal show={show} title="提问" btnType="link" width={630} getContainer={getContainer} confirmText="提交" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()} > <div className="t-2 m-b-1 t-s-16"> 针对<span className="t-4">课时{courseNo.no}</span>的{' '} <Select value={data.position} theme="white" list={selectList} onChange={item => { this.changeData('position', item.key); }} /> 进行提问. </div> <div className="t-2 t-s-16">老师讲解的内容是:</div> <Textarea value={data.originContent} className="b-c-1 w-10 p-10" rows={4} placeholder={'请简单描述,以便老师准确定位。'} empty={empty.originContent} onChange={e => { this.changeData('originContent', e.target.value); }} /> <div className="t-2 t-s-16">您的问题是:</div> <Textarea value={data.content} className="b-c-1 w-10 p-10" rows={4} placeholder={'老师会在n小时内回答你的问题。'} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class CourseNoteModal extends Component { constructor(props) { super(props); this.state = { data: { content: '' } }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm() { const { course, onConfirm } = this.props; const { data } = this.state; if (!data.content || !data.originContent) { this.setState({ empty: { content: !data.content } }); return Promise.reject(); } return My.updateCourseNote(course.id, data.courseNoId, data.content).then(() => { this.setState({ data: { content: '' } }); if (onConfirm) onConfirm(); }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { content: '' } }); if (onCancel) onCancel(); } render() { const { show, course = {}, courseNos = [], noteMap = {}, getContainer } = this.props; const { data, empty = {} } = this.state; return ( <Modal show={show} title="笔记" width={630} getContainer={getContainer} confirmText="提交" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()} > <div className="t-2 m-b-1 t-s-16"> {course.title} <Select theme="white" value={data.courseNoId} list={courseNos.map(row => { return { title: `课时${row.no}`, key: row.id, }; })} onChange={item => { if (data.courseNoId !== item.key) { data.courseNoId = item.key; data.content = noteMap[item.key] ? noteMap[item.key].content : ''; } this.setState({ data }); }} /> </div> <Textarea value={data.content} className="b-c-1 w-10 p-10" rows={10} placeholder={'写下笔记,方便以后复习。'} empty={empty.content} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class TextbookFeedbackModal extends Component { constructor(props) { super(props); this.state = { data: { content: '' }, targetList: TextbookFeedbackTarget.map(row => { return { title: row.label, key: row.value, }; }), textbookSubject: TextbookSubject.map(row => { return { title: row.label, key: row.value, }; }), }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm() { const { onConfirm } = this.props; const { data } = this.state; if (data.target !== 'new' && (!data.no || !data.content)) { this.setState({ empty: { content: !data.content, no: !data.no } }); return Promise.reject(); } if (!data.content) { this.setState({ empty: { content: !data.content } }); return Promise.reject(); } return My.addTextbookFeedback(data.textbookSubject, data.target, data.no, data.content) .then(() => { this.setState({ data: { content: '' } }); if (onConfirm) onConfirm(); }) .catch(e => { asyncSMessage(e.message, 'error'); }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { content: '' } }); if (onCancel) onCancel(); } render() { const { show } = this.props; const { data, targetList, textbookSubject, empty = {} } = this.state; return ( <Modal show={show} title="反馈" width={630} onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}> <div className="t-2 t-s-16 m-b-1"> 机经类别:{' '} <Select value={data.textbookSubject} theme="white" list={textbookSubject} onChange={value => { data.textbookSubject = value; this.setState({ data }); }} /> 反馈类型:{' '} <Select value={data.target} theme="white" list={targetList} onChange={({ key }) => { data.target = key; this.setState({ data }); }} /> <span hidden={data.target === 'new'}> {' '} 题号是{' '} <Input value={data.no} style={{ width: 80 }} className="m-l-1 b-c-1 t-c" empty={empty.no} onChange={e => { this.changeData('no', e.target.value); }} /> </span> </div> <div className="t-2 t-s-16">{TextbookFeedbackTargetMap[data.target]}:</div> <Textarea value={data.content} className="b-c-1 w-10 p-10" rows={10} placeholder={TextbookFeedbackTargetMap[data.target]} empty={empty.content} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class FaqModal extends Component { constructor(props) { super(props); this.state = { data: { content: '' } }; } componentWillReceiveProps(nextProps) { if (nextProps.defaultData && nextProps.show) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm() { const { onConfirm } = this.props; const { data } = this.state; if (!data.content) { this.setState({ empty: { content: !data.content } }); return Promise.reject(); } return My.addFaq(data.channel, data.position, data.content).then(() => { this.setState({ data: { content: '' } }); if (onConfirm) onConfirm(); }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { content: '' } }); if (onCancel) onCancel(); } render() { const { show } = this.props; const { data, empty = {} } = this.state; return ( <Modal show={show} title="咨询" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}> <Textarea className="b-c-1 w-10 p-10" value={data.content} rows={6} placeholder="请输入您的问题!" empty={empty.content} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class CommentModal extends Component { constructor(props) { super(props); this.state = { data: { content: '' } }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm() { const { onConfirm } = this.props; const { data } = this.state; if (!data.content) { this.setState({ empty: { content: !data.content } }); return Promise.reject(); } return My.addComment(data.channel, data.position, data.content).then(() => { this.setState({ data: { content: '' } }); if (onConfirm) onConfirm(); }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { content: '' } }); if (onCancel) onCancel(); } render() { const { show } = this.props; const { data, empty = {} } = this.state; return ( <Modal show={show} title="评价" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}> <Textarea value={data.content} className="b-c-1 w-10 p-10" rows={6} placeholder="您的看法对我们来说很重要!" empty={empty.content} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class FinishModal extends Component { render() { const { show, onConfirm } = this.props; return ( <Modal show={show} title="提交成功" confirmText="好的,知道了" btnAlign="center" onConfirm={() => onConfirm()}> <div className="t-2 t-s-18"> <Icon type="check" className="t-5 m-r-5" /> 您的每一次反馈都是千行进步的动力。 </div> </Modal> ); } } export class SuppleModal extends Component { constructor(props) { super(props); this.state = { data: { content: '' } }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm() { const { onConfirm } = this.props; const { data } = this.state; if (!data.content) { this.setState({ empty: { content: !data.content } }); return Promise.reject(); } return My.addRoomFeedback(data.roomId, data.content).then(() => { this.setState({ data: { content: '' } }); if (onConfirm) onConfirm(); }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { content: '' } }); if (onCancel) onCancel(); } render() { const { show, info = {} } = this.props; const { data, empty = {} } = this.state; return ( <Modal show={show} title="考场信息" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}> <div className="t-2 t-s-16"> 考场位置: {info.isOverseas ? '海外' : '中国'} {info.area ? ` ${info.area}` : ''} {info.title} </div> <div className="t-2 t-s-16">补充内容:</div> <Textarea value={data.content} className="b-c-1 w-10 p-10" empty={empty.content} rows={6} onChange={e => { this.changeData('content', e.target.value); }} /> <div className="b-b m-t-2" /> </Modal> ); } } export class SuppleFinishModal extends Component { render() { const { show, onConfirm } = this.props; return ( <Modal show={show} title="提交成功" confirmText="好的,知道了" btnAlign="center" onConfirm={() => onConfirm()}> <div className="t-2 t-s-18"> <Icon type="check" className="t-5 m-r-5" /> 内容将在审核通过后发布,感谢您的参与。 </div> </Modal> ); } } export class QuestionNoteModal extends Component { constructor(props) { super(props); this.state = { data: {}, noteField: AskTarget[0].value }; } componentWillReceiveProps(nextProps) { if (nextProps.show && nextProps.defaultData) { this.setState({ data: Object.assign({}, nextProps.defaultData, this.state.data) }); } } changeData(field, value) { let { data, empty } = this.state; data = data || {}; empty = empty || {}; data[field] = value; if (value) empty[field] = !value; this.setState({ data, empty }); } onConfirm(close) { const { questionNo, onConfirm } = this.props; const { data } = this.state; return My.updateQuestionNote(questionNo.id, data).then(() => { if (close) { this.setState({ data: {}, noteField: AskTarget[0].value }); if (onConfirm) onConfirm(); } }); } onCancel() { const { onCancel } = this.props; this.setState({ data: { content: '' } }); if (onCancel) onCancel(); } render() { const { show } = this.props; const { data, noteField } = this.state; return ( <div hidden={!show} className="question-modal question-note-modal"> <div className="mask" /> <div className="modal-body"> <div className="modal-title">提问</div> <div className="modal-content"> <div className="tabs"> {AskTarget.map(item => { return ( <div className={`tab ${noteField === item.key ? 'active' : ''}`} onClick={() => { this.setState({ noteField: item.key }); }} > <div className="text">{item.label}</div> <div className="date">{data[`${item.key}Time`] ? formatDate(data[`${item.key}Time`]) : ''}</div> </div> ); })} </div> <div className="input"> <Textarea className="textarea" value={data[`${noteField}Content`] || ''} placeholder="记下笔记,方便以后复习" onChange={e => { data[`${noteField}Time`] = new Date(); data[`${noteField}Content`] = e.target.value; this.setState({ data }); }} /> <div className="bottom"> <AnswerButton theme="cancel" size="lager" onClick={() => { this.onCancel(); }} > 取消 </AnswerButton> <AnswerButton size="lager" onClick={() => { this.onConfirm(); }} > 编辑 </AnswerButton> <AnswerButton size="lager" onClick={() => { this.onConfirm(true); }} > 保存 </AnswerButton> </div> </div> </div> </div> </div> ); } }