Просмотр исходного кода

fix: avoid misleading failed report display

jimmylee 2 недель назад
Родитель
Сommit
01dc443e64

+ 22 - 5
src/views/Editor/EnglishSpeaking/preview/TopicDiscussionPreview.vue

@@ -52,14 +52,15 @@
           {{ reportError }}
         </div>
         <OverallReport
-          :evaluation="displayEvaluation"
+          v-if="overallEvaluationForDisplay"
+          :evaluation="overallEvaluationForDisplay"
           :role="mockRole"
           :scoreDisplayMode="'numeric'"
           @restart="resetPreview"
           @complete="resetPreview"
         />
-        <div class="report-divider" />
-        <DetailedReport :sentenceEvaluations="displayEvaluation.sentenceEvaluations" />
+        <div v-if="shouldShowOverallReport" class="report-divider" />
+        <DetailedReport :sentenceEvaluations="displaySentenceEvaluations" />
       </div>
     </div>
 
@@ -198,17 +199,30 @@ const mockEvaluation: OverallEvaluation = {
 const realEvaluation = ref<OverallEvaluation | null>(null)
 const reportStatus = ref<DialogueReport['status'] | null>(null)
 const reportError = ref('')
+const reportFetchFailed = ref(false)
 
-const displayEvaluation = computed<OverallEvaluation>(() => {
+const displayEvaluation = computed<OverallEvaluation | null>(() => {
   const real = realEvaluation.value
   if (real) return real
+  if (reportFetchFailed.value) return null
   return mockEvaluation
 })
 
+const shouldShowOverallReport = computed(() => {
+  return !!displayEvaluation.value
+    && !reportError.value
+    && reportStatus.value !== 'failed'
+    && reportStatus.value !== 'incomplete'
+})
+
+const overallEvaluationForDisplay = computed(() => shouldShowOverallReport.value ? displayEvaluation.value : null)
+const displaySentenceEvaluations = computed(() => displayEvaluation.value?.sentenceEvaluations ?? [])
+
 async function startDialogue() {
   if (sessionCreating.value) return
   sessionCreating.value = true
   sessionError.value = null
+  reportFetchFailed.value = false
   try {
     // Fresh instance per attempt; MockDialogueAPI resets roundIndex in createSession.
     const api = createDialogueApi(props.mode)
@@ -237,9 +251,11 @@ async function startDialogue() {
 }
 
 function handleDialogueComplete(report: DialogueReport | null) {
+  reportFetchFailed.value = !report
   reportStatus.value = report?.status ?? null
   realEvaluation.value = report?.evaluation ?? null
-  if (report?.status === 'failed') reportError.value = '报告生成失败,部分语音评分未完成。'
+  if (!report) reportError.value = '报告生成超时或获取失败,请稍后重试。'
+  else if (report.status === 'failed') reportError.value = '报告生成失败,部分语音评分未完成。'
   else if (report?.status === 'incomplete') reportError.value = '本次练习没有足够的有效回答生成报告。'
   else reportError.value = ''
   dialogueState.value = 'completed'
@@ -250,6 +266,7 @@ function resetPreview() {
   realEvaluation.value = null
   reportStatus.value = null
   reportError.value = ''
+  reportFetchFailed.value = false
   preparedSession.value = null
   sessionError.value = null
   sessionCreating.value = false

+ 19 - 5
src/views/Editor/EnglishSpeaking/services/llmService.ts

@@ -104,14 +104,28 @@ interface BackendOverall {
   improvements: string[]
 }
 
+function hasCompleteScores(evaluation?: BackendEvaluation): evaluation is BackendEvaluation & {
+  accuracyScore: number
+  fluencyScore: number
+  completenessScore: number
+  prosodyScore: number
+} {
+  return !!evaluation
+    && evaluation.status === 'completed'
+    && typeof evaluation.accuracyScore === 'number'
+    && typeof evaluation.fluencyScore === 'number'
+    && typeof evaluation.completenessScore === 'number'
+    && typeof evaluation.prosodyScore === 'number'
+}
+
 function adaptReport(raw: BackendReportResponse): DialogueReport {
   const sentenceEvaluations: SentenceEvaluation[] = raw.rounds.map((r, idx) => {
-    const pronunciation = r.evaluation && r.role === 'student'
+    const pronunciation = r.role === 'student' && hasCompleteScores(r.evaluation)
       ? {
-          accuracy: r.evaluation.accuracyScore ?? 0,
-          fluency: r.evaluation.fluencyScore ?? 0,
-          intonation: r.evaluation.prosodyScore ?? 0,
-          stress: r.evaluation.completenessScore ?? 0,
+          accuracy: r.evaluation.accuracyScore,
+          fluency: r.evaluation.fluencyScore,
+          intonation: r.evaluation.prosodyScore,
+          stress: r.evaluation.completenessScore,
         }
       : undefined