page.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. import React, { Component } from 'react';
  2. import './index.less';
  3. import { Checkbox } from 'antd';
  4. import Page from '@src/containers/Page';
  5. import Modal from '../../../components/Modal';
  6. import HardInput from '../../../components/HardInput';
  7. import AnswerCheckbox from '../../../components/AnswerCheckbox';
  8. import { formatDate, getMap, formatPercent, formatSeconds } from '../../../../../src/services/Tools';
  9. import { My } from '../../../stores/my';
  10. import { User } from '../../../stores/user';
  11. import { SentenceOption } from '../../../../Constant';
  12. const ExportType = [
  13. { label: '收藏', value: 'question_collect' },
  14. { label: '错题', value: 'question_error' },
  15. { label: '笔记', value: 'note_question' },
  16. { label: '笔记', value: 'note_course' },
  17. ];
  18. const ExportTypeMap = getMap(ExportType, 'value', 'label');
  19. const AnswerIndex = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'];
  20. export default class extends Page {
  21. initState() {
  22. const { info } = this.props.user;
  23. return {
  24. showTip: !info.exportTips,
  25. nextTips: true,
  26. };
  27. }
  28. initData() {
  29. const { id } = this.params;
  30. My.exportDetail(id)
  31. .then(result => {
  32. this.setState({ data: result });
  33. });
  34. }
  35. closeTips() {
  36. this.setState({ showTip: false });
  37. const { nextTips } = this.state;
  38. if (!nextTips) return;
  39. My.exportTips()
  40. .then(() => {
  41. const { info } = this.props.user;
  42. info.exportTips = 1;
  43. User.infoHandle(info);
  44. });
  45. }
  46. renderView() {
  47. const { data = {}, showTip, nextTips } = this.state;
  48. return (
  49. <div>
  50. {this.renderHead()}
  51. {data.type !== 'note_course' && this.renderQuestion()}
  52. {data.type === 'note_course' && this.renderNote()}
  53. <Modal
  54. show={showTip}
  55. title="导出方法"
  56. onConfirm={() => this.closeTips()}
  57. confirmText="好的,知道了"
  58. btnAlign="center"
  59. >
  60. <div className="t-2 t-s-18">鼠标右键点击打印后,可直接保存为PDF或打印。</div>
  61. <div className="t-2 t-s-14"><Checkbox checked={nextTips} onClick={() => this.setState({ nextTips: !nextTips })} />下次进入时不再提醒。</div>
  62. </Modal>
  63. </div>
  64. );
  65. }
  66. renderHead() {
  67. const { data = {} } = this.state;
  68. const { content = {} } = data;
  69. const { info } = this.props.user;
  70. return (
  71. <div className="head-layout">
  72. <div className="content p-r">
  73. <div className="t-1 t-s-30">千行GMAR</div>
  74. <div className="t-1 t-s-18">
  75. <span>{info.nickname}</span> <span>ID {info.id}</span>
  76. </div>
  77. <div className="t-2 t-s-12">* 请勿外传或商用!</div>
  78. <div style={{ right: 0, top: 20 }} className="p-a t-r">
  79. <div className="t-2">第{data.no || 0}次导出{ExportTypeMap[data.type]}</div>
  80. <div className="t-2">本次导出 {(content.list || []).length} 道 </div>
  81. <div className="t-2">{formatDate(data.createTime, 'YYYY-MM-DD HH:mm:ss')}</div>
  82. </div>
  83. </div>
  84. </div>
  85. );
  86. }
  87. renderQuestion() {
  88. const { data } = this.state;
  89. const { content = {} } = data;
  90. const { list = [] } = content;
  91. return (
  92. <div className="detail-layout">
  93. <div className="content">
  94. {list.map(item => {
  95. return [this.renderTotal(item),
  96. item.question.questionType === 'sentence' ? <SentenceDetail data={item} /> : <BaseDetail data={item} />];
  97. })}
  98. </div>
  99. </div>
  100. );
  101. }
  102. renderTotal(item) {
  103. const { questionNo = {}, userTime, userPaper } = item;
  104. return (
  105. <div className="total-block p-l-2">
  106. <span className="m-l-1 t-1 t-s-20 f-w-b m-r-2"> {questionNo.title}</span>
  107. {userPaper && <span className="t-1 t-s-20 f-w-b m-r-2">{userPaper.title}</span>}
  108. <span className="t-1">ID:{questionNo.title}</span>
  109. <div className="f-r m-r-1">
  110. {userTime && <span className="t-1 m-r-2">
  111. 用时:
  112. <span
  113. dangerouslySetInnerHTML={{
  114. __html: formatSeconds(userTime).replace(
  115. /([0-9]+)(m|min|h|hour|s)/g,
  116. '<span class="t-4">$1</span>$2',
  117. ),
  118. }}
  119. />
  120. </span>}
  121. <span className="t-1 m-r-2">
  122. 全站:
  123. <span
  124. dangerouslySetInnerHTML={{
  125. __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(
  126. /([0-9]+)(m|min|h|hour|s)/g,
  127. '<span class="t-4">$1</span>$2',
  128. ),
  129. }}
  130. />
  131. </span>
  132. <span className="t-1">
  133. <span className="t-4">{formatPercent(item.questionNo.totalCorrect, item.questionNo.totalNumber)}</span>%
  134. </span>
  135. </div>
  136. </div>
  137. );
  138. }
  139. renderNote() {
  140. const { data } = this.state;
  141. const { content = {} } = data;
  142. const { list = [] } = content;
  143. return (
  144. <div className="detail-layout">
  145. <div className="content">
  146. {list.map(item => {
  147. return <NoteDetail data={item} />;
  148. })}
  149. </div>
  150. </div>
  151. );
  152. }
  153. }
  154. class BaseDetail extends Component {
  155. render() {
  156. return (
  157. <div className="detail-item">
  158. {this.renderQuestion()}
  159. {this.renderOfficial()}
  160. {this.renderQx()}
  161. {this.renderConnect()}
  162. {this.renderAsk()}
  163. </div>
  164. );
  165. }
  166. renderQuestion() {
  167. const { data = {} } = this.props;
  168. const { question = {} } = data;
  169. if (!question.stem) return null;
  170. return [
  171. <div className="detail-item-block">
  172. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.stem }} />
  173. {this.renderSelect(question.content.question[0].select)}
  174. </div>,
  175. this.renderAnswer(),
  176. ];
  177. }
  178. renderAnswer() {
  179. const { data = {} } = this.props;
  180. const { question = {}, note = {}, userAnswer = {} } = data;
  181. const { answer } = question;
  182. return (
  183. <div className="detail-item-block">
  184. <div className="title-item">答案</div>
  185. <div className="t-1 t-s-16 m-b-2">
  186. {userAnswer && <span className="m-r-2">我的答案 {AnswerIndex[answer.questions[0].single.indexOf(true)]}</span>}
  187. <span>正确答案 {AnswerIndex[answer.questions[0].single.indexOf(true)]}</span>
  188. </div>
  189. {this.renderNote('题目', note.questionContent)}
  190. </div>
  191. );
  192. }
  193. renderOfficial() {
  194. const { data = {} } = this.props;
  195. const { question = {}, note = {} } = data;
  196. if (!question.officialContent) return null;
  197. return (
  198. <div className="detail-item-block">
  199. <div className="title-item">官方解析</div>
  200. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.officialContent }} />
  201. {this.renderNote('官方解析', note.officialContent)}
  202. </div>
  203. );
  204. }
  205. renderQx() {
  206. const { data = {} } = this.props;
  207. const { question = {}, note = {} } = data;
  208. if (!question.qxContent) return null;
  209. return (
  210. <div className="detail-item-block">
  211. <div className="title-item">千行解析</div>
  212. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.qxContent }} />
  213. {this.renderNote('千行解析', note.qxContent)}
  214. </div>
  215. );
  216. }
  217. renderConnect() {
  218. const { data = {} } = this.props;
  219. const { associations = [], note = {} } = data;
  220. if (!associations || associations.length === 0) return null;
  221. return (
  222. <div className="detail-item-block">
  223. <div className="title-item">题源联想</div>
  224. {associations.map((item, index) => {
  225. return (
  226. <div className="m-b-2">
  227. <div className="t-1 t-s-16 m-b-1">
  228. <span className="t-4 t-s-14 m-r-5">例题 {index + 1}</span><div dangerouslySetInnerHTML={{ __html: item.stem }} />
  229. </div>
  230. {this.renderSelect(item.content.questions[0].select)}
  231. </div>
  232. );
  233. })}
  234. {this.renderNote('题源联想', note.associationContent)}
  235. </div>
  236. );
  237. }
  238. renderAsk() {
  239. const { data = {} } = this.props;
  240. const { asks = [], note = {} } = data;
  241. if (!asks || asks.length === 0) return null;
  242. return (
  243. <div className="detail-item-block">
  244. <div className="title-item">相关问答</div>
  245. {asks.map((item) => {
  246. return (
  247. <div className="m-b-1 b-b p-b-1">
  248. <div className="ask-tag">提问</div>
  249. <div className="t-1 t-s-16 m-b-1" dangerouslySetInnerHTML={{ __html: item.content }} />
  250. <div className="ask-tag">回答</div>
  251. <div className="t-1 t-s-16 m-b-1" dangerouslySetInnerHTML={{ __html: item.answer }} />
  252. </div>
  253. );
  254. })}
  255. {this.renderNote('相关问答', note.qaContent)}
  256. </div>
  257. );
  258. }
  259. renderSelect(list) {
  260. return (
  261. <div className="select-item">
  262. {list.map((item) => {
  263. return (
  264. <div className="p-r m-b-2">
  265. <div className="select-icon p-a" />
  266. <div className="p-l-2 t-1 t-s-16">{item}</div>
  267. </div>
  268. );
  269. })}
  270. </div>
  271. );
  272. }
  273. renderNote(title, content) {
  274. if (!content) return null;
  275. return (
  276. <div className="note-item">
  277. <div className="t t-1 m-b-1">我的笔记-{title}</div>
  278. <div className="t-1 t-s-16">{content}</div>
  279. </div>
  280. );
  281. }
  282. }
  283. class SentenceDetail extends Component {
  284. render() {
  285. return (
  286. <div className="detail-item">
  287. {this.renderQuestion()}
  288. {this.renderDetail()}
  289. {this.renderChinese()}
  290. </div>
  291. );
  292. }
  293. renderQuestion() {
  294. const { data = {} } = this.props;
  295. const { question = {}, userAnswer = {} } = data;
  296. const { answer = {} } = question;
  297. return (
  298. <div className="detail-item-block">
  299. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.stem }} />
  300. <div className="hard-body m-b-2">
  301. <div className="hard-row">
  302. <div className="label">主语</div>
  303. <div className="input">
  304. <HardInput show list={userAnswer.subject || []} answer={answer.subject} />
  305. </div>
  306. </div>
  307. <div className="hard-row">
  308. <div className="label">谓语</div>
  309. <div className="input">
  310. <HardInput show list={userAnswer.predicate || []} answer={answer.predicate} />
  311. </div>
  312. </div>
  313. <div className="hard-row">
  314. <div className="label">宾语</div>
  315. <div className="input">
  316. <HardInput show list={userAnswer.object || []} answer={answer.object} />
  317. </div>
  318. </div>
  319. </div>
  320. <div className="hard-select">
  321. <div className="t-2 t-s-12 m-b-2">本句存在以下哪种逻辑关系?(可多选)</div>
  322. <AnswerCheckbox
  323. show
  324. list={SentenceOption}
  325. selected={userAnswer.options}
  326. answer={answer.options}
  327. />
  328. </div>
  329. </div>
  330. );
  331. }
  332. renderDetail() {
  333. const { data = {} } = this.props;
  334. const { question = {} } = data;
  335. return (
  336. <div className="detail-item-block">
  337. <div className="title-item">解析详情</div>
  338. <div className="t-1 t-s-16" dangerouslySetInnerHTML={{ __html: question.qxContent }} />
  339. </div>
  340. );
  341. }
  342. renderChinese() {
  343. const { data = {} } = this.props;
  344. const { question = {} } = data;
  345. return (
  346. <div className="detail-item-block">
  347. <div className="title-item">中文语意</div>
  348. <div className="t-1 t-s-16" dangerouslySetInnerHTML={{ __html: question.chineseContent }} />
  349. </div>
  350. );
  351. }
  352. }
  353. class NoteDetail extends Component {
  354. render() {
  355. const { data } = this.props;
  356. return (
  357. <div className="detail-item">
  358. <div className="title-item">
  359. 课时{data.courseNo.no} {data.courseNo.title}<div className="f-r t-6 t-s-12 t-r f-w-d">{formatDate(data.updateTime, 'YYYY-MM-DD HH:mm:ss')}</div>
  360. </div>
  361. <div className="t-1 t-s-16">{data.content}</div>
  362. </div>
  363. );
  364. }
  365. }