page.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import React from 'react';
  2. import './index.less';
  3. import { Link } from 'react-router-dom';
  4. import Page from '@src/containers/Page';
  5. import { asyncConfirm } from '@src/services/AsyncTools';
  6. import Tabs from '../../../components/Tabs';
  7. import Module from '../../../components/Module';
  8. import Input from '../../../components/Input';
  9. import Button from '../../../components/Button';
  10. import Division from '../../../components/Division';
  11. import Card from '../../../components/Card';
  12. import ListTable from '../../../components/ListTable';
  13. import ProgressText from '../../../components/ProgressText';
  14. import IconButton from '../../../components/IconButton';
  15. import { Main } from '../../../stores/main';
  16. import { Question } from '../../../stores/question';
  17. const HARD = 'HARD';
  18. const PREVIEW = 'PREVIEW';
  19. const PREVIEW_CLASS = 'PREVIEW_CLASS';
  20. const PREVIEW_TASK = 'PREVIEW_TASK';
  21. const columns = [
  22. {
  23. title: '练习册',
  24. width: 250,
  25. align: 'left',
  26. render: item => {
  27. return (
  28. <div className="table-row">
  29. <div className="night f-s-16">{item.title}</div>
  30. <div>
  31. <ProgressText
  32. progress={item.report.id ? item.repport.userNumber / item.report.questionNumber : 0}
  33. size="small"
  34. />
  35. </div>
  36. </div>
  37. );
  38. },
  39. },
  40. {
  41. title: '正确率',
  42. width: 150,
  43. align: 'left',
  44. render: item => {
  45. return (
  46. <div className="table-row">
  47. <div className="night f-s-16 f-w-b">--</div>
  48. <div className="f-s-12">{item.stat.totalCorrect / item.stat.totalNumber}</div>
  49. </div>
  50. );
  51. },
  52. },
  53. {
  54. title: '全站用时',
  55. width: 150,
  56. align: 'left',
  57. render: item => {
  58. return (
  59. <div className="table-row">
  60. <div className="night f-s-16 f-w-b">--</div>
  61. <div className="f-s-12">全站{item.stat.totalTime / item.stat.totalNumber}s</div>
  62. </div>
  63. );
  64. },
  65. },
  66. {
  67. title: '最近做题',
  68. width: 150,
  69. align: 'left',
  70. render: () => {
  71. return (
  72. <div className="table-row">
  73. <div>2019-04-28</div>
  74. <div>07:30</div>
  75. </div>
  76. );
  77. },
  78. },
  79. {
  80. title: '操作',
  81. width: 180,
  82. align: 'left',
  83. render: item => {
  84. return (
  85. <div className="table-row p-t-1">
  86. {!item.repport.id && (
  87. <IconButton type="start" tip="Start" onClick={() => this.previewAction('start', item)} />
  88. )}
  89. {item.repport.id && (
  90. <IconButton
  91. className="m-r-2"
  92. type="continue"
  93. tip="Continue"
  94. onClick={() => this.previewAction('continue', item)}
  95. />
  96. )}
  97. {item.repport.id && (
  98. <IconButton type="restart" tip="Restart" onClick={() => this.previewAction('restart', item)} />
  99. )}
  100. </div>
  101. );
  102. },
  103. },
  104. {
  105. title: '报告',
  106. width: 30,
  107. align: 'right',
  108. render: item => {
  109. return (
  110. <div className="table-row p-t-1">
  111. {item.report.userNumber === item.report.questionNumber && <IconButton type="report" tip="Report" />}
  112. </div>
  113. );
  114. },
  115. },
  116. ];
  117. export default class extends Page {
  118. initState() {
  119. this.columns = columns;
  120. return {
  121. level1Tab: PREVIEW,
  122. level2Tab: '',
  123. previewType: PREVIEW_CLASS,
  124. tabs: [],
  125. allClass: [],
  126. classProcess: {},
  127. };
  128. }
  129. initData() {
  130. Main.getExercise().then(result => {
  131. const list = result;
  132. const map = {};
  133. for (let i = 0; i < result.length; i += 1) {
  134. const item = result[i];
  135. if (!map[item.parentId]) map[item.parentId] = [];
  136. map[item.parentId].push(item);
  137. }
  138. const tabs = [];
  139. let allClass = [];
  140. tabs.push({ key: HARD, name: '长难句' });
  141. if (map[0]) {
  142. for (let i = 0; i < map[0].length; i += 1) {
  143. const item = map[0][i];
  144. tabs.push({ key: item.id, name: `${item.titleZh} ${item.titleEn}` });
  145. if (map[item.id]) {
  146. allClass = allClass.concat(map[item.id]);
  147. }
  148. }
  149. }
  150. tabs.push({ key: PREVIEW, name: '预习作业' });
  151. this.setState({ tabs, allClass, list, map });
  152. });
  153. this.refreshClassProcess();
  154. }
  155. refreshPreview() {
  156. const { previewType } = this.state;
  157. if (previewType === PREVIEW_CLASS) {
  158. this.refreshClassProcess();
  159. }
  160. if (previewType === PREVIEW_TASK) {
  161. this.refreshListPreview();
  162. }
  163. }
  164. onChangePreviewType(type) {
  165. this.setState({ previewType: type });
  166. this.refreshPreview();
  167. }
  168. refreshClassProcess() {
  169. Question.getClassProcess().then(result => {
  170. const classProcess = {};
  171. for (let i = 0; i < result.length; i += 1) {
  172. const item = result[i];
  173. classProcess[item.category].push(item);
  174. }
  175. this.setState({ classProcess });
  176. });
  177. }
  178. refreshListPreview() {
  179. Question.listPreview().then(result => {
  180. this.setState({ previews: result });
  181. });
  182. }
  183. onChangeTab(level, tab) {
  184. const state = {};
  185. state[`level${level}Tab`] = tab;
  186. this.setState(state);
  187. }
  188. previewAction(type, item) {
  189. switch (type) {
  190. case 'start':
  191. this.startPreview(item);
  192. break;
  193. case 'restart':
  194. this.restartPreview(item);
  195. break;
  196. case 'continue':
  197. this.continuePreview(item);
  198. break;
  199. default:
  200. break;
  201. }
  202. }
  203. startPreview(item) {
  204. linkTo(`/start/${item.id}?type=preview`);
  205. }
  206. restartPreview(item) {
  207. asyncConfirm('提示', '是否重置', () => {
  208. Question.restart(item.report.id).then(() => {
  209. this.refreshPreview();
  210. });
  211. });
  212. }
  213. continuePreview(item) {
  214. linkTo(`/start/${item.id}?type=preview&r=${item.report.id}`);
  215. }
  216. renderView() {
  217. const { level1Tab, level2Tab, tabs, map } = this.state;
  218. return (
  219. <div>
  220. <div className="content">
  221. <Module className="m-t-2">
  222. <Tabs type="card" active={level1Tab} tabs={tabs} onChange={key => this.onChangeTab(1, key)} />
  223. {level1Tab !== HARD && level1Tab !== PREVIEW && (
  224. <Tabs active={level2Tab} tabs={map[level2Tab]} onChange={key => this.onChangeTab(2, key)} />
  225. )}
  226. </Module>
  227. {level1Tab !== HARD && level1Tab !== PREVIEW && this.renderType()}
  228. {level1Tab === HARD && this.renderHard()}
  229. {level1Tab === PREVIEW && this.renderWork()}
  230. </div>
  231. </div>
  232. );
  233. }
  234. renderWork() {
  235. const { previewType } = this.state;
  236. switch (previewType) {
  237. case PREVIEW_CLASS:
  238. return this.renderAllClass();
  239. case PREVIEW_TASK:
  240. return this.renderAllTask();
  241. default:
  242. return <div />;
  243. }
  244. }
  245. renderAllClass() {
  246. const { allClass, classProcess } = this.state;
  247. return (
  248. <div className="work-body">
  249. <div className="work-nav">
  250. <div className="left">完成情况</div>
  251. <div className="right theme c-p" onClick={() => this.onChangePreviewType(PREVIEW_TASK)}>
  252. 全部作业 >
  253. </div>
  254. </div>
  255. <Division col="3">
  256. {allClass.map(item => {
  257. return <Card data={item} process={classProcess[item.id]} previewAction={this.previewAction} />;
  258. })}
  259. </Division>
  260. </div>
  261. );
  262. }
  263. renderAllTask() {
  264. const { previews } = this.state;
  265. return (
  266. <div className="work-body">
  267. <div className="work-nav">
  268. <div className="left">全部作业</div>
  269. <div className="right theme c-p" onClick={() => this.onChangePreviewType(PREVIEW_CLASS)}>
  270. 我的课程 >
  271. </div>
  272. </div>
  273. <ListTable
  274. filters={[
  275. {
  276. type: 'radio',
  277. checked: 'today',
  278. list: [{ key: 'today', title: '今日需完成' }, { key: 'tomorrow', title: '明日需完成' }],
  279. },
  280. {
  281. type: 'radio',
  282. checked: 'unfinish',
  283. list: [{ key: 'unfinish', title: '未完成' }, { key: 'finish', title: '已完成' }],
  284. },
  285. { type: 'select', checked: 'all', list: [{ key: 'all', title: '全部' }] },
  286. ]}
  287. data={previews}
  288. columns={this.columns}
  289. />
  290. </div>
  291. );
  292. }
  293. renderHard() {
  294. return this.renderInputCode();
  295. }
  296. renderType() {
  297. return <div />;
  298. }
  299. renderInputCode() {
  300. return (
  301. <Module className="code-module">
  302. <div className="title">输入《千行GMAT长难句》专属 Code,解锁在线练习功能。</div>
  303. <div className="input-block">
  304. <Input size="lager" placeholder="请输入CODE" />
  305. <Button size="lager">解锁</Button>
  306. </div>
  307. <div className="tip">
  308. <Link to="/" className="left link">
  309. 什么是CODE?
  310. </Link>
  311. <span>没有 CODE?</span>
  312. <Link to="/" className="link">
  313. 去获取 >>
  314. </Link>
  315. <Link to="/" className="right link">
  316. 试用 >>
  317. </Link>
  318. </div>
  319. </Module>
  320. );
  321. }
  322. }