import React from 'react'; import { Link } from 'react-router-dom'; import './index.less'; import LineChart from '@src/components/LineChart'; import BarChart from '@src/components/BarChart'; import PieChart from '@src/components/PieChart'; import Assets from '@src/components/Assets'; import Page from '@src/containers/Page'; import { formatDate, formatPercent, formatSeconds, formatMinute, formatSecond, formatMinuteSecond, getMap } from '@src/services/Tools'; import { Icon, Tooltip } from 'antd'; import { Question } from '../../../stores/question'; import { Button } from '../../../components/Button'; import Tabs from '../../../components/Tabs'; import { Icon as GIcon } from '../../../components/Icon'; import { QuestionNoteModal } from '../../../components/OtherModal'; import { My } from '../../../stores/my'; import { QuestionDifficult, ExaminationQuestionType, ExaminationSubject, } from '../../../../Constant'; const QuestionDifficultMap = getMap(QuestionDifficult, 'value', 'label'); const QuestionDifficultSort = getMap(QuestionDifficult, 'value', 'sort'); function BarOption3(titles, source, data1, data2, color1, color2) { return { title: [ { text: titles[0], textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: 100, top: 15, }, { text: titles[1], textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: 195, top: 15, }, { text: titles[2], textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: 695, top: 15, }, ], grid: [{ width: 250, x: 200, bottom: 30 }, { width: 250, x: 700, bottom: 30 }], xAxis: [ { gridIndex: 0, show: false, axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, }, { gridIndex: 1, show: false, axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, }, ], yAxis: [ { gridIndex: 0, type: 'category', axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, offset: 15, data: source, axisLabel: { color: '#686872', fontSize: 16 }, }, { gridIndex: 1, type: 'category', axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, axisLabel: { show: false }, }, ], series: [ { type: 'bar', xAxisIndex: 0, yAxisIndex: 0, barWidth: 30, data: data1.map((item, index) => ({ value: item, itemStyle: { color: index % 2 ? color1[0] : color1[1] }, label: { show: true, color: '#303036', align: 'right', position: [360, 5], fontSize: 16, formatter: item, }, })), }, { type: 'bar', xAxisIndex: 1, yAxisIndex: 1, barWidth: 30, data: data2.map((item, index) => ({ value: item, itemStyle: { color: index % 2 ? color2[0] : color2[1] }, label: { show: true, color: '#303036', align: 'right', fontSize: 16, position: [360, 5], formatter: item, }, })), }, ], }; } function BarOption2(title, data, legend, color) { return { title: { text: title, textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, }, tooltip: { trigger: 'axis', }, legend: { show: legend.length > 1, data: legend, right: 20, }, color, dataset: { source: [['type', ...legend], ...data], }, grid: { left: 30, right: 30, height: 300 }, xAxis: { type: 'category', axisLabel: { color: '#686872' }, axisLine: { lineStyle: { color: '#D1D6DF' } }, }, yAxis: { type: 'value', min: 0, max: 100, axisLabel: { color: '#686872' }, axisLine: { lineStyle: { color: '#D1D6DF' } }, }, series: legend.map(() => ({ type: 'bar', barWidth: 40, })), }; } function lineOption1(title, data, legend, color) { return { title: { text: title, textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: '0', }, tooltip: { trigger: 'axis', }, legend: { show: legend.length > 1, data: legend, right: 20, }, color, grid: { left: 30, right: 30, height: 300 }, xAxis: { type: 'category', axisLabel: { color: '#686872' }, axisLine: { lineStyle: { color: '#D1D6DF' } }, }, yAxis: { type: 'value', min: 0, max: 100, axisLabel: { color: '#686872' }, axisLine: { lineStyle: { color: '#D1D6DF' } }, }, dataset: { source: [['type', ...legend], ...data], }, series: legend.map(() => ({ type: 'line', smooth: true, symbol: 'circle', })), }; } function barOption1(title, value, allValue, avgCorrect, avgIncorrent) { const xAxis1 = [ { gridIndex: 0, type: 'category', axisTick: { show: false }, axisLine: { lineStyle: { color: '#D1D6DF' } }, splitLine: { show: false }, }, { gridIndex: 1, type: 'category', axisTick: { show: false }, axisLine: { lineStyle: { color: '#D1D6DF' } }, splitLine: { show: false }, data: [ { value: 'Avg Time\nCorrect', textStyle: { color: '#686872', fontWeight: '500', fontSize: 14, lineHeight: 20 }, }, { value: 'Avg Time\nIncorrect', textStyle: { color: '#686872', fontWeight: '500', fontSize: 14, lineHeight: 20 }, }, ], }, ]; const xAxis2 = { type: 'category', axisTick: { show: false }, axisLine: { lineStyle: { color: '#D1D6DF' } }, splitLine: { show: false }, }; const yAxis1 = [ { gridIndex: 0, show: false, min: 0, max: 100, axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, }, { gridIndex: 1, show: false, min: 0, max: 100, axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, }, ]; const yAxis2 = { show: false, min: 0, max: 100, axisTick: { show: false }, axisLine: { show: false }, splitLine: { show: false }, }; const data1 = { type: 'bar', barWidth: 50, xAxisIndex: 0, yAxisIndex: 0, data: [ { value, itemStyle: { color: '#7AA7DC' }, label: { show: true, position: 'top', formatter: `{a|${value}}`, rich: { a: { fontSize: 16, fontWeight: 'bold', color: '#686872' } }, }, }, { value: allValue, itemStyle: { color: '#598FCF' }, label: { show: true, position: 'top', formatter: `{a|${allValue}}`, rich: { a: { fontSize: 12, color: '#686872' } }, }, }, ], }; const data2 = { type: 'bar', barWidth: 50, xAxisIndex: 1, yAxisIndex: 1, data: [ { value: avgCorrect, name: 'Avg Time\nCorrect', itemStyle: { color: '#7775CA' }, label: { show: true, position: 'top', formatter: `{a|${avgCorrect}}`, rich: { a: { fontSize: 16, fontWeight: 'bold', color: '#686872' } }, }, }, { value: avgIncorrent, name: 'Avg Time\nIncorrect', itemStyle: { color: '#9396C9' }, label: { show: true, position: 'top', formatter: `{a|${avgIncorrent}}`, rich: { a: { fontSize: 16, fontWeight: 'bold', color: '#686872' } }, }, }, ], }; return { title: [ { text: title, textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: '0', }, { text: 'Avg Time\nTotal', textAlign: 'center', textVerticalAlign: 'middle', textStyle: { color: '#686872', fontWeight: '500', fontSize: 14, lineHeight: 20 }, bottom: '2%', left: '26%', }, ], xAxis: avgCorrect ? xAxis1 : xAxis2, yAxis: avgCorrect ? yAxis1 : yAxis2, grid: avgCorrect ? [{ width: 200, x: 72 }, { width: 350, x: 272 }] : { width: 200, left: '30%' }, series: avgCorrect ? [data1, data2] : [data1], }; } function pieOption1(title, userCorrect, userNumber, totalCorrect, totalNumber) { const value = formatPercent(userCorrect, userNumber); const allValue = formatPercent(totalCorrect, totalNumber); return { title: [ { text: title, textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: '0', }, { text: `${value}%`, textAlign: 'center', textVerticalAlign: 'middle', textStyle: { color: value < 50 ? '#f19057' : '#7AA7DC', fontSize: 45 }, subtext: `${userCorrect}/${userNumber}`, subtextStyle: { color: '#686872', fontSize: 16 }, top: '35%', left: '49%', }, ], series: [ { type: 'pie', radius: ['64%', '70%'], label: { show: false, }, hoverAnimation: false, animation: false, data: [ { value: allValue, itemStyle: { color: '#7775CA' }, label: { show: true, position: 'outside', formatter: `{a|全站用户}:{b|${allValue}%}`, rich: { a: { color: '#686872', fontSize: 16, }, b: { color: '#6865FD', fontSize: 16, }, }, }, }, { value: 100 - allValue, itemStyle: { color: '#e1e1e1' }, emphasis: { itemStyle: { color: '#e1e1e1' } }, }, ], }, { type: 'pie', radius: ['45%', '61%'], label: { show: false, }, hoverAnimation: false, animation: false, data: [ { value, itemStyle: { color: value < 50 ? '#f19057' : '#7AA7DC' } }, { value: 100 - value, itemStyle: { color: '#e1e1e1' }, emphasis: { itemStyle: { color: '#e1e1e1' } } }, ], }, ], }; } function pieOption2(title, value1, value2, value3, total) { return { title: [ { text: title, textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' }, left: '0', }, { text: `${total}`, textAlign: 'center', textVerticalAlign: 'middle', textStyle: { color: '#686872', fontSize: 60 }, subtext: '综合实力', subtextStyle: { color: '#686872', fontSize: 14 }, top: '35%', left: '49.5%', }, ], series: [ { type: 'pie', radius: ['50%', '80%'], startAngle: 30, hoverAnimation: false, animation: false, data: [ { value: value1, itemStyle: { color: '#6865FD' }, label: { position: 'outside', formatter: `{a|逻辑关系} {b|${value1}}`, rich: { a: { color: '#686872', fontSize: 18, }, b: { color: '#6865FD', fontSize: 18, }, }, }, }, { value: value2, itemStyle: { color: '#6EC28D' }, label: { position: 'outside', formatter: `{a|句子结构} {b|${value2}}`, rich: { a: { color: '#686872', fontSize: 18, }, b: { color: '#6EC28D', fontSize: 18, }, }, }, }, { value: value3, itemStyle: { color: '#598FCF' }, label: { position: 'outside', formatter: `{a|阅读速度} {b|${value3}}`, rich: { a: { color: '#686872', fontSize: 18, }, b: { color: '#598FCF', fontSize: 18, }, }, }, }, ], }, ], }; } export default class extends Page { initState() { return { tab: 'main', report: { paperModule: '' } }; } initData() { const { id } = this.params; const { info = '' } = this.state.search; Question.detailReport(id).then(result => { switch (result.paperModule) { case 'sentence': this.refreshSentence(result); break; case 'textbook': this.refreshTextbook(result); break; case 'exercise': this.refreshExercise(result); break; case 'examination': this.refreshExamination(result); break; default: } this.setState({ report: result, paper: result.paper }); }); switch (info) { case 'question': // 题目回顾列表 Question.questionReport(id).then(result => { switch (result.paperModule) { case 'sentence': result = result.map((row) => { row.struct = row.detail.subject && row.detail.predicate && row.detail.object ? 0 : 1; row.logic = row.detail.options ? 0 : 1; row.note = row.note ? 1 : 0; row.collect = row.collect ? 1 : 0; return row; }); break; case 'textbook': case 'exercise': result = result.map((row) => { row.correct = row.isCorrect ? 0 : 1; row.diff = QuestionDifficultSort[row.question.difficult]; row.note = row.note ? 1 : 0; row.collect = row.collect ? 1 : 0; return row; }); this.refreshExercise(result); break; default: } this.setState({ list: result }); }); break; default: break; } } refreshSentence() { const { info = '' } = this.state.search; switch (info) { case 'question': break; default: } } refreshTextbook() { this.refreshExercise(); } refreshExamination() { const { info = '' } = this.state.search; switch (info) { case 'score': break; default: } } refreshExercise() { const { info = '' } = this.state.search; switch (info) { case 'question': break; default: } } questionSort(field) { let { order } = this.state; const { list = [] } = this.state; if (order === field) { order = 'no'; // direction = 'asc'; } else { order = field; // direction = 'desc'; } list.sort((a, b) => { const aValue = a[order]; const bValue = a[order]; if (aValue === bValue) { return a.no < b.no ? -1 : a.no > b.no ? 1 : 0; } return aValue > bValue ? -1 : 1; }); // if (direction === 'desc') { // list.reverse(); // } this.setState({ order, list }); } toggleCollect(index) { const { list } = this.state; const userQuestion = list[index]; if (!userQuestion.collect) { My.addQuestionCollect(userQuestion.questionNo.id).then(() => { userQuestion.collect = true; this.setState({ list }); }); } else { My.delQuestionCollect(userQuestion.questionNo.id).then(() => { userQuestion.collect = false; this.setState({ list }); }); } } note(index) { const { list } = this.state; const userQuestion = list[index]; const { questionNo } = userQuestion; My.getQuestionNote(questionNo.id) .then(result => { this.setState({ questionNo, note: result || {}, showNote: true, index }); }); } renderView() { const { report = {}, search = {} } = this.state; const { info } = search; switch (report.paperModule) { case 'sentence': if (info === 'question') { return this.renderSentenceQuestion(); } return this.renderSentence(); case 'textbook': if (info === 'question') { return this.renderExerciseQuestion(); } return this.renderTextbook(); case 'exercise': if (info === 'question') { return this.renderExerciseQuestion(); } return this.renderExercise(); case 'examination': return this.renderExamination(); default: return
; } } renderSentence() { const { paper = {}, report = {}, search = {} } = this.state; const { info } = search; const { user } = this.props; return (
Report for 「{report.paperModule === 'examination' ? '模考' : '练习'}」{paper.title}
{!info && } {info === 'question' && }
{user.info.nickname}
练习次数{paper.times + 1}
{formatDate(report.updateTime, 'YYYY-MM-DD HH:mm:ss')}
{info === 'question' && this.renderSentenceQuestion()} {!info && this.renderSentenceDetail()}
); } renderTextbook() { return this.renderExercise(); } renderExercise() { const { paper = {}, report = {}, search = {} } = this.state; const { info } = search; const { user } = this.props; return (
Report for「练习」{paper.title}
{!info && } {info === 'question' && }
{user.info.nickname}
练习次数{paper.times + 1}
{formatDate(report.updateTime, 'YYYY-MM-DD HH:mm:ss')}
{info === 'question' && this.renderExerciseQuestion()} {!info && this.renderExerciseDetail()}
); } renderExamination() { const { paper = {}, report = {}, search = {} } = this.state; const { info } = search; const { user } = this.props; return (
Report for 「{report.paperModule === 'examination' ? '模考' : '练习'}」{paper.title}
{!info && } {info === 'score' && }
{user.info.nickname}
练习次数{paper.times + 1}
{formatDate(report.updateTime, 'YYYY-MM-DD HH:mm:ss')}
{info === 'score' && this.renderExaminationScore()} {!info && this.renderExaminationDetail()}
); } renderSentenceQuestion() { const { report, list, order, showNote, note = {}, questionNo = {} } = this.state; return
题目回顾
点击题目查看详情
{(list || []).map((row, index) => { return ; })}
序号 题目 { this.questionSort('struct'); }}>句子结构 { this.questionSort('logic'); }}>逻辑关系 { this.questionSort('userTime'); }}>用时 { this.questionSort('collect'); }}>收藏 { this.questionSort('note'); }}>笔记
{row.no}
{row.questionNo.title}
{row.question.description}
{formatMinuteSecond(row.userTime)} this.toggleCollect(index)} /> this.note(index)} />
{ list[this.state.index].note = true; this.setState({ showNote: false, list }); }} onCancel={() => this.setState({ showNote: false })} />
; } renderSentenceDetail() { const { report = {} } = this.state; const { detail = {} } = report; return
完成情况
总耗时
{formatMinute(detail.info.userTime, true)}
min
{detail.info.userTime > detail.info.time &&
超出建议用时
{formatMinute(detail.info.userTime - detail.info.time, true)}
min
}
完成题目
{detail.info.userNumber}
{detail.info.userNumber !== detail.info.questionNumber &&
剩余未做
{detail.info.questionNumber || 0 - detail.info.userNumber}
}
基本情况
能力评估
; } renderExerciseQuestion() { const { report, list, order, showNote, note = {}, questionNo = {} } = this.state; return
题目回顾
点击题目查看详情
{(list || []).map((row, index) => { return ; })}
序号 题目 { this.questionSort('correct'); }}>正误 { this.questionSort('diff'); }}>难度 { this.questionSort('userTime'); }}>用时 { this.questionSort('place'); }}>主要考点 { this.questionSort('collect'); }}>收藏 { this.questionSort('note'); }}>笔记
{row.no}
{row.questionNo.title}
{row.question.description}
{row.question.difficult} {formatMinuteSecond(row.userTime)} {row.question.place} this.toggleCollect(index)} /> this.note(index)} />
{ list[this.state.index].note = true; this.setState({ showNote: false, list }); }} onCancel={() => this.setState({ showNote: false })} />
; } renderExerciseDetail() { const { report = {} } = this.state; let { detail = {} } = report; detail = detail || {}; const { pace = [], info = {}, difficult = [], place = [], limit = {} } = detail; return
完成情况
总耗时
{formatMinute(info.userTime, true)}
min
{info.userTime > info.time &&
超出建议用时
{formatMinute(info.userTime - info.time, true)}
min
}
完成题目
{info.userNumber}
{info.userNumber !== info.questionNumber &&
剩余未做
{info.questionNumber - info.userNumber}
}
基本情况
PACE
平均用时
$2
') }} />
全站用户
$2
') }} />
{ return [`${row.no}`, row.userTime, row.time]; }), ['我的', '全站'], ['#7AA7DC', '#8684df'], )} />
{report.paperModule !== 'textbook' &&
难度分析
正确率
{formatPercent(info.userCorrect, info.userNumber, false)}
全站用户
{formatPercent(info.totalCorrect, info.totalNumber, false)}
{ return [QuestionDifficultMap[row.key], formatPercent(row.userCorrect, row.userNumber), formatPercent(row.totalCorrect, row.totalNumber)]; }), ['我的', '全站'], ['#8684df', '#5195e5'], )} />
}
知识体系分析
平均用时
$2
') }} />
正确率
{formatPercent(info.userCorrect, info.userNumber, false)}
{ return row.key; }), place.map(row => { return formatPercent(row.userCorrect, row.userNumber); }), place.map(row => { return row.userTime / row.userNumber; }), ['#7AA7DC', '#BFD4EE'], ['#8684df', '#C3C3E5'], )} />
实战提醒
{info.userTime > info.time &&
在实战限时情况下,本套题正确率为
{formatPercent(limit.userCorrect, limit.userNumber)}
} {info.userTime <= info.time &&
目前的做题速度已达到实战标准!很棒!请继续保持!
}
; } renderTextbookQuestion() { return this.renderExerciseQuestion(); } renderExaminationDetail() { const { report = {}, tab } = this.state; const { detail = {} } = report; const { subject = {} } = detail; const subjectDetail = tab === 'main' ? null : (subject || {})[tab] || { info: {}, defficlt: [], place: [], pace: [] }; return
{ this.setState({ tab: value }); }} /> {!subjectDetail &&
完成情况
Verbal
Quant
IR
总耗时
{formatMinute((subject.verbal || {}).userTime, true)}
min
{formatMinute((subject.quant || {}).userTime, true)}
min
{formatMinute((subject.ir || {}).userTime, true)}
min
超出建议用时
{formatMinute((subject.verbal || {}).userTime - (subject.verbal || {}).time, true)}
min
{formatMinute((subject.quant || {}).userTime - (subject.quant || {}).time, true)}
min
{formatMinute((subject.ir || {}).userTime - (subject.ir || {}).time, true)}
min
完成题目
{(subject.verbal || {}).userNumber}
{(subject.quant || {}).userNumber}
{(subject.ir || {}).userNumber}
剩余未做
{(subject.verbal || {}).questionNumber - (subject.verbal || {}).userNumber}
{(subject.quant || {}).questionNumber - (subject.quant || {}).userNumber}
{(subject.ir || {}).questionNumber - (subject.ir || {}).userNumber}
} {subjectDetail &&
PACE
平均用时
$2
') }} />
{ return [`${row.no}`, row.userTime]; }), ['我的'], ['#A3A8BF'], )} />
{ userTime += row.userTime; time += row.time; return [`${row.no}`, userTime, time]; }); }(subjectDetail)), ['我的', '建议'], ['#A3A8BF', '#7AA7DC'], )} />
}
{!subjectDetail &&
成绩单
{ExaminationQuestionType.map(row => { const typeDetail = detail.type[row.value]; return ; })}
Question format Total Correct %Correct Avg Time Avg Time
Correct
Avg Time
Incorrect
Avg Diff
Correct
Avg Diff
Incorrect
{row.long} {typeDetail.info.questionNumber} {typeDetail.info.userCorrect} {formatPercent(typeDetail.info.userCorrect, typeDetail.info.userNumber)} {formatSecond(typeDetail.info.userTime / typeDetail.info.userNumber)} {formatSecond(typeDetail.info.correctTime / typeDetail.info.userCorrect)} {formatSecond(typeDetail.info.incorrectTime / typeDetail.info.userNumber - typeDetail.info.userCorrect)} {typeDetail.info.avgDiffCorrect} {typeDetail.info.avgDiffIncorrect}
} {subjectDetail &&
基本情况
%Correct Avg Time Avg Time
Correct
Avg Time
Incorrect
Avg Diff
Correct
Avg Diff
Incorrect
{formatPercent(subjectDetail.info.userCorrect, subjectDetail.info.userNumber)}
{subjectDetail.info.userCorrect}题/{subjectDetail.info.userNumber}题
{formatSecond(subjectDetail.info.userTime / subjectDetail.info.userNumber)}
{formatMinute(subjectDetail.info.userTime)}min/{subjectDetail.info.userNumber}题
{formatSecond(subjectDetail.info.correctTime / subjectDetail.info.userCorrect)}
{formatMinute(subjectDetail.info.correctTime)}min/{subjectDetail.info.userCorrect}题
{formatSecond(subjectDetail.info.incorrectTime / subjectDetail.info.userNumber - subjectDetail.info.userCorrect)}
{formatMinute(subjectDetail.info.incorrectTime)}min/{subjectDetail.info.userNumber}题
{subjectDetail.info.avgDiffCorrect} {subjectDetail.info.avgDiffIncorrect}
} {subjectDetail &&
难度分析
{ return [QuestionDifficultMap[row.key], formatPercent(row.userCorrect, row.userNumber)]; }), ['我的'], ['#989FC1'], )} />
} {subjectDetail &&
知识体系分析
{ return row.key; }), subjectDetail.place.map(row => { return formatPercent(row.userCorrect, row.userNumber); }), subjectDetail.place.map(row => { return row.userTime / row.userNumber; }), ['#92AFD2', '#BFD4EE'], ['#989FC1', '#CCCCDC'], )} />
}
; } renderExaminationScore() { const { report = {} } = this.state; const { score } = report; return
成绩单
{ExaminationSubject.map(row => { return ; })} ;
学科 分数 排名 题目
{row.long} {row.ignore ? '--' : score[`${row.value}Score`]} {row.ignore ? '--' : score[`${row.value}Rank`]}
Total {score.totalScore} {score.totalRank}
; } }