page.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import React from 'react';
  2. import { Breadcrumb, 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, formatSeconds, formatDate } from '@src/services/Tools';
  7. import ListTable from '../../../components/ListTable';
  8. import ProgressText from '../../../components/ProgressText';
  9. import IconButton from '../../../components/IconButton';
  10. import Button from '../../../components/Button';
  11. import { Question } from '../../../stores/question';
  12. import { Textbook } from '../../../stores/textbook';
  13. import Select from '../../../components/Select';
  14. const TextbookMinYear = 2019;
  15. export default class extends Page {
  16. initState() {
  17. this.columns = [{
  18. title: '练习册',
  19. width: 250,
  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">
  28. <div className="night f-s-16">{record.title}</div>
  29. <div>
  30. <ProgressText progress={progress} times={record.paper ? record.paper.times : 0} size="small" />
  31. </div>
  32. </div>
  33. );
  34. },
  35. }, {
  36. title: '正确率',
  37. width: 150,
  38. align: 'left',
  39. render: (record) => {
  40. let correct = '--';
  41. if (record.report) {
  42. correct = formatPercent(record.report.userCorrect, record.report.userNumber, false);
  43. }
  44. return (
  45. <div className="table-row">
  46. <div className="night f-s-16 f-w-b">{correct}</div>
  47. <div className="f-s-12">全站{formatPercent(record.stat.totalCorrect, record.stat.totalNumber, false)}</div>
  48. </div>
  49. );
  50. },
  51. }, {
  52. title: '全站用时',
  53. width: 150,
  54. align: 'left',
  55. render: (record) => {
  56. let time = '--';
  57. if (record.paper) {
  58. time = formatSeconds(record.paper.report.userTime / record.paper.report.userNumber);
  59. }
  60. return (
  61. <div className="table-row">
  62. <div className="night f-s-16 f-w-b">{time}</div>
  63. <div className="f-s-12">全站{formatSeconds(record.stat.totalTime / record.stat.totalNumber)}</div>
  64. </div>
  65. );
  66. },
  67. }, {
  68. title: '最近做题',
  69. width: 150,
  70. align: 'left',
  71. render: (record) => {
  72. const time = record.report ? record.report.updateTime : record.paper ? record.paper.latestTime : null;
  73. return (
  74. <div className="table-row">
  75. <div>{time && formatDate(time, 'YYYY-MM-DD')}</div>
  76. <div>{time && formatDate(time, 'HH:mm')}</div>
  77. </div>
  78. );
  79. },
  80. }, {
  81. title: '操作',
  82. width: 180,
  83. align: 'left',
  84. render: (record) => {
  85. return (
  86. <div className="table-row p-t-1">
  87. {!record.report && <IconButton type="start" tip="Start" onClick={() => {
  88. Question.startLink('exercise', record);
  89. }} />}
  90. {(record.report && !record.report.isFinish) && <IconButton className="m-r-2" type="continue" tip="Continue" onClick={() => {
  91. Question.continueLink('exercise', record);
  92. }} />}
  93. <IconButton type="restart" tip="Restart" onClick={() => {
  94. this.restart(record);
  95. }} />
  96. </div>
  97. );
  98. },
  99. }, {
  100. title: '报告',
  101. width: 30,
  102. align: 'right',
  103. render: (record) => {
  104. return (
  105. <div className="table-row p-t-1">
  106. {record.report && record.report.isFinish && <IconButton type="report" tip="Report" onClick={() => {
  107. Question.reportLink(record);
  108. }} />}
  109. </div>
  110. );
  111. },
  112. }];
  113. this.inited = false;
  114. const year = [];
  115. const nowYear = new Date().getFullYear();
  116. for (let i = TextbookMinYear; i <= nowYear; i += 1) {
  117. year.push({
  118. title: i.toString(),
  119. key: i.toString(),
  120. });
  121. }
  122. return {
  123. yearList: year,
  124. };
  125. }
  126. initData() {
  127. const { search } = this.state;
  128. const info = {};
  129. info.latest = search.latest ? Number(search.latest) : 0;
  130. info.logic = search.logic ? search.logic : 'ds';
  131. info.year = search.year ? search.year : new Date().getFullYear().toString();
  132. const data = Object.assign(this.state, this.state.search);
  133. data.info = info;
  134. this.setState(data);
  135. this.refreshData();
  136. }
  137. refreshData() {
  138. Textbook.getInfo().then((result) => {
  139. this.setState({ textbook: result });
  140. });
  141. this.refreshTextbook();
  142. }
  143. refreshTextbook() {
  144. Textbook.listPaper(Object.assign({}, this.state.search, this.state.info))
  145. .then((result) => {
  146. this.setState({ list: result.list, total: result.total });
  147. })
  148. .catch(err => {
  149. asyncSMessage(err.message, 'warn');
  150. linkTo('/examination');
  151. });
  152. }
  153. restart(item) {
  154. asyncConfirm('提示', '是否重置', () => {
  155. Question.restart(item.paper.id).then(() => {
  156. this.refresh();
  157. });
  158. });
  159. }
  160. subscribe(value) {
  161. Textbook.subscribe(value)
  162. .then(() => {
  163. this.refresh();
  164. })
  165. .catch(err => {
  166. asyncSMessage(err.message, 'warn');
  167. });
  168. }
  169. renderView() {
  170. const { list, search, info = {}, textbook = {} } = this.state;
  171. const { finish } = search;
  172. return (
  173. <div>
  174. <div className="content">
  175. <div className="textbook-head">
  176. <Breadcrumb separator=">">
  177. <Breadcrumb.Item href="/examination">模考</Breadcrumb.Item>
  178. <Breadcrumb.Item href="/examination?tab1=textbook">数学机经</Breadcrumb.Item>
  179. <Breadcrumb.Item>{info.latest ? '最新' : '往期'}</Breadcrumb.Item>
  180. <Breadcrumb.Item>{info.logic ? info.logic.toUpperCase() : ''}</Breadcrumb.Item>
  181. </Breadcrumb>
  182. {!!info.latest && !!textbook.latest && <div className='textbook-time'>最近更新:{formatDate(textbook.latest.updateTime, 'YYYY-MM-DD')}</div>}
  183. </div>
  184. <ListTable
  185. rightAction={<div>
  186. {!!info.latest && <span>邮箱订阅<Switch checked={textbook.subscribe} onChange={() => {
  187. this.subscribe(!textbook.subscribe);
  188. }} /></span>}
  189. {!!info.latest && <Button radius onClick={() => {
  190. this.download();
  191. }}>下载</Button>}
  192. {!info.latest && <Select value={info.year} theme="default" list={this.state.yearList || []} onChange={(item) => {
  193. this.search({ year: item.key });
  194. }} />}
  195. </div>}
  196. filters={[
  197. {
  198. type: 'radio',
  199. checked: finish,
  200. list: [{ key: '0', title: '未完成' }, { key: '1', title: '已完成' }],
  201. onChange: item => {
  202. if (item.key === finish) {
  203. this.search({ finish: null });
  204. } else if (item.key === '0') {
  205. this.search({ finish: 0 });
  206. } else if (item.key === '1') {
  207. this.search({ finish: 1 });
  208. } else {
  209. this.search({ finish: null });
  210. }
  211. },
  212. },
  213. ]}
  214. data={list}
  215. columns={this.columns}
  216. />
  217. </div>
  218. </div>
  219. );
  220. }
  221. }