|
@@ -0,0 +1,117 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { onlinePracticeRecordListApi } from "@/api/onlinePractice";
|
|
|
+import { OnlinePracticeRecord } from "@/types/student-client";
|
|
|
+import moment from "moment";
|
|
|
+import { onMounted } from "vue";
|
|
|
+import { useRoute, useRouter } from "vue-router";
|
|
|
+
|
|
|
+const route = useRoute();
|
|
|
+const router = useRouter();
|
|
|
+const examName = decodeURIComponent(route.query.examName as string);
|
|
|
+const courseName = decodeURIComponent(route.query.courseName as string);
|
|
|
+let maxAccuracy: string = $ref("0");
|
|
|
+let aveAccuracy: string = $ref("0");
|
|
|
+let recordList = $ref<OnlinePracticeRecord[]>([]);
|
|
|
+async function getRecordList() {
|
|
|
+ if (!route.query.examStudentId) return;
|
|
|
+ const res = await onlinePracticeRecordListApi(
|
|
|
+ route.query.examStudentId as string
|
|
|
+ );
|
|
|
+ recordList = res.data || [];
|
|
|
+ recordList.reverse();
|
|
|
+}
|
|
|
+function getRecordInfo() {
|
|
|
+ if (!recordList.length) return;
|
|
|
+ maxAccuracy = Math.max(...recordList.map((v) => v.objectiveAccuracy)).toFixed(
|
|
|
+ 2
|
|
|
+ );
|
|
|
+
|
|
|
+ aveAccuracy = (
|
|
|
+ recordList.map((v) => v.objectiveAccuracy).reduce((a, b) => a + b) /
|
|
|
+ recordList.length
|
|
|
+ ).toFixed(2);
|
|
|
+}
|
|
|
+function formatTime(ms: number) {
|
|
|
+ return ms ? moment.utc(ms).format("HH:mm:ss") : "";
|
|
|
+}
|
|
|
+
|
|
|
+function toPracticeRecordDetail(record: OnlinePracticeRecord) {
|
|
|
+ void router.push({
|
|
|
+ name: "OnlinePracticeRecordDetail",
|
|
|
+ params: {
|
|
|
+ examId: route.params.examId,
|
|
|
+ examRecordDataId: record.id,
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ await getRecordList();
|
|
|
+ getRecordInfo();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="record-head">
|
|
|
+ <p>批次:{{ examName }}</p>
|
|
|
+ <p>科目:{{ courseName }}</p>
|
|
|
+ <p>平均正确率:{{ aveAccuracy }}%</p>
|
|
|
+ <p>最高正确率:{{ maxAccuracy }}%</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <n-table class="n-table-text-center" :singleLine="false">
|
|
|
+ <colgroup>
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col />
|
|
|
+ <col width="120px" />
|
|
|
+ </colgroup>
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <th>练习编号</th>
|
|
|
+ <th>开始日期</th>
|
|
|
+ <th>结束日期</th>
|
|
|
+ <th>练习时长</th>
|
|
|
+ <th>总题量</th>
|
|
|
+ <th>正确</th>
|
|
|
+ <th>错误</th>
|
|
|
+ <th>未答</th>
|
|
|
+ <th>正确率</th>
|
|
|
+ <th>操作</th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <tr v-for="record in recordList" :key="record.id">
|
|
|
+ <td>{{ record.id }}</td>
|
|
|
+ <td>{{ record.startTime }}</td>
|
|
|
+ <td>{{ record.endTime }}</td>
|
|
|
+ <td>{{ formatTime(record.usedExamTime) }}</td>
|
|
|
+ <td>{{ record.totalQuestionCount }}</td>
|
|
|
+ <td>{{ record.succQuestionNum }}</td>
|
|
|
+ <td>{{ record.failQuestionNum }}</td>
|
|
|
+ <td>{{ record.notAnsweredCount }}</td>
|
|
|
+ <td>{{ record.objectiveAccuracy }}%</td>
|
|
|
+ <td>
|
|
|
+ <n-button type="success" block @click="toPracticeRecordDetail(record)"
|
|
|
+ >查看成绩报告</n-button
|
|
|
+ >
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </n-table>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.record-head {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ align-items: baseline;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+</style>
|