import React, { Component } from 'react'; import './index.scss' import Question from '../common/question' import { browser, getParam, http } from "src/utils" import { Toast } from 'antd-mobile' import storage from 'store2' import Navigation from "src/components/ai-test/common/navigation" import { differenceInSeconds, differenceInMinutes, differenceInHours, differenceInDays, differenceInMilliseconds, } from "date-fns"; import { isEmpty } from 'lodash' import { connect } from 'react-redux' import { matchPath } from 'react-router-dom' class Exam extends Component { store = storage.namespace('aiTestExam') timer = null unlisten = null state = { questions: [], activeQuestion: 0, time: { d: 0, h: 0, m: 0, s: 0, }, elapsed: 0, answer: {}, recordId: undefined, } componentDidMount() { const {user, history} = this.props if (user.hasError) { return history.push('/passport') } if (this.store.session.get('submitted')) { this.store.session.clearAll() this.props.history.replace('/ai-test') } this.unlisten = history.listen((location) => { const match = matchPath(location.pathname, { path: '/ai-test', }) if (match.isExact) { this.store.clearAll() } this.unlisten && this.unlisten() }) this.getQuestions() 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()) } }) } componentWillUnmount() { clearInterval(this.timer) } setCounter = () => { this.timer = setInterval(() => { this.setState(state => { const fms = state.elapsed + 1 return { time: { 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, }, elapsed: fms, } }) }, 10) } 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) { let answer = this.store.session.get('answer') || {} if (isEmpty(answer)) { data.forEach(item => { answer[item.id] = 0 }) } this.setState({ questions: data, answer, recordId: data[0].record_id, }) this.getStartTime(data[0].create_time, data[0].now) this.setCounter() } else if (code === 23007) { this.props.history.replace('/ai-test/scores') } else { Toast.fail(msg, 2, null, false) } }) } getStartTime = (createTimeStamp, current) => { const now = new Date(current * 1000) const createTime = new Date(createTimeStamp * 1000) this.setState({ time: { d: differenceInDays(now, createTime), h: differenceInHours(now, createTime) % 24, m: differenceInMinutes(now, createTime) % 60, s: differenceInSeconds(now, createTime) % 60, }, elapsed: differenceInMilliseconds(now, createTime) / 10, }); } selectAnswer = (question, optionId) => { this.setState(state => { const answer = state.answer const activeQuestion = state.activeQuestion + 1 setTimeout(() => { this.setState({ activeQuestion: activeQuestion >= state.questions.length ? state.questions.length - 1 : activeQuestion, }); }, 200) answer[question.id] = optionId return { answer, } }, () => { const {questions, activeQuestion} = this.state if (activeQuestion === questions.length - 1) { this.storeData() } }) } storeData = () => { const {answer, time, recordId, elapsed} = this.state const {history} = this.props clearInterval(this.timer) this.store.session.setAll({time, answer, recordId, elapsed}) history.push('/ai-test/submit') } render() { const {questions, activeQuestion, time, answer} = this.state 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> { !!time.d && <>{time.d}天</> } { !!time.h && <>{time.h && time.h.toString().padStart(2, '0')}:</> } {time.m.toString().padStart(2, '0')}: {time.s.toString().padStart(2, '0')} </span> </div> <div className="count" onClick={this.storeData}>{Object.values(answer).filter(item => item).length}/{questions.length}</div> </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 && <Question activeIndex={activeQuestion} question={questions[activeQuestion]} selectAnswer={this.selectAnswer} answer={answer}></Question> } </div> <Navigation questions={questions} answer={answer} handleClick={(index) => { this.setState({ activeQuestion: index, }); }}/> </div> ); } } export default connect( ({user}) => ({user}), null, )(Exam);