index.js 6.19 KB
Newer Older
zhanghaozhe committed
1 2 3 4 5 6
import React, { Component } from 'react';
import './index.scss'
import Question from '../common/question'
import { browser, getParam, http } from "@/utils"
import { Toast } from 'antd-mobile'
import storage from 'store2'
zhanghaozhe committed
7
import Navigation from "@components/ai-test/common/navigation"
zhanghaozhe committed
8 9 10 11 12 13 14
import {
  differenceInSeconds,
  differenceInMinutes,
  differenceInHours,
  differenceInDays,
  differenceInMilliseconds,
} from "date-fns";
zhanghaozhe committed
15
import { isEmpty } from 'lodash'
zhanghaozhe committed
16 17
import { connect } from 'react-redux'
import { matchPath } from 'react-router-dom'
zhanghaozhe committed
18 19 20 21

class Exam extends Component {

  store = storage.namespace('aiTestExam')
zhanghaozhe committed
22 23
  timer = null
  unlisten = null
zhanghaozhe committed
24 25 26 27 28

  state = {
    questions: [],
    activeQuestion: 0,
    time: {
zhanghaozhe committed
29
      d: 0,
zhanghaozhe committed
30 31 32 33
      h: 0,
      m: 0,
      s: 0,
    },
zhanghaozhe committed
34
    elapsed: 0,
zhanghaozhe committed
35 36
    answer: {},
    recordId: undefined,
zhanghaozhe committed
37 38 39
  }

  componentDidMount() {
zhanghaozhe committed
40 41 42 43
    const {user, history} = this.props
    if (user.hasError) {
      return history.push('/passport')
    }
zhanghaozhe committed
44 45
    if (this.store.session.get('submitted')) {
      this.store.session.clearAll()
zhanghaozhe committed
46 47
      this.props.history.replace('/ai-test')
    }
zhanghaozhe committed
48 49 50 51 52 53 54 55 56
    this.unlisten = history.listen((location) => {
      const match = matchPath(location.pathname, {
        path: '/ai-test',
      })
      if (match.isExact) {
        this.store.clearAll()
      }
      this.unlisten && this.unlisten()
    })
zhanghaozhe committed
57
    this.getQuestions()
zhanghaozhe committed
58 59 60 61 62 63 64 65 66 67 68 69

    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'visible') {
        this.setState(state => {
          return {
            elapsed: state.elapsed + (Date.now() - this.store.session.get('hiddenTimestamp')) / 10,
          }
        })
      } else {
        this.store.session.set('hiddenTimestamp', Date.now())
      }
    })
zhanghaozhe committed
70 71
  }

zhanghaozhe committed
72 73 74 75 76
  componentWillUnmount() {
    clearInterval(this.timer)
  }


zhanghaozhe committed
77
  setCounter = () => {
zhanghaozhe committed
78
    this.timer = setInterval(() => {
zhanghaozhe committed
79
      this.setState(state => {
zhanghaozhe committed
80
        const fms = state.elapsed + 1
zhanghaozhe committed
81
        return {
zhanghaozhe committed
82
          time: {
zhanghaozhe committed
83 84 85 86
            d: Math.floor(fms / (60 * 60 * 100 * 24)),
            h: Math.floor(fms / (60 * 60 * 100)) % 24,
            m: Math.floor(fms / (60 * 100)) % 60,
            s: Math.floor(fms / 100) % 60,
zhanghaozhe committed
87
          },
zhanghaozhe committed
88
          elapsed: fms,
zhanghaozhe committed
89 90
        }
      })
zhanghaozhe committed
91
    }, 10)
zhanghaozhe committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
  }

  goBack = () => {
    const {state} = this.props.location
    if (browser.isWeixin && getParam('code') && getParam('state')) {
      window.history.go(-2)
    }
    if (state.records && state.records.length > 1) {
      window.history.go(-1);
    } else if (state.from && state.from.pathname) {
      location.replace(`${state.from.pathname}${state.from.search}`)
    } else {
      window.location.href = window.location.origin
    }
  }

  getQuestions = () => {
    http.get(`${API.home}/sys/get_question`)
      .then(res => {
        const {code, msg, data} = res.data
        if (code === 200) {
zhanghaozhe committed
113
          let answer = this.store.session.get('answer') || {}
zhanghaozhe committed
114
          if (isEmpty(answer)) {
zhanghaozhe committed
115
            data.forEach(item => {
zhanghaozhe committed
116
              answer[item.id] = 0
zhanghaozhe committed
117 118
            })
          }
zhanghaozhe committed
119 120
          this.setState({
            questions: data,
zhanghaozhe committed
121 122
            answer,
            recordId: data[0].record_id,
zhanghaozhe committed
123
          })
zhanghaozhe committed
124
          this.getStartTime(data[0].create_time, data[0].now)
zhanghaozhe committed
125 126 127
          this.setCounter()
        } else if (code === 23007) {
          this.props.history.replace('/ai-test/scores')
zhanghaozhe committed
128 129 130 131 132 133
        } else {
          Toast.fail(msg, 2, null, false)
        }
      })
  }

