feat(Capture): 归档后后台预生成大白话摘要,详情页秒开 + 兜底重试
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -311,6 +311,9 @@ struct UnifiedCaptureFlow: View {
|
||||
}
|
||||
|
||||
try? ctx.save()
|
||||
// 后台预生成大白话摘要:用户继续操作,详情页打开时秒开。
|
||||
// 低优先级 —— 任何前台 AI 任务(再次拍照/问答)都会让它在下一个 token 让位。
|
||||
Task { await ReportInsightService.shared.pregenerateIfNeeded(report: report, in: ctx) }
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,14 +257,7 @@ struct TimelineEntryDetailView: View {
|
||||
}
|
||||
}
|
||||
|
||||
if let sum = r.summary, !sum.isEmpty {
|
||||
card {
|
||||
Text(String(appLoc: "摘要"))
|
||||
.font(.tjScaled( 12, weight: .semibold)).foregroundStyle(Tj.Palette.text2)
|
||||
Text(sum).font(.tjScaled( 14)).foregroundStyle(Tj.Palette.text)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
ReportSummaryCard(report: r)
|
||||
|
||||
if !r.indicators.isEmpty {
|
||||
card {
|
||||
@@ -559,3 +552,52 @@ private struct EvidenceHighlightOverlay: View {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 报告摘要卡(无摘要时后台预生成兜底)
|
||||
|
||||
/// 有摘要直接显示;无摘要且有指标时触发后台预生成(归档时若被抢占,这里兜底),
|
||||
/// 生成期间显示流光线,完成后 SwiftData 观察自动刷新出文本。
|
||||
private struct ReportSummaryCard: View {
|
||||
@Environment(\.modelContext) private var ctx
|
||||
let report: Report
|
||||
@State private var generating = false
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let sum = report.summary, !sum.isEmpty {
|
||||
container {
|
||||
Text(String(appLoc: "摘要"))
|
||||
.font(.tjScaled( 12, weight: .semibold)).foregroundStyle(Tj.Palette.text2)
|
||||
Text(sum).font(.tjScaled( 14)).foregroundStyle(Tj.Palette.text)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
} else if generating {
|
||||
container {
|
||||
Text("本地 AI 正在解读这份报告…")
|
||||
.font(.tjScaled( 12)).foregroundStyle(Tj.Palette.text3)
|
||||
AIFlowBar()
|
||||
}
|
||||
}
|
||||
}
|
||||
.task {
|
||||
guard (report.summary ?? "").isEmpty, !report.indicators.isEmpty else { return }
|
||||
generating = true
|
||||
await ReportInsightService.shared.pregenerateIfNeeded(report: report, in: ctx)
|
||||
generating = false
|
||||
}
|
||||
}
|
||||
|
||||
private func container<C: View>(@ViewBuilder _ body: () -> C) -> some View {
|
||||
VStack(alignment: .leading, spacing: 10) { body() }
|
||||
.padding(14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
|
||||
.fill(Tj.Palette.paper)
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
|
||||
.strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user