- Replace all deprecated NavigationLink(destination:) with NavigationLink(value: Route) - Add Route enum with navigationDestination mapping in new Core/Navigation/ - Extract 7 new sub-page files (AIChatPage, AIFeedbackPageView, RecallTestPage, WeakPointsPage, FeedbackFormView, GoalSettingDetailView, MethodPreferenceView) - Add @ScaledMetric-based zxFontScaled modifier for Dynamic Type - Fix ZXPressModifier gesture conflict with ScrollView using onLongPressGesture - Enlarge touch targets from 36pt to 44pt - Add accessibility labels to TextField and other controls Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
108 lines
6.6 KiB
Swift
108 lines
6.6 KiB
Swift
import SwiftUI
|
|
|
|
struct AIFeedbackPageView: View {
|
|
@State private var navigateToChat = false
|
|
@State private var isAnalyzing = true
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
Color.zxBg0.ignoresSafeArea()
|
|
if isAnalyzing {
|
|
ZXAIAnalysisProgress(steps: [
|
|
"解析你的回答结构…",
|
|
"对比知识库标准答案…",
|
|
"评估概念理解深度…",
|
|
"生成个性化反馈…"
|
|
])
|
|
.onAppear {
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
|
|
withAnimation(.easeOut(duration: 0.4)) { isAnalyzing = false }
|
|
}
|
|
}
|
|
} else {
|
|
ScrollView {
|
|
VStack(spacing: 16) {
|
|
HStack(spacing: 20) {
|
|
ZStack {
|
|
Circle().trim(from: 0, to: 0.78).stroke(ZXGradient.brand, style: StrokeStyle(lineWidth: 10, lineCap: .round)).rotationEffect(.degrees(-90)).frame(width: 80, height: 80)
|
|
VStack(spacing: 0) {
|
|
Text("78").font(.system(size: 22, weight: .heavy)).foregroundColor(Color.zxPurple)
|
|
Text("/ 100").font(.system(size: 9)).foregroundColor(Color.zxF04)
|
|
}
|
|
}
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text("良好掌握").zxFontScaled(size: 18, weight: .heavy).foregroundColor(Color.zxF0)
|
|
Text("理解核心概念,但缺少理论深度和解决方案").zxFontScaled(size: 12).foregroundColor(Color.zxF0045).lineSpacing(4)
|
|
}
|
|
Spacer()
|
|
}
|
|
.padding(20)
|
|
.background(ZXGradient.feedbackScore)
|
|
.clipShape(RoundedRectangle(cornerRadius: 20))
|
|
.overlay(RoundedRectangle(cornerRadius: 20).stroke(Color(hex: "#7C6EFA", opacity: 0.2), lineWidth: 1))
|
|
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("你的回答").font(.system(size: 13, weight: .semibold)).foregroundColor(Color.zxF04)
|
|
Text("过拟合就像一个学生只会「死记硬背」考题,而不是真正理解知识…").zxFontScaled(size: 13).foregroundColor(Color.zxF007).lineSpacing(6).padding(14).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14)).overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder006, lineWidth: 1))
|
|
}
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack(spacing: 8) {
|
|
Image(systemName: "checkmark.circle.fill").foregroundColor(Color.zxGreen)
|
|
Text("答对的部分").font(.system(size: 14, weight: .bold)).foregroundColor(Color.zxF0)
|
|
}
|
|
ForEach(["正确识别出过拟合是\"记住训练数据\"而非\"学习规律\"", "使用了死记硬背类比,方向正确且贴切"], id: \.self) { s in
|
|
HStack(alignment: .top, spacing: 12) {
|
|
Circle().fill(Color.zxGreen).frame(width: 6, height: 6).padding(.top, 6)
|
|
Text(s).zxFontScaled(size: 13).foregroundColor(Color(hex: "#F0F0FF", opacity: 0.75)).lineSpacing(4)
|
|
}
|
|
.padding(12)
|
|
.background(Color(hex: "#34D399", opacity: 0.07))
|
|
.clipShape(RoundedRectangle(cornerRadius: 12))
|
|
.overlay(RoundedRectangle(cornerRadius: 12).stroke(Color(hex: "#34D399", opacity: 0.18), lineWidth: 1))
|
|
}
|
|
}
|
|
NavigationLink(value: Route.studyHome) {
|
|
Label("加入待巩固,安排间隔复习", systemImage: "bolt.fill")
|
|
.font(.system(size: 14, weight: .bold))
|
|
.foregroundColor(.white)
|
|
.frame(maxWidth: .infinity).frame(height: 52)
|
|
.background(ZXGradient.ctaPurple)
|
|
.clipShape(RoundedRectangle(cornerRadius: 16))
|
|
.shadow(color: Color(hex: "#7C6EFA", opacity: 0.3), radius: 24)
|
|
}
|
|
HStack(spacing: 12) {
|
|
NavigationLink(value: Route.aiChat) {
|
|
HStack(spacing: 4) {
|
|
Text("深入提问").font(.system(size: 13))
|
|
Image(systemName: "chevron.right").font(.system(size: 14))
|
|
}
|
|
.foregroundColor(Color.zxF05)
|
|
.frame(maxWidth: .infinity).frame(height: 44)
|
|
.background(Color.zxFill005)
|
|
.clipShape(RoundedRectangle(cornerRadius: 14))
|
|
.overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1))
|
|
}
|
|
NavigationLink(value: Route.dailyThinking) {
|
|
HStack(spacing: 4) {
|
|
Text("再来一题").font(.system(size: 13))
|
|
Image(systemName: "chevron.right").font(.system(size: 14))
|
|
}
|
|
.foregroundColor(Color.zxF05)
|
|
.frame(maxWidth: .infinity).frame(height: 44)
|
|
.background(Color.zxFill005)
|
|
.clipShape(RoundedRectangle(cornerRadius: 14))
|
|
.overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1))
|
|
}
|
|
}
|
|
}
|
|
.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
|
}
|
|
.scrollIndicators(.hidden)
|
|
.transition(.opacity.combined(with: .scale(scale: 0.95)))
|
|
}
|
|
}
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbarBackground(.hidden, for: .navigationBar)
|
|
}
|
|
}
|