zhanghaozhe committed
134 135 136
  getStartTime = (createTimeStamp, current) => {
    const now = new Date(current * 1000)
    const createTime = new Date(createTimeStamp * 1000)
zhanghaozhe committed
137 138 139 140 141 142 143
    this.setState({
      time: {
        d: differenceInDays(now, createTime),
        h: differenceInHours(now, createTime) % 24,
        m: differenceInMinutes(now, createTime) % 60,
        s: differenceInSeconds(now, createTime) % 60,
      },
zhanghaozhe committed
144
      elapsed: differenceInMilliseconds(now, createTime) / 10,
zhanghaozhe committed
145 146 147
    });
  }

zhanghaozhe committed
148 149
  selectAnswer = (question, optionId) => {
    this.setState(state => {
zhanghaozhe committed
150
      const answer = state.answer
zhanghaozhe committed
151 152 153 154 155 156
      const activeQuestion = state.activeQuestion + 1
      setTimeout(() => {
        this.setState({
          activeQuestion: activeQuestion >= state.questions.length ? state.questions.length - 1 : activeQuestion,
        });
      }, 200)
zhanghaozhe committed
157
      answer[question.id] = optionId
zhanghaozhe committed
158
      return {
zhanghaozhe committed
159 160 161
        answer,
      }
    }, () => {
zhanghaozhe committed
162 163
      const {questions, activeQuestion} = this.state
      if (activeQuestion === questions.length - 1) {
zhanghaozhe committed
164
        this.storeData()
zhanghaozhe committed
165 166 167 168
      }
    })
  }

zhanghaozhe committed
169 170 171 172
  storeData = () => {
    const {answer, time, recordId, elapsed} = this.state
    const {history} = this.props
    clearInterval(this.timer)
zhanghaozhe committed
173
    this.store.session.setAll({time, answer, recordId, elapsed})
zhanghaozhe committed
174 175 176 177
    history.push('/ai-test/submit')

  }

zhanghaozhe committed
178
  render() {
zhanghaozhe committed
179
    const {questions, activeQuestion, time, answer} = this.state
zhanghaozhe committed
180 181 182 183 184 185 186 187 188 189
    return (
      <div className={'exam'}>
        <header>
          <div className="go-back">
            <i className='iconfont iconiconfront-68' onClick={this.goBack}></i>
          </div>
          <div className="time">
            <i className={'iconfont iconzhong'}></i>
            <span>
              {
zhanghaozhe committed
190
                !!time.d && <>{time.d}</>
zhanghaozhe committed
191 192
              }
              {
zhanghaozhe committed
193 194 195 196 197 198
                !!time.h && <>{time.h && time.h.toString().padStart(2, '0')}:</>
              }
              {time.m.toString().padStart(2, '0')}:
              {time.s.toString().padStart(2, '0')}
            </span>
          </div>
zhanghaozhe committed
199 200
          <div className="count"
               onClick={this.storeData}>{Object.values(answer).filter(item => item).length}/{questions.length}</div>
zhanghaozhe committed
201 202 203 204 205 206 207
        </header>
        <div className="banner">
          <img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/ai-test/m/scores/exam-banner.png" alt=""/>
        </div>
        <div className="question-section">
          {
            !!questions.length &&
zhanghaozhe committed
208 209
            <Question activeIndex={activeQuestion} question={questions[activeQuestion]} selectAnswer={this.selectAnswer}
                      answer={answer}></Question>
zhanghaozhe committed
210 211
          }
        </div>
zhanghaozhe committed
212 213 214 215 216
        <Navigation questions={questions} answer={answer} handleClick={(index) => {
          this.setState({
            activeQuestion: index,
          });
        }}/>
zhanghaozhe committed
217 218 219 220 221
      </div>
    );
  }
}

zhanghaozhe committed
222 223 224 225
export default connect(
  ({user}) => ({user}),
  null,
)(Exam);