feat: show AI and teacher scores on student home

bugfix/ai-assessment-evidence-rescore
陈沅 1 month ago
parent 0128953288
commit 796f74f55e

@ -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; }

@ -0,0 +1,27 @@
const fs = require("node:fs");
const path = require("node:path");
const test = require("node:test");
const assert = require("node:assert/strict");
const source = fs.readFileSync(path.resolve(__dirname, "../src/views/student/index.vue"), "utf8");
test("学生首页并列展示 AI 评分和老师评分", () => {
assert.match(source, /AI评分/);
assert.match(source, /老师评分/);
assert.match(source, /report\.value\.teacherScore/);
assert.match(source, /formatTeacherScore/);
});
test("学生首页成绩摘要保持单行且不展示当前排名", () => {
assert.match(source, /\.score-summary[^}]*flex-wrap:\s*nowrap/);
assert.match(source, /\.score-summary[^}]*white-space:\s*nowrap/);
assert.doesNotMatch(source, /当前排名/);
assert.doesNotMatch(source, /rank-copy/);
});
test("老师未评分时不拼接分数单位", () => {
assert.match(source, /const hasTeacherScore = \(value\) => value !== null && value !== undefined && value !== ""/);
assert.match(source, /v-if="hasTeacherScore\(teacherScore\)"/);
});
console.log("student home AI and teacher score static checks passed");
Loading…
Cancel
Save