|
|
|
@ -21,10 +21,16 @@
|
|
|
|
<section class="score-visual" aria-label="模块成绩分布">
|
|
|
|
<section class="score-visual" aria-label="模块成绩分布">
|
|
|
|
<div ref="scoreChartRef" class="score-chart"></div>
|
|
|
|
<div ref="scoreChartRef" class="score-chart"></div>
|
|
|
|
<div class="score-summary">
|
|
|
|
<div class="score-summary">
|
|
|
|
<span class="summary-label">综合成绩</span>
|
|
|
|
<div class="score-metric score-metric--ai">
|
|
|
|
<strong>{{ formatScore(report.totalScore) }}</strong>
|
|
|
|
<span class="summary-label">AI评分</span>
|
|
|
|
<span class="summary-unit">分</span>
|
|
|
|
<strong>{{ formatScore(aiScore) }}</strong>
|
|
|
|
<span class="rank-copy">当前排名:--</span>
|
|
|
|
<span class="summary-unit">分</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="score-metric score-metric--teacher">
|
|
|
|
|
|
|
|
<span class="summary-label">老师评分</span>
|
|
|
|
|
|
|
|
<strong>{{ formatTeacherScore(teacherScore) }}</strong>
|
|
|
|
|
|
|
|
<span v-if="hasTeacherScore(teacherScore)" class="summary-unit">分</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
@ -107,6 +113,8 @@ let scoreChart;
|
|
|
|
let progressChart;
|
|
|
|
let progressChart;
|
|
|
|
|
|
|
|
|
|
|
|
const displayModules = computed(() => report.value.modules || []);
|
|
|
|
const displayModules = computed(() => report.value.modules || []);
|
|
|
|
|
|
|
|
const aiScore = computed(() => report.value.aiAssessmentScore ?? report.value.aiScore ?? report.value.totalScore);
|
|
|
|
|
|
|
|
const teacherScore = computed(() => report.value.teacherScore);
|
|
|
|
|
|
|
|
|
|
|
|
const totalStudyMinutes = computed(() =>
|
|
|
|
const totalStudyMinutes = computed(() =>
|
|
|
|
Object.values(studyTime.value || {}).reduce((total, value) => total + (Number(value) || 0), 0)
|
|
|
|
Object.values(studyTime.value || {}).reduce((total, value) => total + (Number(value) || 0), 0)
|
|
|
|
@ -115,6 +123,8 @@ const totalStudyMinutes = computed(() =>
|
|
|
|
const studyHours = computed(() => (totalStudyMinutes.value / 60).toFixed(1));
|
|
|
|
const studyHours = computed(() => (totalStudyMinutes.value / 60).toFixed(1));
|
|
|
|
|
|
|
|
|
|
|
|
const formatScore = (value) => Number(value || 0).toFixed(2).replace(/\.00$/, "");
|
|
|
|
const formatScore = (value) => Number(value || 0).toFixed(2).replace(/\.00$/, "");
|
|
|
|
|
|
|
|
const hasTeacherScore = (value) => value !== null && value !== undefined && value !== "";
|
|
|
|
|
|
|
|
const formatTeacherScore = (value) => hasTeacherScore(value) ? formatScore(value) : "待评阅";
|
|
|
|
const formatWeight = (weight) => `${(Number(weight || 0) * 100).toFixed(0)}%`;
|
|
|
|
const formatWeight = (weight) => `${(Number(weight || 0) * 100).toFixed(0)}%`;
|
|
|
|
const moduleColor = (index) => MODULE_COLORS[index % MODULE_COLORS.length];
|
|
|
|
const moduleColor = (index) => MODULE_COLORS[index % MODULE_COLORS.length];
|
|
|
|
const progressPercent = (module) => {
|
|
|
|
const progressPercent = (module) => {
|
|
|
|
@ -269,15 +279,20 @@ onBeforeUnmount(() => {
|
|
|
|
left: 28px;
|
|
|
|
left: 28px;
|
|
|
|
top: 26px;
|
|
|
|
top: 26px;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
gap: 18px;
|
|
|
|
|
|
|
|
flex-wrap: nowrap;
|
|
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
color: #72809a;
|
|
|
|
color: #72809a;
|
|
|
|
|
|
|
|
|
|
|
|
strong { color: #5645d5; font-size: 34px; line-height: 1.1; }
|
|
|
|
strong { font-size: 30px; line-height: 1; }
|
|
|
|
.summary-unit { color: #5645d5; font-weight: 600; }
|
|
|
|
.summary-unit { font-weight: 600; }
|
|
|
|
.rank-copy { margin-top: 18px; font-size: 13px; }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.summary-label { margin-bottom: 4px; font-size: 13px; }
|
|
|
|
.score-metric { display: inline-flex; align-items: baseline; gap: 4px; }
|
|
|
|
|
|
|
|
.score-metric--ai { color: #5645d5; }
|
|
|
|
|
|
|
|
.score-metric--teacher { color: #258edc; }
|
|
|
|
|
|
|
|
.summary-label { font-size: 14px; font-weight: 600; }
|
|
|
|
.score-table-wrap { display: flex; align-items: center; min-width: 0; overflow-x: auto; padding: 8px 0 8px 24px; }
|
|
|
|
.score-table-wrap { display: flex; align-items: center; min-width: 0; overflow-x: auto; padding: 8px 0 8px 24px; }
|
|
|
|
.score-table { width: 100%; min-width: 760px; }
|
|
|
|
.score-table { width: 100%; min-width: 760px; }
|
|
|
|
.score-table :deep(.el-table__cell) { white-space: nowrap; }
|
|
|
|
.score-table :deep(.el-table__cell) { white-space: nowrap; }
|
|
|
|
|