fix: show teacher score in score details

bugfix/ai-assessment-evidence-rescore
chenyuan 1 month ago
parent afda30d02b
commit e60855cf70

@ -693,6 +693,14 @@ export function getScoreDetail(params) {
params,
});
}
// 保存老师对学生的人工评分
export function saveTeacherScore(params) {
return request({
url: "/api/weight/saveTeacherScore",
method: "POST",
params,
});
}
// 更新成绩
export function doRankOne(params) {
return request({

@ -46,6 +46,27 @@
<el-table-column prop="username" label="学号" align="center" />
<el-table-column prop="className" label="班级" align="center" />
<el-table-column prop="score" label="参考成绩" align="center" />
<el-table-column label="老师评分" align="center" min-width="190">
<template #default="{ row }">
<div class="teacher-score-editor">
<el-input-number
v-model="row.teacherScoreDraft"
:min="0"
:max="100"
:precision="2"
:controls="false"
placeholder="0-100"
:aria-label="`给${row.name || row.username}评分`"
/>
<el-button
type="primary"
size="small"
:loading="savingScoreUserId === row.userId"
@click="saveTeacherScore(row)"
>保存</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="实训进度" align="center">
<template #default="{ row }">
<span :title="trainingProgressTitle(row)">{{ formatTrainingProgress(row) }}</span>
@ -101,6 +122,20 @@
</template>
</el-dialog>
<el-dialog v-model="scoreDetailsStart" title="成绩详情" width="50%" class="F_dialog teacher-dialog">
<div class="score-detail-summary">
<div class="score-detail-summary__item">
<span>学生姓名</span>
<strong>{{ scoreDetailStudent.name || "--" }}</strong>
</div>
<div class="score-detail-summary__item">
<span>AI评测总分</span>
<strong>{{ formatScore(scoreDetailStudent.aiTotalScore) }}</strong>
</div>
<div class="score-detail-summary__item">
<span>老师评分</span>
<strong>{{ formatTeacherScore(scoreDetailStudent.teacherScore) }}</strong>
</div>
</div>
<el-table
:data="tableData"
border
@ -130,6 +165,7 @@ import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
const workingCapitalList = ref([]);
const loading = ref(false);
const savingScoreUserId = ref("");
const scoreParams = ref({
classId: "",
index: 1,
@ -138,6 +174,11 @@ const scoreParams = ref({
});
const scoreDetailsStart = ref(false);
const tableData = ref([]);
const scoreDetailStudent = ref({
name: "",
aiTotalScore: null,
teacherScore: null,
});
const WeightStart = ref(false);
// 权重
const workingCapitalTotal = ref(0);
@ -152,6 +193,14 @@ const trainingProgressTitle = (row) => {
if (row.trainingProgress === null || row.trainingProgress === undefined) return "";
return `已完成 ${row.completedTaskCount || 0}/${row.totalTaskCount || 0} 项`;
};
const formatScore = (score) => {
if (score === null || score === undefined || score === "") return "--";
const value = Number(score);
return Number.isFinite(value) ? value.toFixed(2).replace(/\.00$/, "") : "--";
};
const formatTeacherScore = (score) => score === null || score === undefined || score === ""
? "未评分"
: formatScore(score);
const weightFields = ["foundationWeight", "marketInsightWeight", "planningDesignWeight", "developmentValidationWeight", "launchOperationWeight", "comprehensiveTrainingWeight"];
const rules = Object.fromEntries(weightFields.map((field) => [field, [
{ required: true, message: "请输入权重", trigger: "blur" },
@ -167,7 +216,12 @@ const buildScoreQuery = () => {
const getList = () => {
loading.value = true;
indexApi.getScoreList(buildScoreQuery()).then((res) => {
workingCapitalList.value = res.data.list;
workingCapitalList.value = (res.data.list || []).map((row) => ({
...row,
teacherScoreDraft: row.teacherScore === null || row.teacherScore === undefined
? null
: Number(row.teacherScore),
}));
workingCapitalTotal.value = res.data.total;
loading.value = false;
});
@ -231,11 +285,36 @@ const getClassScoreDetail = (row) => {
proxy.$modal.msgWarning("请选择自己的教学班后再查看成绩详情");
return;
}
scoreDetailStudent.value = {
name: row.name,
aiTotalScore: row.score,
teacherScore: row.teacherScore,
};
indexApi.getScoreDetail({ userId: row.userId, classId: scoreParams.value.classId }).then((res) => {
tableData.value = res.data;
scoreDetailsStart.value = true;
});
};
const saveTeacherScore = (row) => {
if (row.teacherScoreDraft === null || row.teacherScoreDraft === undefined || row.teacherScoreDraft === "") {
proxy.$message.error("请输入老师评分");
return;
}
const score = Number(row.teacherScoreDraft);
if (!Number.isFinite(score) || score < 0 || score > 100) {
proxy.$message.error("老师评分必须为0至100之间的数值");
return;
}
savingScoreUserId.value = row.userId;
indexApi.saveTeacherScore({
classId: scoreParams.value.classId,
studentUserId: row.userId,
teacherScore: score,
}).then(() => {
row.teacherScore = score;
proxy.$message.success("老师评分保存成功");
}).finally(() => (savingScoreUserId.value = ""));
};
// 更新成绩
const updateScore = () => {
if (!scoreParams.value.classId) {
@ -265,4 +344,40 @@ onMounted(() => {
background: #ffffff;
height: calc(100vh - 70px);
}
.teacher-score-editor {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
:deep(.el-input-number) {
width: 104px;
}
}
.score-detail-summary {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
margin-bottom: 16px;
}
.score-detail-summary__item {
display: flex;
flex-direction: column;
gap: 8px;
padding: 14px 18px;
background: rgba(2, 167, 240, 0.08);
border: 1px solid rgba(2, 167, 240, 0.3);
border-radius: 6px;
span {
color: #7f9cab;
font-size: 13px;
}
strong {
color: #02a7f0;
font-size: 20px;
font-variant-numeric: tabular-nums;
}
}
</style>

@ -0,0 +1,16 @@
const assert = require("assert");
const fs = require("fs");
const page = fs.readFileSync("src/views/teacherEnd/score/index.vue", "utf8");
const api = fs.readFileSync("src/api/teacher.js", "utf8");
assert(page.includes("学生姓名"));
assert(page.includes("AI评测总分"));
assert(page.includes("老师评分"));
assert(page.includes("scoreDetailStudent.name"));
assert(page.includes("scoreDetailStudent.aiTotalScore"));
assert(page.includes("scoreDetailStudent.teacherScore"));
assert(page.includes("row.teacherScore = score"));
assert(api.includes("/api/weight/saveTeacherScore"));
console.log("score detail summary static checks passed");
Loading…
Cancel
Save