diff --git a/康康/Features/Diary/DiaryQuickSheet.swift b/康康/Features/Diary/DiaryQuickSheet.swift index 462807a..1e05ded 100644 --- a/康康/Features/Diary/DiaryQuickSheet.swift +++ b/康康/Features/Diary/DiaryQuickSheet.swift @@ -53,7 +53,10 @@ struct DiaryQuickSheet: View { @State private var voiceDeniedAlert = false @State private var voiceFlowTask: Task? @State private var recordingWatchdog: Task? - private let dictation = SpeechDictationService() + /// 必须 @State:struct View 重建(键盘收起/detent 变化都会触发)时普通 let 会换成 + /// 全新实例,导致 stop() 落在没在录音的新服务上返回空串(「没听清」假错误), + /// 且真正在录音的老实例关不掉、麦克风悬挂。@State 保证视图身份期内实例唯一。 + @State private var dictation = SpeechDictationService() private var hasContent: Bool { !content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty @@ -590,8 +593,13 @@ struct DiaryQuickSheet: View { guard voicePhase == .recording else { return } recordingWatchdog?.cancel() voiceFlowTask = Task { @MainActor in - let transcript = (await dictation.stop()) + // 防御兜底:服务返回空(极端情况下实例丢失/最终结果丢失)时, + // 用 @State 里的实时字幕——那就是用户亲眼看到的已识别文字。 + var transcript = (await dictation.stop()) .trimmingCharacters(in: .whitespacesAndNewlines) + if transcript.isEmpty { + transcript = liveTranscript.trimmingCharacters(in: .whitespacesAndNewlines) + } liveTranscript = transcript guard !transcript.isEmpty else { withAnimation(.snappy(duration: 0.2)) { voicePhase = .idle }