page.js 9.5 KB

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