page.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. import React from 'react';
  2. import Fullscreen from 'react-fullscreen-crossbrowser';
  3. import './index.less';
  4. import Page from '@src/containers/Page';
  5. import { randomList, sortListWithOrder, resortListWithOrder } from '@src/services/Tools';
  6. import { Question } from '../../../stores/question';
  7. import Base from './base';
  8. import Sentence from './sentence';
  9. import { ExaminationOrder } from '../../../../Constant';
  10. import { Main } from '../../../stores/main';
  11. import { My } from '../../../stores/my';
  12. export default class extends Page {
  13. init() {
  14. this.singleTime = null;
  15. this.singleInterval = null;
  16. this.totalTime = null;
  17. this.totalInterval = null;
  18. this.stages = {};
  19. this.stage = '';
  20. this.stageInterval = null;
  21. this.stageTime = 0;
  22. this.stageNumber = 0;
  23. this.stageProcess = { number: 0, time: 0 };
  24. this.relaxProcess = { time: 0 };
  25. this.startInterval = null;
  26. this.startTime = 0;
  27. this.baseRef = null;
  28. this.sentenceRef = null;
  29. }
  30. initState() {
  31. return {
  32. setting: {},
  33. report: {},
  34. question: {},
  35. userQuestion: {},
  36. paper: {},
  37. scene: null,
  38. };
  39. }
  40. initData() {
  41. const { type, id } = this.params;
  42. // type 是获取基础paper的表信息
  43. // 等同于PaperOrigin
  44. Question.getPaper(type, id).then(paper => {
  45. let totalNumber = paper.questionNumber;
  46. let handler = null;
  47. if (paper.paperModule === 'examination') {
  48. // 模考获取配置信息
  49. handler = Main.getExaminationNumber().then(result => {
  50. totalNumber = 0;
  51. Object.keys(result).forEach(key => {
  52. result[key].time = Number(result[key].time);
  53. result[key].number = Number(result[key].number);
  54. totalNumber += result[key].number;
  55. });
  56. this.stages = result;
  57. this.relaxProcess = { time: 8 * 60 };
  58. });
  59. } else {
  60. handler = Promise.resolve();
  61. }
  62. this.setState({ paper, totalNumber });
  63. const { r } = this.state.search;
  64. if (r) {
  65. handler.then(() => {
  66. this.continue(r);
  67. });
  68. } else if (paper.paperModule === 'sentence') {
  69. // 长难句没有设置,直接开始
  70. handler.then(() => {
  71. this.start({});
  72. });
  73. } else {
  74. this.setState({ scene: 'start' });
  75. // 模考cat1分钟自动开始
  76. if (paper.isAdapt > 1) {
  77. this.startWaitTime();
  78. }
  79. }
  80. handler.catch(() => {
  81. goBack();
  82. });
  83. });
  84. }
  85. setSetting(newSetting) {
  86. const { setting } = this.state;
  87. this.setState({ setting: Object.assign(setting, newSetting) });
  88. }
  89. start(setting) {
  90. const { type, id } = this.params;
  91. return Question.start(type, id, setting).then(report => {
  92. if (report.isFinish) {
  93. return this.finish();
  94. }
  95. this.setState({ report, scene: 'question' });
  96. // 开始统计做题进度
  97. if (report.paperModule === 'examination') {
  98. const { order } = setting;
  99. this.initStage(order[0], 0, 0);
  100. }
  101. this.totalQuestionTime();
  102. return this.next();
  103. });
  104. }
  105. continue(reportId) {
  106. return Question.continue(reportId)
  107. .then(report => {
  108. if (report.isFinish) {
  109. throw new Error('做题结束,请先重置');
  110. }
  111. this.setState({ report, scene: 'questionn' });
  112. // 更新当前做题进度
  113. if (report.paperModule === 'examination') {
  114. const { stage, time, number } = report.setting;
  115. this.initStage(stage, time[stage], number[stage]);
  116. }
  117. this.totalQuestionTime(report.userTime || 0);
  118. return this.next();
  119. })
  120. .catch(() => {
  121. Question.reportLink({ report: { id: reportId } }, false);
  122. });
  123. }
  124. next() {
  125. const { report, scene } = this.state;
  126. const { setting = {} } = report;
  127. if (scene === 'relax') {
  128. // 进入下一阶段
  129. this.nextStage();
  130. }
  131. // 更新模考做题进度
  132. if (report.paperModule === 'examination') {
  133. if (this.stageNumber >= this.stageProcess.number) {
  134. const { order } = report.setting;
  135. // 进入休息
  136. if (order.indexOf(this.stage) < order.length - 1) {
  137. this.relaxStage();
  138. return Promise.resolve();
  139. }
  140. }
  141. }
  142. return Question.next(report.id)
  143. .then(userQuestion => {
  144. const questionSetting = {};
  145. if (setting.disorder) {
  146. const { questions } = userQuestion.question.content;
  147. if (questions) {
  148. // 乱序显示选项
  149. questionSetting.questions = [];
  150. questions.forEach(q => {
  151. const order = randomList(q.select.length);
  152. q.select = sortListWithOrder(q.select, order);
  153. questionSetting.questions.push(order);
  154. });
  155. }
  156. }
  157. this.setState({
  158. userQuestion,
  159. question: userQuestion.question,
  160. questionSetting,
  161. scene: 'question',
  162. });
  163. this.singleQuestionTime();
  164. return true;
  165. })
  166. .catch(err => {
  167. if (err.message === 'finish') {
  168. // 考试结束
  169. return this.finish();
  170. }
  171. return false;
  172. });
  173. }
  174. submit(answer) {
  175. const { report, userQuestion, questionSetting, singleTime } = this.state;
  176. const { setting = {} } = report;
  177. if (setting.disorder) {
  178. const { questions } = answer;
  179. if (questions) {
  180. // 还原乱序选项
  181. questions.forEach((q, index) => {
  182. const order = questionSetting.questions[index];
  183. Object.keys(q).forEach(k => {
  184. if (q[k]) q[k] = resortListWithOrder(q[k], order);
  185. });
  186. });
  187. }
  188. }
  189. return Question.submit(userQuestion.id, answer, singleTime, questionSetting).then(() => {
  190. this.singleQuestionTime(true);
  191. if (report.paperModule === 'examination') {
  192. this.stageNumber += 1;
  193. }
  194. });
  195. }
  196. // 主动进入下一阶段
  197. stage() {
  198. const { report } = this.state;
  199. return Question.stage(report.id)
  200. .then(() => {
  201. this.baseRef.timeOut(() => {
  202. this.relaxStage();
  203. });
  204. });
  205. }
  206. finish() {
  207. const { report } = this.state;
  208. return Question.finish(report.id)
  209. .then(() => {
  210. // 跳转到报告页
  211. Question.reportLink({ report }, false);
  212. // this.setState({ scene: 'finish' });
  213. })
  214. .catch(() => {
  215. Question.reportLink({ report }, false);
  216. });
  217. }
  218. singleQuestionTime(stop) {
  219. if (this.singleInterval) {
  220. clearInterval(this.singleInterval);
  221. this.singleInterval = null;
  222. }
  223. if (!stop) {
  224. this.singleTime = 0;
  225. this.singleInterval = setInterval(() => {
  226. this.singleTime += 1;
  227. this.setState({ singleTime: this.singleTime });
  228. }, 1000);
  229. }
  230. }
  231. totalQuestionTime(initTime, stop) {
  232. if (initTime) {
  233. this.totalTime = initTime;
  234. }
  235. if (this.totalInterval) {
  236. clearInterval(this.totalInterval);
  237. this.totalInterval = null;
  238. }
  239. if (!stop) {
  240. this.totalInterval = setInterval(() => {
  241. this.totalTime += 1;
  242. this.setState({ totalTime: this.totalTime });
  243. }, 1000);
  244. }
  245. }
  246. stageQuestionTime(initTime, stop) {
  247. if (this.stageInterval) {
  248. clearInterval(this.stageInterval);
  249. this.stageInterval = null;
  250. this.stageTime = initTime;
  251. }
  252. if (!stop) {
  253. this.stageInterval = setInterval(() => {
  254. this.stageTime += 1;
  255. if (this.stageTime >= this.stageProcess.time) {
  256. this.stageQuestionTime(0, true);
  257. const { scene } = this.state;
  258. if (scene === 'relax') {
  259. // 进入下一阶段,获取下一题
  260. this.next();
  261. } else {
  262. // 提交当前阶段
  263. this.stage();
  264. }
  265. }
  266. this.setState({ stageTime: this.stageProcess.time - this.stageTime });
  267. }, 1000);
  268. }
  269. }
  270. startWaitTime() {
  271. if (this.startInterval) {
  272. clearInterval(this.startInterval);
  273. this.startInterval = null;
  274. }
  275. this.startInterval = setInterval(() => {
  276. this.startTime += 1;
  277. // 1分钟等待: 自动提交第一选择
  278. const { scene } = this.state;
  279. if (scene !== 'start') {
  280. clearInterval(this.startInterval);
  281. this.startInterval = null;
  282. } else if (this.startTime >= 60) {
  283. clearInterval(this.startInterval);
  284. this.startInterval = null;
  285. this.start(Object.assign({ order: ExaminationOrder[0].value }, this.state.setting));
  286. }
  287. this.setState({ startTime: 60 - this.startTime });
  288. }, 1000);
  289. }
  290. nextStage() {
  291. const { report } = this.state;
  292. // 进入下一阶段
  293. const { order } = report.setting;
  294. this.stage = order[order.indexOf(this.stage) + 1];
  295. this.stageProcess = this.stages[this.stage];
  296. this.stageNumber = 0;
  297. this.stageQuestionTime(0);
  298. this.setState({ totalNumber: this.stageProcess.number });
  299. }
  300. relaxStage() {
  301. this.stageProcess = this.relaxProcess;
  302. this.stageNumber = 0;
  303. this.stageQuestionTime(0);
  304. this.setState({
  305. scene: 'relax',
  306. });
  307. return true;
  308. }
  309. initStage(stage, time, number) {
  310. this.stage = stage;
  311. this.stageProcess = this.stages[stage];
  312. this.stageTime = time;
  313. this.stageNumber = number;
  314. this.stageQuestionTime(time);
  315. this.setState({ totalNumber: this.stageProcess.number });
  316. }
  317. toggleFullscreen() {
  318. const { isFullscreenEnabled } = this.state;
  319. this.setState({ isFullscreenEnabled: !isFullscreenEnabled });
  320. }
  321. toggleCollect() {
  322. const { userQuestion = {} } = this.state;
  323. if (!userQuestion.collect) {
  324. My.addQuestionCollect(userQuestion.questionNoId).then(() => {
  325. userQuestion.collect = true;
  326. this.setState({ userQuestion });
  327. });
  328. } else {
  329. My.delQuestionCollect(userQuestion.questionNoId).then(() => {
  330. userQuestion.collect = false;
  331. this.setState({ userQuestion });
  332. });
  333. }
  334. }
  335. renderView() {
  336. return (
  337. <Fullscreen
  338. enabled={this.state.isFullscreenEnabled}
  339. onChange={isFullscreenEnabled => this.setState({ isFullscreenEnabled })}
  340. >
  341. {this.renderDetail()}
  342. </Fullscreen>
  343. );
  344. }
  345. renderDetail() {
  346. const { scene, paper, userQuestion } = this.state;
  347. if (!paper.id || !scene) return null;
  348. switch (paper.paperModule) {
  349. case 'sentence':
  350. return <Sentence ref={(ref) => { this.sentenceRef = ref; }} key={userQuestion.id} {...this.state} flow={this} mode='process' />;
  351. default:
  352. return <Base ref={(ref) => { this.baseRef = ref; }} key={userQuestion.id} {...this.state} flow={this} mode='process' />;
  353. }
  354. }
  355. }