page.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { Carousel, Tooltip } from 'antd';
  4. import { Link } from 'react-router-dom';
  5. import Fullscreen from 'react-fullscreen-crossbrowser';
  6. import './index.less';
  7. import Page from '@src/containers/Page';
  8. import { formatSeconds, formatPercent, formatDate, sortListWithOrder } from '@src/services/Tools';
  9. import Assets from '@src/components/Assets';
  10. import Navigation from '../../../components/Navigation';
  11. import Tabs from '../../../components/Tabs';
  12. import Icon from '../../../components/Icon';
  13. import Switch from '../../../components/Switch';
  14. import Select from '../../../components/Select';
  15. import { Button } from '../../../components/Button';
  16. import AnswerSelect from '../../../components/AnswerSelect';
  17. import AnswerList from '../../../components/AnswerList';
  18. import AnswerButton from '../../../components/AnswerButton';
  19. import AnswerTable from '../../../components/AnswerTable';
  20. import OtherAnswer from '../../../components/OtherAnswer';
  21. import { AskTarget } from '../../../../Constant';
  22. import { Question } from '../../../stores/question';
  23. import { My } from '../../../stores/my';
  24. import Sentence from '../process/sentence';
  25. export default class extends Page {
  26. initState() {
  27. return {
  28. step: 0,
  29. hideAnalysis: true,
  30. analysisTab: 'official',
  31. showAnswer: false,
  32. noteField: AskTarget[0].key,
  33. showIds: false,
  34. // question: {
  35. // content: {
  36. // typeset: 'one',
  37. // },
  38. // // questionType: 'awa',
  39. // answer: {
  40. // subject: [[{ text: 'like', uuid: 'hKyz' }]],
  41. // options: ['parallel'],
  42. // },
  43. // stem: "<p><span uuid='kBJe'>I</span> <span uuid='hKyz'>like</span> <span uuid='fQXh'>book</span></p>",
  44. // },
  45. // userQuestion: {
  46. // userAnswer: {
  47. // subject: [{ text: 'I', uuid: 'kBJe' }],
  48. // options: ['compare'],
  49. // },
  50. // no: 2,
  51. // },
  52. // paper: {
  53. // title: '长难句练习',
  54. // questionNumber: 20,
  55. // },
  56. // report: {
  57. // paperModule: 'sentence',
  58. // },
  59. };
  60. }
  61. initData() {
  62. const { id } = this.params;
  63. Question.getDetailById(id).then(userQuestion => {
  64. const { question, questionNos, paper, note, report, setting } = userQuestion;
  65. paper.paperModule = 'examination';
  66. let { questionNo } = userQuestion;
  67. if (!questionNo) ([questionNo] = questionNos);
  68. if (!question.answer) question.answer = { questions: [] };
  69. if (!question.answerDistributed) question.answerDistributed = { questions: [] };
  70. if (!userQuestion.userAnswer) userQuestion.userAnswer = { questions: [] };
  71. if ((report.setting || {}).disorder) {
  72. const { content } = question;
  73. // 还原做题顺序
  74. content.questions.forEach((q, i) => {
  75. q.select = sortListWithOrder(q.select, setting.questions[i]);
  76. });
  77. question.answer.questions.forEach((q, i) => {
  78. Object.keys(q).forEach((k) => {
  79. if (q[k]) q[k] = sortListWithOrder(q[k], setting.questions[i]);
  80. });
  81. });
  82. question.answerDistributed.questions.forEach((q, i) => {
  83. Object.keys(q).forEach((k) => {
  84. if (q[k]) q[k] = sortListWithOrder(q[k], setting.questions[i]);
  85. });
  86. });
  87. userQuestion.userAnswer.questions.forEach((q, i) => {
  88. Object.keys(q).forEach((k) => {
  89. if (q[k]) q[k] = sortListWithOrder(q[k], setting.questions[i]);
  90. });
  91. });
  92. }
  93. this.setState({ userQuestion, question, questionNo, note, paper, questionNos });
  94. });
  95. }
  96. prevQuestion() {
  97. const { userQuestion } = this.state;
  98. if (userQuestion.no === 1) return;
  99. Question.getDetailByNo(userQuestion.reportId, userQuestion.no - 1).then((r) => {
  100. linkTo(`/paper/question/${r.id}`);
  101. });
  102. }
  103. nextQuestion() {
  104. const { userQuestion } = this.state;
  105. if (userQuestion.questionNumber === userQuestion.no) return;
  106. Question.getDetailByNo(userQuestion.reportId, userQuestion.no + 1).then((r) => {
  107. linkTo(`/paper/question/${r.id}`);
  108. });
  109. }
  110. submitAsk() {
  111. const { question = {}, questionNo = {}, paper = {}, ask = {} } = this.state;
  112. if (ask.originContent === '' || ask.content === '' || ask.target === '') return;
  113. My.addQuestionAsk(paper.id, ask.target, question.questionModule, questionNo.id, ask.originContent, ask.content).then(() => {
  114. this.setState({ askModal: false, askOkModal: true });
  115. }).catch(err => {
  116. this.setState({ askError: err.message });
  117. });
  118. }
  119. submitFeedbackError() {
  120. const { feedback = {}, userQuestion = {}, questionNo = {} } = this.state;
  121. if (feedback.originContent === '' || feedback.content === '' || feedback.target === '') return;
  122. My.addFeedbackErrorQuestion(userQuestion.questionModule, questionNo.id, questionNo.title, feedback.target, feedback.originContent, feedback.content).then(() => {
  123. this.setState({ feedbackModal: false, feedbackOkModal: true });
  124. }).catch(err => {
  125. this.setState({ feedbackError: err.message });
  126. });
  127. }
  128. submitNote(close) {
  129. const { userQuestion = {}, questionNo = {}, note = {} } = this.state;
  130. My.updateQuestionNote(userQuestion.questionModule, questionNo.id, note).then(() => {
  131. if (close) this.setState({ noteModal: false });
  132. }).catch(err => {
  133. this.setState({ noteError: err.message });
  134. });
  135. }
  136. toggleFullscreen() {
  137. const { isFullscreenEnabled } = this.state;
  138. this.setState({ isFullscreenEnabled: !isFullscreenEnabled });
  139. }
  140. toggleCollect() {
  141. const { userQuestion = {}, questionNo = {} } = this.state;
  142. if (!userQuestion.collect) {
  143. My.addQuestionCollect(userQuestion.questionModule, questionNo.id).then(() => {
  144. userQuestion.collect = true;
  145. this.setState({ userQuestion });
  146. });
  147. } else {
  148. My.delQuestionCollect(userQuestion.questionModule, questionNo.id).then(() => {
  149. userQuestion.collect = false;
  150. this.setState({ userQuestion });
  151. });
  152. }
  153. }
  154. formatStem(text) {
  155. if (!text) return '';
  156. const { showAnswer, question = { content: {} }, userQuestion } = this.state;
  157. const { table = {}, questions = [] } = question.content;
  158. text = text.replace(/#select#/g, "<span class='#select#' />");
  159. text = text.replace(/#table#/g, "<span class='#table#' />");
  160. setTimeout(() => {
  161. const selectList = document.getElementsByClassName('#select#');
  162. const tableList = document.getElementsByClassName('#table#');
  163. for (let i = 0; i < selectList.length; i += 1) {
  164. if (!questions[i]) break;
  165. ReactDOM.render(
  166. <AnswerSelect
  167. list={questions[i].select}
  168. type={'single'}
  169. selected={(userQuestion.userAnswer || { questions: [] }).questions[i]}
  170. answer={(question.answer || { questions: [] }).questions[i]}
  171. fix
  172. show={showAnswer} />,
  173. selectList[i],
  174. );
  175. }
  176. if (table.row && table.col && table.header) {
  177. const columns = table.header.map((title, index) => {
  178. return { title, key: index };
  179. });
  180. for (let i = 0; i < tableList.length; i += 1) {
  181. ReactDOM.render(<AnswerTable list={columns} columns={columns} data={table.data} />, tableList[i]);
  182. }
  183. }
  184. }, 1);
  185. return text;
  186. }
  187. renderView() {
  188. return (
  189. <Fullscreen
  190. enabled={this.state.isFullscreenEnabled}
  191. onChange={isFullscreenEnabled => this.setState({ isFullscreenEnabled })}
  192. >
  193. {this.renderDetail()}
  194. </Fullscreen>
  195. );
  196. }
  197. renderDetail() {
  198. const { report = {} } = this.state;
  199. switch (report.paperModule) {
  200. case 'sentence':
  201. return <Sentence {...this.state} flow={this} scene='answer' mode='question' />;
  202. default:
  203. return <div className='base'>{this.renderBase()}</div>;
  204. }
  205. }
  206. renderHeader() {
  207. const { userQuestion = {}, questionNo = {}, paper = {}, report = {}, showIds, questionNos = [], question = {} } = this.state;
  208. return <div className={'layout-header'}>
  209. <div className="left">
  210. {paper.paperModule && paper.paperModule !== 'examination' && <div className="btn"><Button radius onClick={() => {
  211. linkTo(`/paper/report/${report.id}`);
  212. }}>返回练习报告</Button></div>}
  213. {paper.paperModule && paper.paperModule === 'examination' && <div className="btn"><Button radius onClick={() => {
  214. linkTo(`/paper/report/${report.id}`);
  215. }}>返回成绩单</Button></div>}
  216. <div className="no">No.{userQuestion.stageNo || userQuestion.no}</div>
  217. <div className="title"><Assets name='book' />{paper.title}</div>
  218. </div>
  219. <div className="center">
  220. <div className="menu-wrap">
  221. ID:{questionNo.title}
  222. {questionNos && questionNos.length > 0 && <Icon name="more" onClick={() => {
  223. this.setState({ showIds: true });
  224. }} />}
  225. {showIds && <div className='menu-content'>
  226. <p>题源汇总</p>
  227. {(questionNos || []).map((row) => <p>ID:{row.title}</p>)}
  228. </div>}
  229. </div>
  230. </div>
  231. <div className="right" hidden={question.questionType === 'awa'}>
  232. <span className="b" hidden={!userQuestion.id}>
  233. 用时:<span dangerouslySetInnerHTML={{ __html: formatSeconds(userQuestion.userTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span class="s">$1</span>$2') }} />
  234. {/* 用时:<span className="s">1</span>m<span className="s">39</span>s */}
  235. </span>
  236. <span className="b">
  237. 全站:<span dangerouslySetInnerHTML={{ __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span class="s">$1</span>$2') }} />
  238. {/* 全站:<span className="s">1</span>m<span className="s">39</span>s */}
  239. </span>
  240. <span className="b">
  241. <span className="s">{formatPercent(questionNo.totalCorrect, questionNo.totalNumber)}</span>%
  242. </span>
  243. <Icon name="question" />
  244. <Icon name="star" active={userQuestion.collect} onClick={() => this.toggleCollect()} />
  245. </div>
  246. </div>;
  247. }
  248. renderBase() {
  249. const { questionStatus, userQuestion = {}, paper = {}, showIds } = this.state;
  250. return <div className={`layout ${paper.paperModule}`} onClick={() => {
  251. if (showIds) this.setState({ showIds: false });
  252. }}>
  253. {this.renderHeader()}
  254. <div className="layout-body">{this.renderBody()}</div>
  255. <div className="layout-footer">
  256. <div className="left">
  257. <Tooltip overlayClassName='gray' placement='top' title='全屏'>
  258. <a>
  259. <Icon name={this.state.isFullscreenEnabled ? 'sceen-restore' : 'sceen-full'} onClick={() => this.toggleFullscreen()} />
  260. </a>
  261. </Tooltip>
  262. </div>
  263. <div className="center">
  264. <AnswerButton className="item" onClick={() => this.setState({ noteModal: true })}>笔记</AnswerButton>
  265. {questionStatus >= 0 && <AnswerButton className="item" onClick={() => {
  266. if (questionStatus > 0) {
  267. this.setState({ askModal: true });
  268. } else {
  269. this.setState({ askFailModal: true });
  270. }
  271. }}>提问</AnswerButton>}
  272. <AnswerButton className="item" onClick={() => this.setState({ feedbackModal: true })}>纠错</AnswerButton>
  273. </div>
  274. <div className="right">
  275. {userQuestion.no !== 1 && <Icon name="prev" onClick={() => this.prevQuestion()} />}
  276. {userQuestion.questionNumber !== userQuestion.no && <Icon name="next" onClick={() => this.nextQuestion()} />}
  277. </div>
  278. </div>
  279. {this.state.askModal && this.renderAsk()}
  280. {this.state.askOkModal && this.renderAskOk()}
  281. {this.state.askFailModal && this.renderAskFail()}
  282. {this.state.feedbackModal && this.renderFeedbackError()}
  283. {this.state.feedbackOkModal && this.renderFeedbackErrorOk()}
  284. {this.state.noteModal && this.renderNote()}
  285. </div>;
  286. }
  287. renderBody() {
  288. const { question = { content: {} } } = this.state;
  289. const { typeset = 'one' } = question.content;
  290. const { hideAnalysis } = this.state;
  291. const show = typeset === 'one' ? true : !hideAnalysis;
  292. return (
  293. <div className="layout-content">
  294. <div className='two'>
  295. {this.renderContent()}
  296. {question.questionType !== 'awa' && this.renderAnswer()}
  297. {question.questionType === 'awa' && this.renderAWA()}
  298. </div>
  299. {question.questionType !== 'awa' && this.renderAnalysis()}
  300. {typeset === 'two' && question.questionType !== 'awa' && (
  301. <div className="fixed-analysis" onClick={() => this.setState({ hideAnalysis: !hideAnalysis })}>
  302. {show ? '收起解析 >' : '查看解析 <'}
  303. </div>
  304. )}
  305. </div>
  306. );
  307. }
  308. renderAnalysis() {
  309. const { question = { content: {} }, analysisTab } = this.state;
  310. const { typeset = 'one' } = question.content;
  311. const { hideAnalysis } = this.state;
  312. const show = typeset === 'one' ? true : !hideAnalysis;
  313. return (
  314. <div className={`block block-analysis two-analysis ${show ? 'show' : ''}`}>
  315. <Tabs
  316. type="division"
  317. active={analysisTab}
  318. space={2}
  319. tabs={[
  320. { key: 'official', name: '官方解析' },
  321. { key: 'qx', name: '千行解析' },
  322. { key: 'association', name: '题源联想' },
  323. { key: 'qa', name: '相关回答' },
  324. ]}
  325. onChange={(key) => {
  326. this.setState({ analysisTab: key });
  327. }}
  328. />
  329. <div className="detail">
  330. {typeset === 'two' && this.renderAnswer()}
  331. {this.renderText()}
  332. </div>
  333. </div>
  334. );
  335. }
  336. renderText() {
  337. const { analysisTab, question = {}, userQuestion = {} } = this.state;
  338. const { asks = [], associations = [] } = userQuestion;
  339. let content;
  340. switch (analysisTab) {
  341. case 'official':
  342. content = <div className="detail-block text-block" dangerouslySetInnerHTML={{ __html: question.officialContent }} />;
  343. break;
  344. case 'qx':
  345. content = <div className="detail-block text-block" dangerouslySetInnerHTML={{ __html: question.qxContent }} />;
  346. break;
  347. case 'association':
  348. content = <div className="detail-block">
  349. <Carousel>
  350. {associations.map(association => {
  351. return <div className="text-block" dangerouslySetInnerHTML={{ __html: association.stem }} />;
  352. })}
  353. </Carousel>
  354. </div>;
  355. break;
  356. case 'qa':
  357. content = <div className="detail-block answer-block">
  358. {asks.map((ask, index) => {
  359. return <OtherAnswer key={index} data={ask} />;
  360. })}
  361. </div>;
  362. break;
  363. default:
  364. break;
  365. }
  366. return content;
  367. }
  368. renderAnswer() {
  369. const { question = { content: {} }, showAnswer, userQuestion = {} } = this.state;
  370. const { questions = [], type, typeset = 'one' } = question.content;
  371. return <div className="block block-answer">
  372. {typeset === 'two' ? <Switch checked={showAnswer} onChange={(value) => {
  373. this.setState({ showAnswer: value });
  374. }}>{showAnswer ? '显示答案' : '关闭答案'}</Switch> : ''}
  375. {questions.map((item, index) => {
  376. return (
  377. <div>
  378. <div className="text m-b-2">{item.description}</div>
  379. <AnswerList
  380. show={showAnswer}
  381. selected={(userQuestion.userAnswer || { questions: [] }).questions[index]}
  382. answer={(question.answer || { questions: [] }).questions[index]}
  383. distributed={(question.answerDistributed || { questions: [] }).questions[index]}
  384. list={item.select}
  385. type={type}
  386. first={item.first}
  387. second={item.second}
  388. direction={item.direction}
  389. />
  390. </div>
  391. );
  392. })}
  393. </div>;
  394. }
  395. renderContent() {
  396. const { question = { content: {} }, showAnswer, step } = this.state;
  397. const { typeset = 'one' } = question.content;
  398. const { steps = [] } = question.content;
  399. return (
  400. <div className="block block-content">
  401. {typeset === 'one' && question.questionType !== 'awa' ? <Switch checked={showAnswer} onChange={(value) => {
  402. this.setState({ showAnswer: value });
  403. }}>{showAnswer ? '显示答案' : '关闭答案'}</Switch> : ''}
  404. {question.questionType === 'awa' && <h2>Analytical Writing Assessment</h2>}
  405. {steps.length > 0 && <Navigation theme='detail' list={question.content.steps} active={step} onChange={(v) => this.setState({ step: v })} />}
  406. <div className="text" style={{ height: 2000 }} dangerouslySetInnerHTML={{ __html: this.formatStem(steps.length > 0 ? steps[step].stem : question.stem) }} />
  407. </div>
  408. );
  409. }
  410. renderAWA() {
  411. const { showAnswer, userQuestion = { detail: {}, userAnswer: {} } } = this.state;
  412. return <div className="block block-awa">
  413. <Switch checked={showAnswer} onChange={(value) => {
  414. this.setState({ showAnswer: value });
  415. }}>{showAnswer ? '显示答案' : '关闭答案'}</Switch>
  416. <div className="body">
  417. <h2>Your Response</h2>
  418. {showAnswer && <div className='detail'>
  419. <div className='info'>
  420. <span className="b">
  421. 用时:<span dangerouslySetInnerHTML={{ __html: formatSeconds(userQuestion.userTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span class="s">$1</span>$2') }} />
  422. {/* 用时:<span className="s">1</span>m<span className="s">39</span>s */}
  423. </span>
  424. <span className="b">
  425. 单词数:<span className="s">{Number((userQuestion.detail || {}).words || 0)}</span>词
  426. </span>
  427. </div>
  428. <div className='content-awa' dangerouslySetInnerHTML={{ __html: userQuestion.userAnswer.awa || '' }} />
  429. </div>}
  430. {!showAnswer && <div className='show-awa'>选择「显示答案」查看自己的作文</div>}
  431. </div>
  432. </div>;
  433. }
  434. renderAsk() {
  435. const { ask = {} } = this.state;
  436. return (
  437. <div className="modal ask">
  438. <div className="mask" />
  439. <div className="body">
  440. <div className="title">提问</div>
  441. <div className="desc">
  442. <div className="select-inline">我想对<Select excludeSelf size="small" theme="white" value={ask.target} list={AskTarget} onChange={(item) => {
  443. ask.target = item.value;
  444. this.setState({ ask });
  445. }} />进行提问</div>
  446. <div className="label">有疑问的具体内容是:</div>
  447. <textarea className="textarea" value={ask.originContent} placeholder="请复制粘贴有疑问的内容。" onChange={(e) => {
  448. ask.originContent = e.target.value;
  449. this.setState({ ask });
  450. }} />
  451. <div className="label">针对以上内容的问题是:</div>
  452. <textarea className="textarea" value={ask.content} placeholder="提问频率高的问题会被优先回答哦。" onChange={(e) => {
  453. ask.content = e.target.value;
  454. this.setState({ ask });
  455. }} />
  456. </div>
  457. <div className="bottom">
  458. <AnswerButton theme="cancel" size="lager" onClick={() => this.setState({ askModal: false })}>
  459. 取消
  460. </AnswerButton>
  461. <AnswerButton size="lager" onClick={() => this.submitAsk()}>提交</AnswerButton>
  462. </div>
  463. </div>
  464. </div>
  465. );
  466. }
  467. renderAskOk() {
  468. return (
  469. <div className="modal ask-ok">
  470. <div className="mask" />
  471. <div className="body">
  472. <div className="title">提问</div>
  473. <div className="content">
  474. <div className="left">
  475. <div className="text">已提交成功!</div>
  476. <div className="text">关注公众号,老师回答后会立即收到通知。</div>
  477. <div className="text">我们也会通过站内信的方式通知你。</div>
  478. <div className="small">成为学员享受极速答疑特权。<Link>了解更多</Link></div>
  479. </div>
  480. <div className="right">
  481. <div className="text">扫码关注公众号</div>
  482. <div className="text">千行GMAT</div>
  483. </div>
  484. </div>
  485. <div className="confirm">
  486. <AnswerButton size="lager" theme="confirm" onClick={() => {
  487. this.setState({ askOkModal: false });
  488. }}>
  489. 好的,知道了
  490. </AnswerButton>
  491. </div>
  492. </div>
  493. </div>
  494. );
  495. }
  496. renderAskFail() {
  497. return (
  498. <div className="modal ask-ok">
  499. <div className="mask" />
  500. <div className="body">
  501. <div className="title">提问</div>
  502. <div className="content">
  503. <div className="left">
  504. <div className="text">提问功能正在维护中。</div>
  505. <div className="text">可先查阅“相关问答” 或 成为学员享受极速 答疑特权。</div>
  506. <Link to="/">了解更多></Link>
  507. </div>
  508. <div className="right">
  509. <div className="text">扫码关注公众号</div>
  510. <div className="text">千行GMAT</div>
  511. </div>
  512. </div>
  513. <div className="confirm">
  514. <AnswerButton size="lager" theme="confirm" onClick={() => {
  515. this.setState({ askFailModal: false });
  516. }}>
  517. 好的,知道了
  518. </AnswerButton>
  519. </div>
  520. </div>
  521. </div>
  522. );
  523. }
  524. renderFeedbackError() {
  525. const { feedback = {} } = this.state;
  526. return (
  527. <div className="modal error">
  528. <div className="mask" />
  529. <div className="body">
  530. <div className="title">纠错</div>
  531. <div className="desc">
  532. <div className="select-inline">我想对<Select excludeSelf size="small" theme="white" value={feedback.target} list={AskTarget} onChange={(item) => {
  533. feedback.target = item.value;
  534. this.setState({ feedback });
  535. }} />进行提问</div>
  536. <div className="label">错误内容是:</div>
  537. <textarea className="textarea" value={feedback.originContent} placeholder="你可以适当扩大复制范围以使我们准确定位,感谢。" />
  538. <div className="label">应该改为:</div>
  539. <textarea className="textarea" placeholder="只需提供正确内容即可" />
  540. </div>
  541. <div className="bottom">
  542. <AnswerButton theme="cancel" size="lager" onClick={() => {
  543. this.setState({ feedbackModal: false });
  544. }}>
  545. 取消
  546. </AnswerButton>
  547. <AnswerButton size="lager" onClick={() => {
  548. this.submitFeedbackError();
  549. }}>提交</AnswerButton>
  550. </div>
  551. </div>
  552. </div>
  553. );
  554. }
  555. renderFeedbackErrorOk() {
  556. return (
  557. <div className="modal error-ok">
  558. <div className="mask" />
  559. <div className="body">
  560. <div className="title">纠错</div>
  561. <div className="content">
  562. <div className="left">
  563. <div className="text"><Assets name='right' svg />已提交成功!</div>
  564. <div className="text">感谢您的耐心反馈,我们会尽快核实并以站内信的方式告知结果。</div>
  565. <div className="text">您也可以关注公众号及时获取结果。</div>
  566. </div>
  567. <div className="right">
  568. <div className="text">扫码关注公众号</div>
  569. <div className="text">千行GMAT</div>
  570. </div>
  571. </div>
  572. <div className="confirm">
  573. <AnswerButton size="lager" theme="confirm" onClick={() => {
  574. this.setState({ feedbackOkModal: false });
  575. }}>
  576. 好的,知道了
  577. </AnswerButton>
  578. </div>
  579. </div>
  580. </div>
  581. );
  582. }
  583. renderNote() {
  584. const { noteField, note = {} } = this.state;
  585. return (
  586. <div className="modal note">
  587. <div className="mask" />
  588. <div className="body">
  589. <div className="title">笔记</div>
  590. <div className="content">
  591. <div className="tabs">
  592. {AskTarget.map(item => {
  593. return (
  594. <div className={`tab ${noteField === item.key ? 'active' : ''}`} onClick={() => {
  595. this.setState({ noteField: item.key });
  596. }}>
  597. <div className="text">{item.label}</div>
  598. <div className="date">{note[`${item.key}Time`] ? formatDate(note[`${item.key}Time`]) : ''}</div>
  599. </div>
  600. );
  601. })}
  602. </div>
  603. <div className="input">
  604. <textarea className="textarea" value={note[`${noteField}Content`] || ''} placeholder="记下笔记,方便以后复习" onChange={(e) => {
  605. note[`${noteField}Time`] = new Date();
  606. note[`${noteField}Content`] = e.target.value;
  607. this.setState({ note });
  608. }} />
  609. <div className="bottom">
  610. <AnswerButton theme="cancel" size="lager" onClick={() => {
  611. this.setState({ noteModal: false });
  612. }}>
  613. 取消
  614. </AnswerButton>
  615. <AnswerButton size="lager" onClick={() => {
  616. this.submitNote();
  617. }}>编辑</AnswerButton>
  618. <AnswerButton size="lager" onClick={() => {
  619. this.submitNote(true);
  620. }}>保存</AnswerButton>
  621. </div>
  622. </div>
  623. </div>
  624. </div>
  625. </div>
  626. );
  627. }
  628. }