|
|
@@ -4,41 +4,41 @@
|
|
|
<template #header>
|
|
|
<page-header>
|
|
|
<template #actions>
|
|
|
- <el-button @click="fetchExamDetail" :loading="loading.refresh">
|
|
|
- <el-icon><RefreshRight /></el-icon>
|
|
|
- </el-button>
|
|
|
+ <!-- <el-button @clicxk="fetchExamDetail" :loading="loading.refresh">-->
|
|
|
+ <!-- <el-icon><RefreshRight /></el-icon>-->
|
|
|
+ <!-- </el-button>-->
|
|
|
<el-button
|
|
|
- v-if="isStudentGroup && !exam.joined"
|
|
|
- @click="dialog.join = true"
|
|
|
+ v-if="isStudentGroup && !exam.joined"
|
|
|
+ @click="dialog.join = true"
|
|
|
>
|
|
|
参加考试
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="(isStudentGroup && exam.joined) || (isTeacherGroup)"
|
|
|
- style="background-color: #1767C0;border-color:#1767C0;color:white;min-width: 100px;"
|
|
|
- @click="jumpToCoderOnlineExam"
|
|
|
+ v-if="(isStudentGroup && exam.joined) || (isTeacherGroup)"
|
|
|
+ type="primary"
|
|
|
+ @click="jumpToCoderOnlineExam"
|
|
|
>
|
|
|
在线自测
|
|
|
</el-button>
|
|
|
-<!-- <el-button-->
|
|
|
-<!-- v-if="isTeacherGroup || isAdmin || isAssistantGroup"-->
|
|
|
-<!-- style="background-color:white;border-color:white;color:#606266;min-width: 125px;box-shadow: #868484 0 2px 5px .1px"-->
|
|
|
-<!-- @click="checkStudentGrade"-->
|
|
|
-<!-- >-->
|
|
|
-<!-- 查看学生成绩-->
|
|
|
-<!-- </el-button>-->
|
|
|
+ <!-- <el-button-->
|
|
|
+ <!-- v-if="isTeacherGroup || isAdmin || isAssistantGroup"-->
|
|
|
+ <!-- style="background-color:white;border-color:white;color:#606266;min-width: 125px;box-shadow: #868484 0 2px 5px .1px"-->
|
|
|
+ <!-- @click="checkStudentGrade"-->
|
|
|
+ <!-- >-->
|
|
|
+ <!-- 查看学生成绩-->
|
|
|
+ <!-- </el-button>-->
|
|
|
<el-button
|
|
|
- v-if="isTeacherGroup || isAdmin"
|
|
|
- disabled
|
|
|
- style="background-color:white;color:#606266;min-width: 100px;"
|
|
|
- @click="goToDetect()"
|
|
|
+ v-if="isTeacherGroup || isAdmin"
|
|
|
+ disabled
|
|
|
+ style="background-color:white;color:#606266;min-width: 100px;"
|
|
|
+ @click="goToDetect()"
|
|
|
>
|
|
|
查看查重结果
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="isTeacherGroup || isAdmin"
|
|
|
- style="background-color:#F46C6C;border-color:#F46C6C;color:white;min-width: 100px;"
|
|
|
- @click="dialog.delete = true"
|
|
|
+ v-if="isTeacherGroup || isAdmin"
|
|
|
+ style="background-color:#F46C6C;border-color:#F46C6C;color:white;min-width: 100px;"
|
|
|
+ @click="dialog.delete = true"
|
|
|
>
|
|
|
删除考试
|
|
|
</el-button>
|
|
|
@@ -47,80 +47,87 @@
|
|
|
</page-header>
|
|
|
</template>
|
|
|
|
|
|
- <el-descriptions>
|
|
|
+ <el-descriptions class="exam-descrption">
|
|
|
<el-descriptions-item
|
|
|
- label="编号:"
|
|
|
- label-class-name="label-bold"
|
|
|
- min-width="200px"
|
|
|
+ label="编号:"
|
|
|
+ label-class-name="label-bold"
|
|
|
+ min-width="200px"
|
|
|
>
|
|
|
{{ exam.id }}
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item
|
|
|
- label="创建者:"
|
|
|
- label-class-name="label-bold"
|
|
|
- min-width="300px"
|
|
|
+ label="教师:"
|
|
|
+ label-class-name="label-bold"
|
|
|
+ min-width="300px"
|
|
|
>
|
|
|
- {{ exam.creator ? exam.creator.username : '' }}
|
|
|
+ {{ teacherName }}
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item
|
|
|
- label="状态:"
|
|
|
- label-class-name="label-bold"
|
|
|
+ label="课程:"
|
|
|
+ label-class-name="label-bold"
|
|
|
+ min-width="300px"
|
|
|
>
|
|
|
- <el-tag size="small" :type="statusTagType" round>
|
|
|
- {{ statusTagContent }}
|
|
|
- </el-tag>
|
|
|
+ {{ exam.course }}
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item
|
|
|
- v-if="(isStudentGroup || isTeacherGroup) && exam.joined"
|
|
|
- :label="`${isTeacherGroup ? '自测' : ''}成绩:`"
|
|
|
- label-class-name="label-bold"
|
|
|
+ label="状态:"
|
|
|
+ label-class-name="label-bold"
|
|
|
>
|
|
|
- {{ result.score }}
|
|
|
+ <el-tag size="small" :type="statusTagType" round>
|
|
|
+ {{ statusTagContent }}
|
|
|
+ </el-tag>
|
|
|
</el-descriptions-item>
|
|
|
+ <!-- <el-descriptions-item-->
|
|
|
+ <!-- v-if="(isStudentGroup || isTeacherGroup) && exam.joined"-->
|
|
|
+ <!-- :label="`${isTeacherGroup ? '自测' : ''}成绩:`"-->
|
|
|
+ <!-- label-class-name="label-bold"-->
|
|
|
+ <!-- >-->
|
|
|
+ <!-- {{ result.score }}-->
|
|
|
+ <!-- </el-descriptions-item>-->
|
|
|
<el-descriptions-item
|
|
|
- label="创建时间:"
|
|
|
- label-class-name="label-bold"
|
|
|
+ label="创建时间:"
|
|
|
+ label-class-name="label-bold"
|
|
|
>
|
|
|
{{ formatTimestamp(exam.created_at) }}
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item
|
|
|
- label="起止时间:"
|
|
|
- :span="2"
|
|
|
- label-class-name="label-bold"
|
|
|
+ label="起止时间:"
|
|
|
+ :span="2"
|
|
|
+ label-class-name="label-bold"
|
|
|
>
|
|
|
{{ formatTimestamp(exam.startAt) }} 至 {{ formatTimestamp(exam.endAt) }}
|
|
|
<a
|
|
|
- v-if="isTeacherGroup || isAdmin"
|
|
|
- class="changeable"
|
|
|
- @click="dialog.update = true"
|
|
|
+ v-if="isTeacherGroup || isAdmin"
|
|
|
+ class="changeable"
|
|
|
+ @click="dialog.update = true"
|
|
|
>
|
|
|
修改
|
|
|
</a>
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item
|
|
|
- v-if="(isStudentGroup && exam.joined) || isTeacherGroup"
|
|
|
- label="试卷地址:"
|
|
|
- :span="3"
|
|
|
- label-class-name="label-bold"
|
|
|
+ v-if="(isStudentGroup && exam.joined) || isTeacherGroup"
|
|
|
+ label="试卷地址:"
|
|
|
+ :span="3"
|
|
|
+ label-class-name="label-bold"
|
|
|
>
|
|
|
<span id="exam-url">
|
|
|
- {{ exam.url ? exam.url : '不可用' }}
|
|
|
+ {{ exam.url ? exam.url : "不可用" }}
|
|
|
</span>
|
|
|
<a
|
|
|
- v-if="exam.url"
|
|
|
- id="copy-btn"
|
|
|
- class="changeable"
|
|
|
- data-clipboard-target="#exam-url"
|
|
|
- @click="copyAddress"
|
|
|
+ v-if="exam.url"
|
|
|
+ id="copy-btn"
|
|
|
+ class="changeable"
|
|
|
+ data-clipboard-target="#exam-url"
|
|
|
+ @click="copyAddress"
|
|
|
>
|
|
|
复制
|
|
|
</a>
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item
|
|
|
- v-if="isTeacherGroup || isAdmin"
|
|
|
- label="是否允许学生查看控制台:"
|
|
|
- :span="2"
|
|
|
- label-class-name="label-bold"
|
|
|
+ v-if="isTeacherGroup || isAdmin"
|
|
|
+ label="是否允许学生查看控制台:"
|
|
|
+ :span="2"
|
|
|
+ label-class-name="label-bold"
|
|
|
>
|
|
|
<span>{{ isConsoleOutputShownForStu ? "允许" : "不允许" }}</span>
|
|
|
<a class="changeable" @click="dialog.console = true">
|
|
|
@@ -129,17 +136,18 @@
|
|
|
</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
|
|
|
-<!-- 题目列表-->
|
|
|
- <el-card class="son-card" style="background: none; box-shadow:none;border: none; margin-top: 15px;margin-bottom: 30px">
|
|
|
+ <!-- 题目列表-->
|
|
|
+ <el-card class="son-card"
|
|
|
+ style="background: none; box-shadow:none;border: none; margin-top: 15px;margin-bottom: 30px">
|
|
|
<template #header>
|
|
|
<span style="color:black;font-size: 24px;font-family: 'Inter',sans-serif">题目列表</span>
|
|
|
</template>
|
|
|
|
|
|
<el-collapse accordion>
|
|
|
<el-collapse-item
|
|
|
- v-for="problem in exam.problems"
|
|
|
- :key="problem.id"
|
|
|
- :name="problem.id"
|
|
|
+ v-for="problem in exam.problems"
|
|
|
+ :key="problem.id"
|
|
|
+ :name="problem.id"
|
|
|
>
|
|
|
<template #title>
|
|
|
<span style="margin-left: 20px;font-size: 16px;">{{ problem.name }}</span>
|
|
|
@@ -150,9 +158,9 @@
|
|
|
<div style="margin-left: 40px">{{ problem.description }}</div>
|
|
|
<div style="margin-left: 30px;margin-top: 10px">
|
|
|
<a
|
|
|
- v-if="isTeacherGroup || isAdmin"
|
|
|
- style="color: #409EFF;cursor: pointer;"
|
|
|
- @click="jumpToProblemDetail(problem.id)">
|
|
|
+ v-if="isTeacherGroup || isAdmin"
|
|
|
+ style="color: #409EFF;cursor: pointer;"
|
|
|
+ @click="jumpToProblemDetail(problem.id)">
|
|
|
预览
|
|
|
</a>
|
|
|
</div>
|
|
|
@@ -160,14 +168,14 @@
|
|
|
</el-collapse>
|
|
|
</el-card>
|
|
|
|
|
|
-<!-- 提交记录-->
|
|
|
+ <!-- 提交记录-->
|
|
|
<el-card class="son-card" style="background: none; box-shadow:none;border: none;margin-bottom: 30px">
|
|
|
<template #header>
|
|
|
<span style="color:black;font-size: 24px;font-family: 'Inter',sans-serif">提交记录</span>
|
|
|
</template>
|
|
|
|
|
|
<el-table v-if="exam.joined" :data="result.commits" style="background: none; box-shadow:none;border: none">
|
|
|
- <el-table-column prop="id" label="#" width="200" />
|
|
|
+ <el-table-column prop="id" label="#" width="200"/>
|
|
|
<el-table-column label="提交时间">
|
|
|
<template #default="scope">
|
|
|
<span>{{ formatTimestamp(scope.row.created_at) }}</span>
|
|
|
@@ -175,18 +183,18 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="状态" width="200">
|
|
|
<template #default="scope">
|
|
|
- <span>
|
|
|
- {{ scope.row.finished ? '运行结束' : '等待或运行中' }}
|
|
|
+ <span
|
|
|
+ :style="{color: + scope.row.finished ? $color.ElEMENT_COLOR.successColor : $color.ElEMENT_COLOR.primaryColor}">
|
|
|
+ {{ scope.row.finished ? "运行结束" : "等待或运行中" }}
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="score" label="成绩" width="150" />
|
|
|
+ <el-table-column prop="score" label="成绩" width="150"/>
|
|
|
<el-table-column label="操作" width="150">
|
|
|
<template #default="scope">
|
|
|
<el-button
|
|
|
- type="primary"
|
|
|
- size="mini"
|
|
|
- @click="
|
|
|
+ type="text"
|
|
|
+ @click="
|
|
|
$router.push(
|
|
|
{
|
|
|
path: `/exam/${$route.params.examId}/commit/${scope.row.id}`
|
|
|
@@ -200,27 +208,29 @@
|
|
|
</el-table>
|
|
|
</el-card>
|
|
|
|
|
|
-<!-- 结果列表-->
|
|
|
- <el-card class="son-card" style="background: none; box-shadow:none;border: none;margin-bottom: 30px" v-if="isTeacherGroup || isAdmin || isAssistantGroup">
|
|
|
+ <!-- 结果列表-->
|
|
|
+ <el-card class="son-card" style="background: none; box-shadow:none;border: none;margin-bottom: 30px"
|
|
|
+ v-if="isTeacherGroup || isAdmin || isAssistantGroup">
|
|
|
<template #header>
|
|
|
<page-header>
|
|
|
<template #actions>
|
|
|
<el-button
|
|
|
- @click="download"
|
|
|
- style="background-color: #1767C0;border-color:#1767C0;color:white;min-width: 100px;">
|
|
|
+ type="primary"
|
|
|
+ @click="download">
|
|
|
下载成绩单
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- @click="downloadDetailed"
|
|
|
- style="background-color: #1767C0;border-color:#1767C0;color:white;min-width: 100px;">
|
|
|
+ @click="downloadDetailed"
|
|
|
+ type="primary">
|
|
|
下载详细成绩单
|
|
|
</el-button>
|
|
|
</template>
|
|
|
- <span style="color:black;font-size: 24px;font-family: 'Inter',sans-serif;font-weight: normal;margin-top: 0;margin-bottom: 0">结果列表</span>
|
|
|
+ <span
|
|
|
+ style="color:black;font-size: 24px;font-family: 'Inter',sans-serif;font-weight: normal;margin-top: 0;margin-bottom: 0">结果列表</span>
|
|
|
</page-header>
|
|
|
</template>
|
|
|
<div style="margin-left: 20px">
|
|
|
- <echarts style="width: 100%" :options="chartOptions" />
|
|
|
+ <echarts style="width: 100%" :options="chartOptions"/>
|
|
|
<el-descriptions>
|
|
|
<el-descriptions-item label="总计人数:" label-class-name="label-bold">
|
|
|
{{ totalStudents }}
|
|
|
@@ -248,7 +258,7 @@
|
|
|
</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
<el-table :data="resultList" style="background: none; box-shadow:none;border: none">
|
|
|
- <el-table-column prop="id" label="#" width="200" />
|
|
|
+ <el-table-column prop="id" label="#" width="200"/>
|
|
|
<el-table-column label="用户名">
|
|
|
<template #default="scope">
|
|
|
<span>{{ scope.row.owner.username }}</span>
|
|
|
@@ -260,7 +270,7 @@
|
|
|
<span v-else>{{ formatTimestamp(scope.row.lastCommitAt) }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="score" label="成绩" width="200" />
|
|
|
+ <el-table-column prop="score" label="成绩" width="200"/>
|
|
|
<el-table-column label="操作" width="200">
|
|
|
<template #default="scope">
|
|
|
<el-button type="text" @click="jumpToCodemirror" disabled>源码</el-button>
|
|
|
@@ -275,10 +285,10 @@
|
|
|
|
|
|
<el-dialog title="确认删除考试吗?" v-model="dialog.delete">
|
|
|
<el-alert
|
|
|
- style="margin-bottom: 20px"
|
|
|
- title="注意:所有与该场考试有关的提交数据都将被删除!"
|
|
|
- type="error"
|
|
|
- :closable="false"
|
|
|
+ style="margin-bottom: 20px"
|
|
|
+ title="注意:所有与该场考试有关的提交数据都将被删除!"
|
|
|
+ type="error"
|
|
|
+ :closable="false"
|
|
|
></el-alert>
|
|
|
<el-descriptions>
|
|
|
<el-descriptions-item label="考试ID:">{{ exam.id }}</el-descriptions-item>
|
|
|
@@ -288,41 +298,42 @@
|
|
|
<template #footer class="dialog-footer">
|
|
|
<el-button @click="dialog.delete = false">取消</el-button>
|
|
|
<el-button
|
|
|
- type="danger"
|
|
|
- :loading="loading.delete"
|
|
|
- @click="deleteExam"
|
|
|
- >确定</el-button>
|
|
|
+ type="danger"
|
|
|
+ :loading="loading.delete"
|
|
|
+ @click="deleteExam"
|
|
|
+ >确定
|
|
|
+ </el-button>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
<el-dialog title="修改起止时间" v-model="dialog.update" width="960px">
|
|
|
+ <el-alert title="注意" type="warning" style="margin-bottom: 20px">
|
|
|
+ <p>开始时间早于当前时间考试将立即开始</p>
|
|
|
+ <p>开始时间晚于当前时间考试将回归未开始状态</p>
|
|
|
+ <p>结束时间早于当前时间考试将立即结束并关闭</p>
|
|
|
+ <p>考试关闭后将无法恢复</p>
|
|
|
+ </el-alert>
|
|
|
<el-descriptions>
|
|
|
<el-descriptions-item label="原起止时间:" :span="2">
|
|
|
{{ formatTimestamp(exam.startAt) }} 至 {{ formatTimestamp(exam.endAt) }}
|
|
|
</el-descriptions-item>
|
|
|
<el-descriptions-item label="新起止时间:" :span="2">
|
|
|
<el-date-picker
|
|
|
- v-model="range"
|
|
|
- type="datetimerange"
|
|
|
- range-separator="至"
|
|
|
- start-placeholder="开始时间"
|
|
|
- end-placeholder="结束时间"
|
|
|
+ v-model="range"
|
|
|
+ type="datetimerange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始时间"
|
|
|
+ end-placeholder="结束时间"
|
|
|
/>
|
|
|
</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
- <el-alert title="注意" type="warning" style="margin-top: 20px">
|
|
|
- <p>开始时间早于当前时间考试将立即开始</p>
|
|
|
- <p>开始时间晚于当前时间考试将回归未开始状态</p>
|
|
|
- <p>结束时间早于当前时间考试将立即结束并关闭</p>
|
|
|
- <p>考试关闭后将无法恢复</p>
|
|
|
- </el-alert>
|
|
|
|
|
|
<template #footer class="dialog-footer">
|
|
|
<el-button @click="dialog.update = false">取消</el-button>
|
|
|
<el-button
|
|
|
- variant="primary"
|
|
|
- :loading="loading.update"
|
|
|
- :disabled="range.length !== 2"
|
|
|
- @click="updateExam"
|
|
|
+ variant="primary"
|
|
|
+ :loading="loading.update"
|
|
|
+ :disabled="range.length !== 2"
|
|
|
+ @click="updateExam"
|
|
|
>
|
|
|
确定
|
|
|
</el-button>
|
|
|
@@ -332,14 +343,16 @@
|
|
|
<el-descriptions>
|
|
|
<el-descriptions-item label="考试ID:">{{ exam.id }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="考试名称:">{{ exam.name }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="当前控制台权限:">{{isConsoleOutputShownForStu?"":"不"}}允许学生查看控制台输出</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="当前控制台权限:">
|
|
|
+ {{ isConsoleOutputShownForStu ? "" : "不" }}允许学生查看控制台输出
|
|
|
+ </el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
<template #footer class="dialog-footer">
|
|
|
<el-button @click="dialog.console = false">取消</el-button>
|
|
|
<el-button
|
|
|
- variant="primary"
|
|
|
- :loading="loading.console"
|
|
|
- @click="changeShowConsoleForStu"
|
|
|
+ variant="primary"
|
|
|
+ :loading="loading.console"
|
|
|
+ @click="changeShowConsoleForStu"
|
|
|
>
|
|
|
确定
|
|
|
</el-button>
|
|
|
@@ -348,7 +361,7 @@
|
|
|
<el-dialog title="确认参加这场考试吗?" v-model="dialog.join">
|
|
|
<el-descriptions>
|
|
|
<el-descriptions-item label="考试名称">{{ exam.name }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="创建者">{{ exam.creator ? exam.creator.username : '' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="创建者">{{ exam.creator ? exam.creator.username : "" }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="起止时间" :span="2">
|
|
|
{{ formatTimestamp(exam.startAt) }} 至 {{ formatTimestamp(exam.endAt) }}
|
|
|
</el-descriptions-item>
|
|
|
@@ -364,7 +377,12 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import {examStatusToTagContent, examStatusToTagType, formatTimestamp, problemTypeToTagContent} from "@/utils/coder-utils";
|
|
|
+import {
|
|
|
+ examStatusToTagContent,
|
|
|
+ examStatusToTagType,
|
|
|
+ formatTimestamp,
|
|
|
+ problemTypeToTagContent
|
|
|
+} from "@/utils/coder-utils";
|
|
|
import {mapGetters} from "vuex";
|
|
|
import PageHeader from "../../components/PageHeader";
|
|
|
import Echarts from "@/views/ExamPage/ResultPage/Echarts.vue";
|
|
|
@@ -377,11 +395,10 @@ export default {
|
|
|
PageHeader,
|
|
|
Echarts
|
|
|
},
|
|
|
- props: {
|
|
|
- },
|
|
|
+ props: {},
|
|
|
data() {
|
|
|
return {
|
|
|
- exam: { joined: true },
|
|
|
+ exam: {joined: true},
|
|
|
result: {},
|
|
|
isConsoleOutputShownForStu: false,
|
|
|
|
|
|
@@ -436,7 +453,10 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
]
|
|
|
- }
|
|
|
+ },
|
|
|
+
|
|
|
+ // name, not username 门户统一使用name而非username
|
|
|
+ teacherName: "",
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -446,27 +466,27 @@ export default {
|
|
|
"isAdmin",
|
|
|
"isAssistantGroup"
|
|
|
]),
|
|
|
- statusTagType(){
|
|
|
+ statusTagType() {
|
|
|
return examStatusToTagType(this.exam.status);
|
|
|
},
|
|
|
- statusTagContent(){
|
|
|
+ statusTagContent() {
|
|
|
return examStatusToTagContent(this.exam.status);
|
|
|
},
|
|
|
joinDisabled() {
|
|
|
return (
|
|
|
- this.exam.status === "UNAVAILABLE" ||
|
|
|
- this.exam.status === "FINISHED" ||
|
|
|
- this.exam.status === "CLOSED"
|
|
|
+ this.exam.status === "UNAVAILABLE" ||
|
|
|
+ this.exam.status === "FINISHED" ||
|
|
|
+ this.exam.status === "CLOSED"
|
|
|
);
|
|
|
},
|
|
|
tabValue() {
|
|
|
- return this.exam.joined? "commits": "problems";
|
|
|
+ return this.exam.joined ? "commits" : "problems";
|
|
|
},
|
|
|
//结果列表的统计数据
|
|
|
summary() {
|
|
|
return this.resultList
|
|
|
- .map((result) => result.score)
|
|
|
- .reduce((a = 0, b = 0) => a + b, 0) ?? 0;
|
|
|
+ .map((result) => result.score)
|
|
|
+ .reduce((a = 0, b = 0) => a + b, 0) ?? 0;
|
|
|
},
|
|
|
totalStudents() {
|
|
|
return this.resultList.length;
|
|
|
@@ -476,40 +496,43 @@ export default {
|
|
|
},
|
|
|
committedStudents() { //该同学有提交历史就算有效提交
|
|
|
return this.resultList
|
|
|
- .map(result => result.lastCommitAt ? 1 : 0)
|
|
|
- .reduce((a, b) => a + b, 0);
|
|
|
+ .map(result => result.lastCommitAt ? 1 : 0)
|
|
|
+ .reduce((a, b) => a + b, 0);
|
|
|
},
|
|
|
committedAverage() { //注意:无效提交成绩为0
|
|
|
return (this.summary / Math.max(this.committedStudents, 1)).toFixed(2);
|
|
|
},
|
|
|
fullScoreStudents() {
|
|
|
return this.resultList
|
|
|
- .map(result => result.score === 100)
|
|
|
- .reduce((a, b) => a + b, 0);
|
|
|
+ .map(result => result.score === 100)
|
|
|
+ .reduce((a, b) => a + b, 0);
|
|
|
},
|
|
|
fullScoreRatio() {
|
|
|
return (
|
|
|
- (
|
|
|
- (this.fullScoreStudents * 100) /
|
|
|
- Math.max(this.committedStudents, 1)
|
|
|
- ).toFixed(2) + "%"
|
|
|
+ (
|
|
|
+ (this.fullScoreStudents * 100) /
|
|
|
+ Math.max(this.committedStudents, 1)
|
|
|
+ ).toFixed(2) + "%"
|
|
|
);
|
|
|
},
|
|
|
passedStudents() { //
|
|
|
return this.resultList
|
|
|
- .map(result => result?.score ?? 0 >= 60)
|
|
|
- .reduce((a, b) => a + b, 0);
|
|
|
+ .map(result => result?.score ?? 0 >= 60)
|
|
|
+ .reduce((a, b) => a + b, 0);
|
|
|
},
|
|
|
passedRatio() {
|
|
|
return (
|
|
|
- (
|
|
|
- this.passedStudents / Math.max(this.committedStudents, 1)
|
|
|
- ).toFixed(2) + "%"
|
|
|
+ (
|
|
|
+ this.passedStudents / Math.max(this.committedStudents, 1)
|
|
|
+ ).toFixed(2) + "%"
|
|
|
);
|
|
|
- }
|
|
|
+ },
|
|
|
},
|
|
|
- mounted() {
|
|
|
- this.fetchExamDetail();
|
|
|
+ async mounted() {
|
|
|
+ await this.fetchExamDetail();
|
|
|
+ if (this.exam.creator) {
|
|
|
+ this.teacherName = (await this.$apis.getNameByUsernameAPI(this.exam.creator.username)).data.data;
|
|
|
+ }
|
|
|
},
|
|
|
methods: {
|
|
|
/**
|
|
|
@@ -518,48 +541,47 @@ export default {
|
|
|
this.loading.refresh = true;
|
|
|
const {examId} = this.$route.params;
|
|
|
await this.$apis.getCoderExamByExamId(examId)
|
|
|
+ .then(_res => {
|
|
|
+ this.exam = _res.data.res;
|
|
|
+ if (!this.isAdmin && this.exam.joined) {
|
|
|
+ this.fetchResult();
|
|
|
+ }
|
|
|
+ }).catch(_err => {
|
|
|
+ ElMessage.error("当前考试不存在!跳转到管理页面!");
|
|
|
+ this.$router.push("/manage");
|
|
|
+ });
|
|
|
+ if (this.isTeacherGroup) {
|
|
|
+ await this.$apis.getExamIsShownForStu(examId)
|
|
|
.then(_res => {
|
|
|
- this.exam = _res.data.res;
|
|
|
- if (!this.isAdmin && this.exam.joined) {
|
|
|
- this.fetchResult();
|
|
|
- }
|
|
|
+ this.isConsoleOutputShownForStu = _res.data.res ?? false;
|
|
|
+ this.loading.refresh = false;
|
|
|
}).catch(_err => {
|
|
|
- ElMessage.error("当前考试不存在!跳转到管理页面!");
|
|
|
- this.$router.push("/manage");
|
|
|
+ ElMessage.error(_err);
|
|
|
});
|
|
|
- if (this.isTeacherGroup) {
|
|
|
- await this.$apis.getExamIsShownForStu(examId)
|
|
|
- .then(_res => {
|
|
|
- this.isConsoleOutputShownForStu = _res.data.res ?? false;
|
|
|
- this.loading.refresh = false;
|
|
|
- }).catch(_err => {
|
|
|
- ElMessage.error(_err);
|
|
|
- });
|
|
|
await this.$apis.getCoderResultByExamId(examId)
|
|
|
- .then(_res => {
|
|
|
- this.resultList = _res.data.res ?? [];
|
|
|
- console.log(this.resultList);
|
|
|
- //下面是两步操作
|
|
|
- //1 按照分数段分类
|
|
|
- //2 根据分数段,获取每个分数段的人数(返回数组)
|
|
|
- this.chartOptions.series[0].data = this.resultList.map(
|
|
|
- result => (result.lastCommitAt ? Math.floor((result.score ?? 0) / 10) : -1) + 1
|
|
|
- ).reduce((a, b) => {
|
|
|
- a[b]++;
|
|
|
- return a;
|
|
|
- }, new Array(12).fill(0));
|
|
|
- }).catch(_err => {
|
|
|
- ElMessage.error(_err);
|
|
|
- });
|
|
|
+ .then(_res => {
|
|
|
+ this.resultList = _res.data.res ?? [];
|
|
|
+ //下面是两步操作
|
|
|
+ //1 按照分数段分类
|
|
|
+ //2 根据分数段,获取每个分数段的人数(返回数组)
|
|
|
+ this.chartOptions.series[0].data = this.resultList.map(
|
|
|
+ result => (result.lastCommitAt ? Math.floor((result.score ?? 0) / 10) : -1) + 1
|
|
|
+ ).reduce((a, b) => {
|
|
|
+ a[b]++;
|
|
|
+ return a;
|
|
|
+ }, new Array(12).fill(0));
|
|
|
+ }).catch(_err => {
|
|
|
+ ElMessage.error(_err);
|
|
|
+ });
|
|
|
}
|
|
|
this.loading.refresh = false;
|
|
|
},
|
|
|
fetchResult() {
|
|
|
this.$apis.getResultByResultId(this.exam.result?.id)
|
|
|
- .then(_res => {
|
|
|
- this.result = _res.data.res ?? {};
|
|
|
- }).catch(_err => {
|
|
|
- ElMessage.error(_err);
|
|
|
+ .then(_res => {
|
|
|
+ this.result = _res.data.res ?? {};
|
|
|
+ }).catch(_err => {
|
|
|
+ ElMessage.error(_err);
|
|
|
});
|
|
|
},
|
|
|
formatTimestamp,
|
|
|
@@ -574,17 +596,17 @@ export default {
|
|
|
// ElMessage.error("暂不支持查看查重结果");
|
|
|
},
|
|
|
checkStudentGrade() {
|
|
|
- this.$router.push(this.$route.path+"/result");
|
|
|
+ this.$router.push(this.$route.path + "/result");
|
|
|
},
|
|
|
deleteExam() {
|
|
|
this.loading.delete = true;
|
|
|
- const { examId } = this.$route.params;
|
|
|
+ const {examId} = this.$route.params;
|
|
|
this.$apis.deleteCoderExam(examId)
|
|
|
- .then(_res => {
|
|
|
- ElMessage.success("删除考试成功");
|
|
|
- this.dialog.delete = false;
|
|
|
- this.$router.push("/manage");
|
|
|
- }).catch(_err => {
|
|
|
+ .then(_res => {
|
|
|
+ ElMessage.success("删除考试成功");
|
|
|
+ this.dialog.delete = false;
|
|
|
+ this.$router.push("/manage");
|
|
|
+ }).catch(_err => {
|
|
|
ElMessage.error("删除考试失败");
|
|
|
}).finally(() => {
|
|
|
this.loading.delete = false;
|
|
|
@@ -592,7 +614,7 @@ export default {
|
|
|
},
|
|
|
updateExam() {
|
|
|
this.loading.update = true;
|
|
|
- const { examId } = this.$route.params;
|
|
|
+ const {examId} = this.$route.params;
|
|
|
|
|
|
this.$apis.updateCoderExam(examId, {
|
|
|
course: this.exam.courseId,
|
|
|
@@ -635,14 +657,14 @@ export default {
|
|
|
},
|
|
|
changeShowConsoleForStu() {
|
|
|
this.loading.console = true;
|
|
|
- const { examId } = this.$route.params;
|
|
|
+ const {examId} = this.$route.params;
|
|
|
const showConsoleForStu = !this.isConsoleOutputShownForStu;
|
|
|
|
|
|
this.$apis.changeExamIsShownForStu(examId, showConsoleForStu)
|
|
|
- .then(_res => {
|
|
|
- this.isConsoleOutputShownForStu = _res.data.res ?? false;
|
|
|
- ElMessage.success("修改控制台权限成功!");
|
|
|
- }).catch(_err => {
|
|
|
+ .then(_res => {
|
|
|
+ this.isConsoleOutputShownForStu = _res.data.res ?? false;
|
|
|
+ ElMessage.success("修改控制台权限成功!");
|
|
|
+ }).catch(_err => {
|
|
|
console.log(_err);
|
|
|
ElMessage.success("修改控制台权限失败!");
|
|
|
}).finally(() => {
|
|
|
@@ -650,19 +672,19 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
jumpToProblemDetail(problemId) {
|
|
|
- this.$router.push("/problem/"+problemId);
|
|
|
+ this.$router.push("/problem/" + problemId);
|
|
|
},
|
|
|
joinExam() {
|
|
|
this.loading.join = true;
|
|
|
this.$apis.joinCoderExam(this.exam.id)
|
|
|
- .then(_res => {
|
|
|
- this.$message.success({
|
|
|
- message: "参加考试成功!",
|
|
|
- center: true
|
|
|
- });
|
|
|
- console.log("参加考试接口返回信息", _res);
|
|
|
- this.fetchExamDetail();
|
|
|
- }).catch(_err => {
|
|
|
+ .then(_res => {
|
|
|
+ this.$message.success({
|
|
|
+ message: "参加考试成功!",
|
|
|
+ center: true
|
|
|
+ });
|
|
|
+ console.log("参加考试接口返回信息", _res);
|
|
|
+ this.fetchExamDetail();
|
|
|
+ }).catch(_err => {
|
|
|
this.$message.error({
|
|
|
message: "参加考试出错!",
|
|
|
center: true
|
|
|
@@ -675,12 +697,12 @@ export default {
|
|
|
//TODO 下载考试成绩的认证过程,信息安全问题
|
|
|
//下载考试成绩单
|
|
|
download() {
|
|
|
- const { examId } = this.$route.params;
|
|
|
+ const {examId} = this.$route.params;
|
|
|
window.open(`https://coder.seec.seecoder.cn/api/file/result/${examId}`);
|
|
|
},
|
|
|
//下载考试详细成绩单
|
|
|
downloadDetailed() {
|
|
|
- const { examId } = this.$nuxt.$route.params;
|
|
|
+ const {examId} = this.$route.params;
|
|
|
window.open(`https://coder.seec.seecoder.cn/api/file/result/${examId}/detailed`);
|
|
|
},
|
|
|
//查看提交代码
|
|
|
@@ -699,13 +721,14 @@ export default {
|
|
|
margin: 40px 10vw 80px 10vw;
|
|
|
min-height: calc(100vh - 100px);
|
|
|
}
|
|
|
+
|
|
|
.changeable {
|
|
|
color: #409EFF;
|
|
|
cursor: pointer;
|
|
|
margin-left: 20px;
|
|
|
}
|
|
|
|
|
|
-::v-deep .el-card__header {
|
|
|
+::v-deep .el-card__header {
|
|
|
border-bottom: 1px solid black;
|
|
|
}
|
|
|
|
|
|
@@ -714,9 +737,9 @@ export default {
|
|
|
padding-bottom: 0;
|
|
|
}
|
|
|
|
|
|
-::v-deep .el-descriptions__body {
|
|
|
+::v-deep .el-descriptions__body .exam-descrption{
|
|
|
font-size: 16px;
|
|
|
- background-color: #F8F9FB; //样式穿透,覆盖原本的样式
|
|
|
+ background-color: #F8F9FB; //样式穿透,覆盖原本的样式
|
|
|
}
|
|
|
|
|
|
::v-deep .label-bold {
|