-
{{ displayEvalMessage }}
-
- 综合评分:
{{ displayFinalScore }} / 100
+
+
{{ reports.assessmentSummary }}
+
+
+
+ {{ item.name }}
+ {{ item.score }} / {{ item.maxScore }}
+
+
{{ item.description }}
+
+
+
+
{{ displayEvalMessage }}
请先至少填写并保存一项实训内容,再请求 AI 助评。
@@ -109,13 +128,20 @@ const route = useRoute();
const currentTaskKey = computed(() => resolveTrainingTaskKey(route, props.taskKey));
const reports = computed(() => normalizeEvaluationReports(evaluation.value));
const currentStepContext = computed(() => [props.studyTip, props.referenceTitle, plainText(props.referenceText)].filter(Boolean).join("\n"));
+const displayScoreCriteria = computed(() => {
+ const criteria = reports.value.scoreCriteria;
+ const stepNames = props.progressItems.map((item) => String(item?.text || "").trim()).filter(Boolean);
+ if (!stepNames.length || stepNames.length !== criteria.length) return criteria;
+ return criteria.map((item, index) => ({ ...item, name: stepNames[index] }));
+});
const displayAssistMessage = computed(() => assistMessage.value || props.studyTip);
const displayScoreVisible = computed(() => props.scoreVisible || internalScoreVisible.value || reports.value.score !== null);
const displayFinalScore = computed(() => (props.scoreVisible ? props.finalScore : reports.value.score ?? internalScore.value));
+const hasStructuredAssessment = computed(() => Boolean(reports.value.assessmentSummary || displayScoreCriteria.value.length || reports.value.improvements.length));
const displayEvalMessage = computed(() => {
if (props.scoreVisible) return props.evalMessage;
- return reports.value.assessmentReport || internalEvalMessage.value || props.evalMessage;
+ return internalEvalMessage.value || props.evalMessage;
});
onMounted(loadEvaluation);
@@ -174,7 +200,7 @@ async function requestEvaluation() {
await loadEvaluation();
internalScoreVisible.value = reports.value.score !== null;
internalScore.value = reports.value.score ?? "--";
- internalEvalMessage.value = reports.value.assessmentReport || props.evalMessage;
+ internalEvalMessage.value = reports.value.assessmentSummary || "AI 评分已生成,请查看评分明细与改进建议。";
} catch (error) {
internalEvalMessage.value = "AI 助评暂时不可用,请稍后重试。";
} finally { assessmentLoading.value = false; }
@@ -266,6 +292,61 @@ function plainText(value) {
margin: 0;
}
}
+.ai-output--review {
+ max-height: 500px;
+ overflow-y: auto;
+}
+.assessment-result {
+ position: relative;
+ z-index: 1;
+ display: grid;
+ gap: 12px;
+}
+.assessment-summary {
+ margin: 0;
+ color: #e6f7ff;
+ font-weight: 650;
+ line-height: 1.8;
+}
+.assessment-criteria {
+ display: grid;
+ gap: 8px;
+}
+.assessment-criterion {
+ padding: 10px 11px;
+ border: 1px solid rgba(113, 225, 255, 0.22);
+ border-radius: 10px;
+ background: rgba(10, 43, 61, 0.4);
+}
+.assessment-criterion__heading {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 10px;
+ color: #f0fbff;
+}
+.assessment-criterion__heading span {
+ flex: 0 0 auto;
+ color: #71e8ff;
+ font-weight: 800;
+ font-variant-numeric: tabular-nums;
+}
+.assessment-criterion__heading small { color: #91bbcf; font-weight: 600; }
+.assessment-criterion p {
+ margin: 6px 0 0;
+ color: #afd3e3;
+ font-size: 13px;
+ line-height: 1.65;
+}
+.assessment-actions {
+ padding: 10px 11px;
+ border-left: 2px solid #5ce4ff;
+ color: #cceafa;
+ background: rgba(29, 114, 149, 0.14);
+}
+.assessment-actions strong { color: #7cecff; font-size: 13px; }
+.assessment-actions ul { margin: 6px 0 0; padding-left: 18px; }
+.assessment-actions li + li { margin-top: 4px; }
.study-messages {
position: relative;
z-index: 1;
@@ -380,17 +461,30 @@ function plainText(value) {
z-index: 1;
display: inline-flex;
align-items: center;
- gap: 6px;
- margin-top: 14px;
- padding: 8px 12px;
- border: 1px solid rgba(126, 233, 255, 0.38);
- border-radius: 999px;
+ width: 100%;
+ gap: 8px;
+ margin: -2px 0 14px;
+ padding: 12px 14px;
+ border: 1px solid rgba(101, 238, 255, 0.7);
+ border-radius: 12px;
color: #dff8ff;
- background: rgba(11, 42, 56, 0.78);
+ background:
+ linear-gradient(90deg, rgba(20, 169, 216, 0.4), rgba(8, 50, 70, 0.75)),
+ rgba(11, 42, 56, 0.78);
+ box-shadow: inset 0 1px 0 rgba(220, 253, 255, 0.23), 0 0 24px rgba(39, 209, 255, 0.16);
+ font-size: 14px;
+ font-weight: 800;
+ letter-spacing: 0.04em;
+
+ span { color: #dff8ff; }
+ em { color: #b8dce9; font-size: 13px; font-style: normal; font-weight: 700; }
strong {
color: #7ee9ff;
- font-size: 20px;
+ margin-left: auto;
+ font-size: 28px;
+ line-height: 1;
+ text-shadow: 0 0 14px rgba(102, 238, 255, 0.6);
}
}
diff --git a/src/views/components/trainingAiEvaluationReport.js b/src/views/components/trainingAiEvaluationReport.js
index 4961461..01e2c6c 100644
--- a/src/views/components/trainingAiEvaluationReport.js
+++ b/src/views/components/trainingAiEvaluationReport.js
@@ -8,6 +8,11 @@ function safeParseJson(value) {
}
}
+function criterionDisplayName(value) {
+ const name = String(value || "").trim();
+ return name || "评分项";
+}
+
function formatReport(value) {
if (value == null) return "";
const parsed = typeof value === "string" ? safeParseJson(value) : value;
@@ -24,13 +29,19 @@ function normalizeCriteria(value) {
return value.map((item) => {
if (typeof item === "string") return { name: item, score: "", description: "" };
return {
- name: String(item?.name || item?.criterion || item?.title || "评分项"),
+ name: criterionDisplayName(item?.name || item?.criterion || item?.title),
score: item?.score ?? item?.weight ?? "",
- description: String(item?.description || item?.detail || ""),
+ maxScore: item?.maxScore ?? item?.max ?? "",
+ description: String(item?.rationale || item?.description || item?.detail || ""),
};
});
}
+function normalizeTextList(value) {
+ if (!Array.isArray(value)) return [];
+ return value.map((item) => String(item || "").trim()).filter(Boolean);
+}
+
function normalizeOperation(operation, root, type) {
const value = operation && typeof operation === "object" ? operation : {};
const prefix = type === "help" ? "help" : "assessment";
@@ -47,15 +58,19 @@ function normalizeEvaluationReports(evaluation) {
const root = evaluation && typeof evaluation === "object" ? evaluation : {};
const help = normalizeOperation(root.help || root.helpEvaluation, root, "help");
const assessment = normalizeOperation(root.assessment || root.assessmentEvaluation, root, "assessment");
- const assessmentReportData = safeParseJson(root.assessmentReportJson);
+ const assessmentReportValue = assessment.report || assessment.content || assessment.feedback;
+ const assessmentReportData = safeParseJson(root.assessmentReportJson) || safeParseJson(assessmentReportValue) || {};
return {
help,
assessment,
helpReport: formatReport(help.report || help.content || help.suggestion),
- assessmentReport: formatReport(assessment.report || assessment.content || assessment.feedback),
+ assessmentReport: formatReport(assessmentReportValue),
score: root.assessmentScore ?? assessment.score ?? assessmentReportData?.score ?? root.score ?? null,
scoreCriteria: normalizeCriteria(assessmentReportData?.criteria || assessment.scoreCriteria || root.scoreCriteria),
+ assessmentSummary: String(assessmentReportData?.overallComment || assessmentReportData?.summary || "").trim(),
+ strengths: normalizeTextList(assessmentReportData?.strengths),
+ improvements: normalizeTextList(assessmentReportData?.improvements),
};
}
diff --git a/src/views/test/index.vue b/src/views/test/index.vue
index 503e59c..39f518a 100644
--- a/src/views/test/index.vue
+++ b/src/views/test/index.vue
@@ -56,7 +56,7 @@
| 当前权重合计 | {{ displayWeightTotal }}% | |