page.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  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), item.question.questionType === 'sentence' ? <SentenceDetail data={item} /> : <BaseDetail data={item} />];
  96. })}
  97. </div>
  98. </div>
  99. );
  100. }
  101. renderTotal(item) {
  102. const { questionNo = {}, userTime, userPaper } = item;
  103. return (
  104. <div className="total-block p-l-2">
  105. <span className="m-l-1 t-1 t-s-20 f-w-b m-r-2"> {questionNo.title}</span>
  106. {userPaper && <span className="t-1 t-s-20 f-w-b m-r-2">{userPaper.title}</span>}
  107. <span className="t-1">ID:{questionNo.title}</span>
  108. <div className="f-r m-r-1">
  109. {userTime && <span className="t-1 m-r-2">
  110. 用时:
  111. <span
  112. dangerouslySetInnerHTML={{
  113. __html: formatSeconds(userTime).replace(
  114. /([0-9]+)(min|m|hour|h|s)/g,
  115. '<span class="t-4">$1</span>$2',
  116. ),
  117. }}
  118. />
  119. </span>}
  120. <span className="t-1 m-r-2">
  121. 全站:
  122. <span
  123. dangerouslySetInnerHTML={{
  124. __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(
  125. /([0-9]+)(min|m|hour|h|s)/g,
  126. '<span class="t-4">$1</span>$2',
  127. ),
  128. }}
  129. />
  130. </span>
  131. <span className="t-1">
  132. <span className="t-4">{formatPercent(item.questionNo.totalCorrect, item.questionNo.totalNumber)}</span>%
  133. </span>
  134. </div>
  135. </div>
  136. );
  137. }
  138. renderNote() {
  139. const { data } = this.state;
  140. const { content = {} } = data;
  141. const { list = [] } = content;
  142. return (
  143. <div className="detail-layout">
  144. <div className="content">
  145. {list.map(item => {
  146. return <NoteDetail data={item} />;
  147. })}
  148. </div>
  149. </div>
  150. );
  151. }
  152. }
  153. class BaseDetail extends Component {
  154. render() {
  155. return (
  156. <div className="detail-item">
  157. {this.renderQuestion()}
  158. {this.renderOfficial()}
  159. {this.renderQx()}
  160. {this.renderConnect()}
  161. {this.renderAsk()}
  162. </div>
  163. );
  164. }
  165. renderQuestion() {
  166. const { data = {} } = this.props;
  167. const { question = {} } = data;
  168. if (!question.stem) return null;
  169. return [
  170. <div className="detail-item-block">
  171. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.stem }} />
  172. {this.renderSelect(question.content.questions[0].select)}
  173. </div>,
  174. this.renderAnswer(),
  175. ];
  176. }
  177. renderAnswer() {
  178. const { data = {} } = this.props;
  179. const { question = {}, note = {}, userAnswer = {} } = data;
  180. const { answer } = question;
  181. return (
  182. <div className="detail-item-block">
  183. <div className="title-item">答案</div>
  184. <div className="t-1 t-s-16 m-b-2">
  185. {userAnswer && <span className="m-r-2">我的答案 {AnswerIndex[answer.questions[0].single.indexOf(true)]}</span>}
  186. <span>正确答案 {AnswerIndex[answer.questions[0].single.indexOf(true)]}</span>
  187. </div>
  188. {this.renderNote('题目', note.questionContent)}
  189. </div>
  190. );
  191. }
  192. renderOfficial() {
  193. const { data = {} } = this.props;
  194. const { question = {}, note = {} } = data;
  195. if (!question.officialContent) return null;
  196. return (
  197. <div className="detail-item-block">
  198. <div className="title-item">官方解析</div>
  199. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.officialContent }} />
  200. {this.renderNote('官方解析', note.officialContent)}
  201. </div>
  202. );
  203. }
  204. renderQx() {
  205. const { data = {} } = this.props;
  206. const { question = {}, note = {} } = data;
  207. if (!question.qxContent) return null;
  208. return (
  209. <div className="detail-item-block">
  210. <div className="title-item">千行解析</div>
  211. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.qxContent }} />
  212. {this.renderNote('千行解析', note.qxContent)}
  213. </div>
  214. );
  215. }
  216. renderConnect() {
  217. const { data = {} } = this.props;
  218. const { associations = [], note = {} } = data;
  219. if (!associations || associations.length === 0) return null;
  220. return (
  221. <div className="detail-item-block">
  222. <div className="title-item">题源联想</div>
  223. {associations.filter(row => row).map((item, index) => {
  224. return (
  225. <div className="m-b-2">
  226. <div className="t-1 t-s-16 m-b-1">
  227. <span className="t-4 t-s-14 m-r-5">例题 {index + 1}</span><div dangerouslySetInnerHTML={{ __html: item.stem }} />
  228. </div>
  229. {this.renderSelect(item.content.questions[0].select)}
  230. </div>
  231. );
  232. })}
  233. {this.renderNote('题源联想', note.associationContent)}
  234. </div>
  235. );
  236. }
  237. renderAsk() {
  238. const { data = {} } = this.props;
  239. const { asks = [], note = {} } = data;
  240. if (!asks || asks.length === 0) return null;
  241. return (
  242. <div className="detail-item-block">
  243. <div className="title-item">相关问答</div>
  244. {asks.map((item) => {
  245. return (
  246. <div className="m-b-1 b-b p-b-1">
  247. <div className="ask-tag">提问</div>
  248. <div className="t-1 t-s-16 m-b-1" dangerouslySetInnerHTML={{ __html: item.content }} />
  249. <div className="ask-tag">回答</div>
  250. <div className="t-1 t-s-16 m-b-1" dangerouslySetInnerHTML={{ __html: item.answer }} />
  251. </div>
  252. );
  253. })}
  254. {this.renderNote('相关问答', note.qaContent)}
  255. </div>
  256. );
  257. }
  258. renderSelect(list) {
  259. return (
  260. <div className="select-item">
  261. {list.map((item) => {
  262. return (
  263. <div className="p-r m-b-2">
  264. <div className="select-icon p-a" />
  265. <div className="p-l-2 t-1 t-s-16">{item}</div>
  266. </div>
  267. );
  268. })}
  269. </div>
  270. );
  271. }
  272. renderNote(title, content) {
  273. if (!content) return null;
  274. return (
  275. <div className="note-item">
  276. <div className="t t-1 m-b-1">我的笔记-{title}</div>
  277. <div className="t-1 t-s-16">{content}</div>
  278. </div>
  279. );
  280. }
  281. }
  282. class SentenceDetail extends Component {
  283. render() {
  284. return (
  285. <div className="detail-item">
  286. {this.renderQuestion()}
  287. {this.renderDetail()}
  288. {this.renderChinese()}
  289. </div>
  290. );
  291. }
  292. renderQuestion() {
  293. const { data = {} } = this.props;
  294. const { question = {}, userAnswer = {} } = data;
  295. const { answer = {} } = question;
  296. return (
  297. <div className="detail-item-block">
  298. <div className="t-1 t-s-16 m-b-2" dangerouslySetInnerHTML={{ __html: question.stem }} />
  299. <div className="hard-body m-b-2">
  300. <div className="hard-row">
  301. <div className="label">主语</div>
  302. <div className="input">
  303. <HardInput show list={userAnswer.subject || []} answer={answer.subject} />
  304. </div>
  305. </div>
  306. <div className="hard-row">
  307. <div className="label">谓语</div>
  308. <div className="input">
  309. <HardInput show list={userAnswer.predicate || []} answer={answer.predicate} />
  310. </div>
  311. </div>
  312. <div className="hard-row">
  313. <div className="label">宾语</div>
  314. <div className="input">
  315. <HardInput show list={userAnswer.object || []} answer={answer.object} />
  316. </div>
  317. </div>
  318. </div>
  319. <div className="hard-select">
  320. <div className="t-2 t-s-12 m-b-2">本句存在以下哪种逻辑关系?(可多选)</div>
  321. <AnswerCheckbox
  322. show
  323. list={SentenceOption}
  324. selected={userAnswer.options}
  325. answer={answer.options}
  326. />
  327. </div>
  328. </div>
  329. );
  330. }
  331. renderDetail() {
  332. const { data = {} } = this.props;
  333. const { question = {} } = data;
  334. return (
  335. <div className="detail-item-block">
  336. <div className="title-item">解析详情</div>
  337. <div className="t-1 t-s-16" dangerouslySetInnerHTML={{ __html: question.qxContent }} />
  338. </div>
  339. );
  340. }
  341. renderChinese() {
  342. const { data = {} } = this.props;
  343. const { question = {} } = data;
  344. return (
  345. <div className="detail-item-block">
  346. <div className="title-item">中文语意</div>
  347. <div className="t-1 t-s-16" dangerouslySetInnerHTML={{ __html: question.chineseContent }} />
  348. </div>
  349. );
  350. }
  351. }
  352. class NoteDetail extends Component {
  353. render() {
  354. const { data } = this.props;
  355. return (
  356. <div className="detail-item">
  357. <div className="title-item">
  358. 课时{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>
  359. </div>
  360. <div className="t-1 t-s-16">{data.content}</div>
  361. </div>
  362. );
  363. }
  364. }