2025-08-07 17:44:13 +08:00

275 lines
7.4 KiB
Vue

<template>
<!-- 刷题统计 -->
<view class="single_box exercise_statistics">
<view class="title">刷题统计</view>
<isp-data-load :loading="loading" :empty="empty" emptyText="暂无数据">
<view class="date_filter_box">
<DateFilter :dateType="dateType" @filter="i => handleFilterDate(i)" />
</view>
<view class="study_situation2">
<view class="item">
<text class="item_label">做题数</text>
<view
:class="{
item_date: true,
up: showData.totalNum > showData.totalRatioNum,
down: showData.totalNum < showData.totalRatioNum,
keep: showData.totalNum === showData.totalRatioNum,
}"
>
{{ showData.totalNum }}<text style="color: #333">&nbsp;</text>
<image
class="trend_icon"
:src="
showData.totalNum > showData.totalRatioNum
? `${OSS_URL}/iconfont/learning_progress_${1}.png`
: showData.totalNum === showData.totalRatioNum
? `${OSS_URL}/iconfont/learning_progress_${2}.png`
: `${OSS_URL}/iconfont/learning_progress_${3}.png`
"
/>
</view>
</view>
<view class="item">
<text class="item_label">产生错题数</text>
<view
:class="{
item_date: true,
up: showData.errorNum > showData.errorRatioNum,
down: showData.errorNum < showData.errorRatioNum,
keep: showData.errorNum === showData.errorRatioNum,
}"
>
{{ showData.errorNum }}<text style="color: #333">&nbsp;</text>
<image
class="trend_icon"
:src="
showData.errorNum > showData.errorRatioNum
? `${OSS_URL}/iconfont/learning_progress_${1}.png`
: showData.errorNum === showData.errorRatioNum
? `${OSS_URL}/iconfont/learning_progress_${2}.png`
: `${OSS_URL}/iconfont/learning_progress_${3}.png`
"
/>
</view>
</view>
<view class="item">
<text class="item_label">订正错题数</text>
<view
:class="{
item_date: true,
up: showData.correctedNum > showData.correctedRatioNum,
down: showData.correctedNum < showData.correctedRatioNum,
keep: showData.correctedNum === showData.correctedRatioNum,
}"
>
{{ showData.correctedNum }}<text style="color: #333">&nbsp;</text>
<image
class="trend_icon"
:src="
showData.correctedNum > showData.correctedRatioNum
? `${OSS_URL}/iconfont/learning_progress_${1}.png`
: showData.correctedNum === showData.correctedRatioNum
? `${OSS_URL}/iconfont/learning_progress_${2}.png`
: `${OSS_URL}/iconfont/learning_progress_${3}.png`
"
/>
</view>
</view>
</view>
<RingChart
:chartData="ringDate"
:showLegend="false"
:subtitle="showData.correctRate"
title="答题正确率"
/>
<template v-if="dateType !== 0">
<view class="title2">答题记录</view>
<view class="charts-box">
<qiun-data-charts
type="line"
canvas2d
:opts="opts"
:chartData="exerciseStatistics"
ontouch
tooltip-format="tooltipExer"
/>
</view>
</template>
</isp-data-load>
</view>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, watch } from 'vue';
import DateFilter from './dateFilter.vue';
import RingChart from './Echart/RingChart.vue';
import dayjs from 'dayjs';
import '../index.scss';
import { studyErrorStatApi } from '@/api';
const props = withDefaults(
defineProps<{
subjectId: number | string;
userId: string;
}>(),
{
subjectId: 0,
userId: '',
},
);
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const empty = ref(false);
const opts = ref({
padding: [15, 20, 0, 15],
enableScroll: false,
dataLabel: false,
dataPointShape: false,
legend: { position: 'top', padding: 2 },
xAxis: {
disableGrid: true,
labelCount: 3, // 标签数
format: 'xAixsHoursMin',
},
yAxis: {
gridType: 'dash',
dashLength: 2,
calibration: true,
},
extra: {
line: {
type: 'curve',
width: 2,
activeType: 'none',
},
tooltip: {
bgColor: '#21D17A',
fontColor: '#fff',
bgOpacity: 1,
borderRadius: 8,
gridColor: '#21D17A',
labelFontColor: '#333',
legendShow: false,
borderOpacity: 1,
labelBgOpacity: 1,
},
},
});
const loading = ref(false);
const dateType = ref(0);
const showData = ref({
correctRate: '',
correctedNum: 0,
correctedRatioNum: 0,
errorNum: 0,
errorRatioNum: 0,
recordVoList: [
{
correctRate: 0,
correctedErrors: 0,
studyDate: '',
totalErrors: 0,
totalQuestions: 0,
},
],
totalNum: 0,
totalRatioNum: 0,
});
// 刷题统计
const ringDate = ref({
series: [
{
data: [],
},
],
});
const exerciseStatistics = ref({
categories: [],
series: [
{
name: '做题数',
data: [],
color: '#9789ff',
},
{
name: '产生错题数',
data: [],
color: 'rgba(255, 168, 161, 1)',
},
{ name: '订正错题数', data: [], color: 'rgba(60, 195, 223, 1)' },
],
});
async function fetchChartData() {
if (props.subjectId === 0) {
empty.value = true;
return;
}
empty.value = false;
try {
loading.value = true;
const data = await studyErrorStatApi({
dateType: dateType.value,
subjectId: props.subjectId,
userId: props.userId,
});
showData.value = data;
ringDate.value.series[0].data = [
{
name: '',
value: showData.value.totalNum - showData.value.errorNum,
color: '#7e6eff',
labelShow: false,
},
{
name: '',
value:
showData.value.totalNum - showData.value.errorNum === 0 ? 100 : showData.value.errorNum,
color: '#e2e2e2',
labelShow: false,
},
];
exerciseStatistics.value.categories = [];
for (let i in data.recordVoList) {
exerciseStatistics.value.categories[i] = dayjs(data.recordVoList[i].studyDate).format(
'YYYY/MM/DD',
);
exerciseStatistics.value.series = [
{
name: '做题数',
data: showData.value.recordVoList.map(item => item.totalQuestions),
color: '#9789ff',
},
{
name: '产生错题数',
data: showData.value.recordVoList.map(item => item.totalErrors),
color: 'rgba(255, 168, 161, 1)',
},
{
name: '订正错题数',
data: showData.value.recordVoList.map(item => item.correctedErrors),
color: 'rgba(60, 195, 223, 1)',
},
];
}
} finally {
loading.value = false;
}
}
function handleFilterDate(i) {
dateType.value = i.value;
fetchChartData();
}
watch(
() => props.subjectId,
val => {
dateType.value = 0;
fetchChartData();
},
);
</script>
<style lang="scss" scoped>
.title2 {
margin-bottom: -20rpx !important;
}
</style>