page.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. import React from 'react';
  2. import { Breadcrumb, Tooltip, Switch } from 'antd';
  3. import './index.less';
  4. import Page from '@src/containers/Page';
  5. import { asyncConfirm, asyncSMessage } from '@src/services/AsyncTools';
  6. import { formatPercent, formatDate } from '@src/services/Tools';
  7. import { RestartConfirmModal } from '../../../components/OtherModal';
  8. import ListTable from '../../../components/ListTable';
  9. import ProgressText from '../../../components/ProgressText';
  10. import IconButton from '../../../components/IconButton';
  11. import Button from '../../../components/Button';
  12. import { Main } from '../../../stores/main';
  13. import { Question } from '../../../stores/question';
  14. export default class extends Page {
  15. initState() {
  16. this.qxCatColumns = [
  17. {
  18. title: '模考',
  19. width: 210,
  20. align: 'left',
  21. render: record => {
  22. let progress = 0;
  23. if (record.report) {
  24. progress = formatPercent(record.report.userNumber, record.report.questionNumber);
  25. }
  26. return [
  27. <div className="table-row" style={{ paddingRight: 40 }}>
  28. <div className="night f-s-16">
  29. {record.title}
  30. {record.paper && record.paper.paperNo > 0 ? String.fromCharCode(64 + record.paper.paperNo) : ''}
  31. </div>
  32. <div>
  33. <ProgressText progress={progress} size="small" />
  34. </div>
  35. </div>,
  36. this.state.showPrev && record.prevReport && (
  37. <div className="table-row prev t-3">
  38. <div className="night f-s-16">
  39. {record.title}
  40. {record.prevPaper && record.prevPaper.paperNo > 0
  41. ? String.fromCharCode(64 + record.prevPaper.paperNo)
  42. : ''}
  43. </div>
  44. </div>
  45. ),
  46. ];
  47. },
  48. },
  49. {
  50. title: 'Total',
  51. width: 110,
  52. align: 'left',
  53. render: record => {
  54. return [
  55. <div className="table-row">
  56. <div className="night f-s-16 f-w-b">
  57. {record.report ? `${record.report.score.totalScore}分${record.report.score.totalRank}th` : '-分-th'}
  58. </div>
  59. <div className="f-s-12">全站: {Math.round(record.totalScore / record.totalTimes)}分</div>
  60. </div>,
  61. this.state.showPrev && record.prevReport && (
  62. <div className="table-row prev t-3">
  63. <div className="night f-s-16 f-w-b">
  64. {record.prevReport.score.totalScore}分{record.prevReport.score.totalRank}th
  65. </div>
  66. <div className="f-s-12">全站: {Math.round(record.secondTotalScore / record.secondTotalTimes)}分</div>
  67. </div>
  68. ),
  69. ];
  70. },
  71. },
  72. {
  73. title: 'Verbal',
  74. width: 110,
  75. align: 'left',
  76. render: record => {
  77. return [
  78. <div className="table-row">
  79. <div className="night f-s-16 f-w-b">
  80. {record.report ? `${record.report.score.verbalScore}分${record.report.score.verbalRank}th` : '-分-th'}
  81. </div>
  82. <div className="f-s-12">全站: {Math.round(record.verbalScore / record.totalTimes)}分</div>
  83. </div>,
  84. this.state.showPrev && record.prevReport && (
  85. <div className="table-row prev t-3">
  86. <div className="night f-s-16 f-w-b">
  87. {record.prevReport.score.verbalScore}分{record.prevReport.score.verbalRank}th
  88. </div>
  89. <div className="f-s-12">全站: {Math.round(record.secondVerbalScore / record.secondTotalTimes)}分</div>
  90. </div>
  91. ),
  92. ];
  93. },
  94. },
  95. {
  96. title: 'Quant',
  97. width: 110,
  98. align: 'left',
  99. render: record => {
  100. return [<div className="table-row">
  101. <div className="night f-s-16 f-w-b">
  102. {record.report ? `${record.report.score.quantScore}分${record.report.score.quantRank}th` : '-分-th'}
  103. </div>
  104. <div className="f-s-12">全站: {Math.round(record.quantScore / record.totalTimes)}分</div>
  105. </div>,
  106. this.state.showPrev && record.prevReport && (
  107. <div className="table-row prev t-3">
  108. <div className="night f-s-16 f-w-b">
  109. {record.prevReport.score.quantScore}分{record.prevReport.score.quantRank}th
  110. </div>
  111. <div className="f-s-12">全站: {Math.round(record.secondQuantScore / record.secondTotalTimes)}分</div>
  112. </div>
  113. ),
  114. ];
  115. },
  116. },
  117. {
  118. title: 'IR',
  119. width: 110,
  120. align: 'left',
  121. render: record => {
  122. return [<div className="table-row">
  123. <div className="night f-s-16 f-w-b">
  124. {record.report ? `${record.report.score.irScore}分${record.report.score.irRank}th` : '-分-th'}
  125. </div>
  126. <div className="f-s-12">全站: {Math.round(record.irScore / record.totalTimes)}分</div>
  127. </div>,
  128. this.state.showPrev && record.prevReport && (
  129. <div className="table-row prev t-3">
  130. <div className="night f-s-16 f-w-b">
  131. {record.prevReport.score.irScore}分{record.prevReport.score.irRank}th
  132. </div>
  133. <div className="f-s-12">全站: {Math.round(record.secondIrScore / record.secondTotalTimes)}分</div>
  134. </div>
  135. ),
  136. ];
  137. },
  138. },
  139. {
  140. title: '做题时间',
  141. width: 100,
  142. align: 'left',
  143. render: record => {
  144. return [<div className="table-row">
  145. <div>{record.report && formatDate(record.report.updateTime, 'YYYY-MM-DD')}</div>
  146. <div>{record.report && formatDate(record.report.updateTime, 'HH:mm')}</div>
  147. </div>,
  148. this.state.showPrev && record.prevReport && (
  149. <div className="table-row prev t-3">
  150. <div>{formatDate(record.prevReport.updateTime, 'YYYY-MM-DD')}</div>
  151. <div>{formatDate(record.prevReport.updateTime, 'HH:mm')}</div>
  152. </div>
  153. ),
  154. ];
  155. },
  156. },
  157. {
  158. title: '操作',
  159. width: 110,
  160. align: 'left',
  161. render: record => {
  162. return [<div className="table-row p-t-1">
  163. {!record.report && (
  164. <IconButton
  165. className="m-r-5"
  166. type="start"
  167. tip="Start"
  168. onClick={() => {
  169. Question.startLink('examination', record);
  170. }}
  171. />
  172. )}
  173. {record.report && !record.report.isFinish && (
  174. <IconButton
  175. type="continue"
  176. tip="Continue"
  177. onClick={() => {
  178. Question.continueLink('examination', record);
  179. }}
  180. />
  181. )}
  182. </div>,
  183. this.state.showPrev && record.prevReport && (
  184. <div className="table-row prev" />
  185. ),
  186. ];
  187. },
  188. },
  189. {
  190. title: '报告',
  191. width: 50,
  192. align: 'right',
  193. render: record => {
  194. return [<div className="table-row p-t-1">
  195. {record.report && !!record.report.isFinish && (
  196. <IconButton
  197. className="m-r-5"
  198. type="report"
  199. tip="Report"
  200. onClick={() => {
  201. Question.reportLink(record);
  202. }}
  203. />
  204. )}
  205. </div>,
  206. this.state.showPrev && (
  207. <div className="prev">
  208. {record.prevReport && (
  209. <IconButton
  210. type="report"
  211. tip="Report"
  212. onClick={() => {
  213. Question.reportPrevLink(record);
  214. }}
  215. />
  216. )}
  217. </div>
  218. ),
  219. ];
  220. },
  221. },
  222. ];
  223. this.catColumns = [
  224. {
  225. title: '模考',
  226. width: 210,
  227. align: 'left',
  228. render: record => {
  229. let progress = 0;
  230. if (record.report) {
  231. progress = formatPercent(record.report.userNumber, record.report.questionNumber);
  232. }
  233. return (
  234. <div className="table-row">
  235. <div className="night f-s-16">
  236. {record.title}
  237. {record.paper && record.paper.paperNo > 0 ? String.fromCharCode(64 + record.paper.paperNo) : ''}
  238. </div>
  239. <div>
  240. <ProgressText progress={progress} size="small" />
  241. </div>
  242. </div>
  243. );
  244. },
  245. },
  246. {
  247. title: 'Total',
  248. width: 110,
  249. align: 'left',
  250. render: record => {
  251. return (
  252. <div className="table-row">
  253. <div className="night f-s-16 f-w-b">
  254. {record.report ? `${record.report.score.totalScore}分${record.report.score.totalRank}th` : '-分-th'}
  255. </div>
  256. <div className="f-s-12">全站: {Math.round(record.totalScore / record.totalTimes)}分</div>
  257. </div>
  258. );
  259. },
  260. },
  261. {
  262. title: 'Verbal',
  263. width: 110,
  264. align: 'left',
  265. render: record => {
  266. return (
  267. <div className="table-row">
  268. <div className="night f-s-16 f-w-b">
  269. {record.report ? `${record.report.score.verbalScore}分${record.report.score.verbalRank}th` : '-分-th'}
  270. </div>
  271. <div className="f-s-12">全站: {Math.round(record.verbalScore / record.totalTimes)}分</div>
  272. </div>
  273. );
  274. },
  275. },
  276. {
  277. title: 'Quant',
  278. width: 110,
  279. align: 'left',
  280. render: record => {
  281. return (
  282. <div className="table-row">
  283. <div className="night f-s-16 f-w-b">
  284. {record.report ? `${record.report.score.quantScore}分${record.report.score.quantRank}th` : '-分-th'}
  285. </div>
  286. <div className="f-s-12">全站: {Math.round(record.quantScore / record.totalTimes)}分</div>
  287. </div>
  288. );
  289. },
  290. },
  291. {
  292. title: 'IR',
  293. width: 110,
  294. align: 'left',
  295. render: record => {
  296. return (
  297. <div className="table-row">
  298. <div className="night f-s-16 f-w-b">
  299. {record.report ? `${record.report.score.irScore}分${record.report.score.irRank}th` : '-分-th'}
  300. </div>
  301. <div className="f-s-12">全站: {Math.round(record.irScore / record.totalTimes)}分</div>
  302. </div>
  303. );
  304. },
  305. },
  306. {
  307. title: '做题时间',
  308. width: 100,
  309. align: 'left',
  310. render: record => {
  311. return (
  312. <div className="table-row">
  313. <div>{record.report && formatDate(record.report.updateTime, 'YYYY-MM-DD')}</div>
  314. <div>{record.report && formatDate(record.report.updateTime, 'HH:mm')}</div>
  315. </div>
  316. );
  317. },
  318. },
  319. {
  320. title: '操作',
  321. width: 110,
  322. align: 'left',
  323. render: record => {
  324. return (
  325. <div className="table-row p-t-1">
  326. {!record.report && (
  327. <IconButton
  328. type="start"
  329. tip="Start"
  330. onClick={() => {
  331. Question.startLink('examination', record);
  332. }}
  333. />
  334. )}
  335. {record.report && !record.report.isFinish && (
  336. <IconButton
  337. className="m-r-2"
  338. type="continue"
  339. tip="Continue"
  340. onClick={() => {
  341. Question.continueLink('examination', record);
  342. }}
  343. />
  344. )}
  345. {record.report && <IconButton
  346. type="restart"
  347. tip="Restart"
  348. onClick={() => {
  349. this.restart(record);
  350. }}
  351. />}
  352. </div>
  353. );
  354. },
  355. },
  356. {
  357. title: '报告',
  358. width: 50,
  359. align: 'right',
  360. render: record => {
  361. return (
  362. <div className="table-row p-t-1">
  363. {record.report && !!record.report.isFinish && (
  364. <IconButton
  365. type="report"
  366. tip="Report"
  367. onClick={() => {
  368. Question.reportLink(record);
  369. }}
  370. />
  371. )}
  372. {this.state.showPrev && (
  373. <div className="prev">
  374. {record.prevReport && (
  375. <IconButton
  376. type="report"
  377. tip="Report"
  378. onClick={() => {
  379. Question.reportPrevLink(record);
  380. }}
  381. />
  382. )}
  383. </div>
  384. )}
  385. </div>
  386. );
  387. },
  388. },
  389. ];
  390. this.columns = [
  391. {
  392. title: '模考',
  393. width: 210,
  394. align: 'left',
  395. render: record => {
  396. let progress = 0;
  397. if (record.report) {
  398. progress = formatPercent(record.report.userNumber, record.report.questionNumber);
  399. }
  400. return (
  401. <div className="table-row">
  402. <div className="night f-s-16">{record.title}</div>
  403. <div>
  404. <ProgressText progress={progress} times={record.paper ? record.paper.finishTimes : 0} size="small" />
  405. </div>
  406. </div>
  407. );
  408. },
  409. },
  410. {
  411. title: 'Total',
  412. width: 110,
  413. align: 'left',
  414. render: () => {
  415. return (
  416. <div className="table-row">
  417. <div className="f-s-12">仅CAT模考<br />提供分数</div>
  418. </div>
  419. );
  420. },
  421. },
  422. {
  423. title: 'Verbal',
  424. width: 110,
  425. align: 'left',
  426. render: record => {
  427. return (
  428. <div className="table-row">
  429. <div className="f-s-12">
  430. {record.report
  431. ? formatPercent(record.report.setting.number.verbal, this.nums.verbal.number, false)
  432. : '0%'}
  433. </div>
  434. </div>
  435. );
  436. },
  437. },
  438. {
  439. title: 'Quant',
  440. width: 110,
  441. align: 'left',
  442. render: record => {
  443. return (
  444. <div className="table-row">
  445. <div className="f-s-12">
  446. {record.report
  447. ? formatPercent(record.report.setting.number.quant, this.nums.quant.number, false)
  448. : '0%'}
  449. </div>
  450. </div>
  451. );
  452. },
  453. },
  454. {
  455. title: 'IR',
  456. width: 110,
  457. align: 'left',
  458. render: record => {
  459. return (
  460. <div className="table-row">
  461. <div className="f-s-12">
  462. {record.report ? formatPercent(record.report.setting.number.ir, this.nums.ir.number, false) : '0%'}
  463. </div>
  464. </div>
  465. );
  466. },
  467. },
  468. {
  469. title: '做题时间',
  470. width: 100,
  471. align: 'left',
  472. render: record => {
  473. if (!record.report) return null;
  474. return (
  475. <div className="table-row">
  476. <div>{formatDate(record.report.updateTime, 'YYYY-MM-DD')}</div>
  477. <div>{formatDate(record.report.updateTime, 'HH:mm')}</div>
  478. </div>
  479. );
  480. },
  481. },
  482. {
  483. title: '操作',
  484. width: 110,
  485. align: 'left',
  486. render: record => {
  487. return (
  488. <div className="table-row p-t-1">
  489. {!record.report && (
  490. <IconButton
  491. type="start"
  492. tip="Start"
  493. onClick={() => {
  494. Question.startLink('examination', record);
  495. }}
  496. />
  497. )}
  498. {record.report && !record.report.isFinish && (
  499. <IconButton
  500. className="m-r-2"
  501. type="continue"
  502. tip="Continue"
  503. onClick={() => {
  504. Question.continueLink('examination', record);
  505. }}
  506. />
  507. )}
  508. {record.report && <IconButton
  509. type="restart"
  510. tip="Restart"
  511. onClick={() => {
  512. this.restart(record);
  513. }}
  514. />}
  515. </div>
  516. );
  517. },
  518. },
  519. {
  520. title: '报告',
  521. width: 50,
  522. align: 'right',
  523. render: record => {
  524. if (!record.report || !record.report.isFinish) return null;
  525. return (
  526. <div className="table-row p-t-1">
  527. <IconButton
  528. type="report"
  529. tip="Report"
  530. onClick={() => {
  531. Question.reportLink(record);
  532. }}
  533. />
  534. </div>
  535. );
  536. },
  537. },
  538. ];
  539. this.inited = false;
  540. return {};
  541. }
  542. init() {
  543. const { id } = this.params;
  544. Main.getExaminationParent(id).then(result => {
  545. const navs = result.map(row => {
  546. row.title = `${row.titleZh}${row.titleEn}`;
  547. return row;
  548. });
  549. this.cat = navs.filter(row => row.isAdapt > 0).length > 0;
  550. this.qxCat = navs.filter(row => row.isAdapt > 1).length > 0;
  551. Main.getExaminationNumber().then(nums => {
  552. this.nums = nums;
  553. this.inited = true;
  554. this.setState({ navs });
  555. this.refreshData();
  556. });
  557. });
  558. }
  559. initData() {
  560. const data = Object.assign(this.state, this.state.search);
  561. this.setState(data);
  562. if (this.inited) this.refreshData();
  563. }
  564. refreshData() {
  565. if (this.cat) {
  566. Question.getExaminationInfo().then(result => {
  567. this.setState({ examination: result });
  568. });
  569. }
  570. this.refreshExamination();
  571. }
  572. refreshExamination() {
  573. Question.getExaminationList(Object.assign({ structId: this.params.id }, this.state.search))
  574. .then(result => {
  575. this.setState({ list: result.list, total: result.total });
  576. })
  577. .catch(err => {
  578. asyncSMessage(err.message, 'warn');
  579. // linkTo('/examination');
  580. });
  581. }
  582. restart(item) {
  583. asyncConfirm('提示', '你打算重做本套练习,过往做题记录可至「个人中心-报告」查看。', () => {
  584. Question.restart(item.paper.id).then(() => {
  585. this.refresh();
  586. });
  587. });
  588. }
  589. resetCat() {
  590. Question.resetCat().then(() => {
  591. this.refresh();
  592. });
  593. }
  594. renderView() {
  595. const { list, navs, search, examination = {}, reset } = this.state;
  596. const { finish } = search;
  597. return (
  598. <div>
  599. <div className="content">
  600. <Breadcrumb separator=">">
  601. <Breadcrumb.Item href="/examination">模考</Breadcrumb.Item>
  602. {(navs || []).map(row => {
  603. return <Breadcrumb.Item>{row.title}</Breadcrumb.Item>;
  604. })}
  605. </Breadcrumb>
  606. <ListTable
  607. rightAction={
  608. <div hidden={!this.qxCat}>
  609. <span>有效期至:{examination.expireTime && formatDate(examination.expireTime, 'YYYY-MM-DD')}</span>
  610. {examination.reset && (
  611. <span>
  612. 第一遍模考成绩
  613. <Switch
  614. checked={this.state.showPrev}
  615. onChange={() => {
  616. this.setState({ showPrev: !this.state.showPrev });
  617. }}
  618. />
  619. </span>
  620. )}
  621. {!examination.reset && examination.canReset && (
  622. <Button
  623. size="small"
  624. radius
  625. onClick={() => {
  626. this.setState({ reset: true });
  627. }}
  628. >
  629. Reset
  630. </Button>
  631. )}
  632. {!examination.reset && !examination.canReset && (
  633. <Tooltip overlayClassName="gray" placement="top" title="全部模考做完才可重置">
  634. <a>
  635. <Button size="small" disabled radius>
  636. Reset
  637. </Button>
  638. </a>
  639. </Tooltip>
  640. )}
  641. </div>
  642. }
  643. filters={[
  644. {
  645. type: 'radio',
  646. checked: finish,
  647. list: [{ key: '0', title: '未完成' }, { key: '1', title: '已完成' }],
  648. onChange: item => {
  649. if (item.key === finish) {
  650. this.search({ finish: null });
  651. } else if (item.key === '0') {
  652. this.search({ finish: 0 });
  653. } else if (item.key === '1') {
  654. this.search({ finish: 1 });
  655. } else {
  656. this.search({ finish: null });
  657. }
  658. },
  659. },
  660. ]}
  661. data={list}
  662. columns={this.qxCatColumns}
  663. />
  664. </div>
  665. <RestartConfirmModal show={reset} onConfirm={() => this.resetCat()} onCancel={() => this.setState({ reset: false })} />
  666. </div>
  667. );
  668. }
  669. }