- 移除 3 处强制深色模式,用 @AppStorage 全局切换 - 设置页「外观」按钮实时切换深色/浅色/跟随系统 - 底部导航栏 inactive 颜色改为自适应 Color.zxF03 - 12 个子页面修复:保留返回按钮 + 消除顶部空白 - 新增 LearningSessionView/ReviewCardView/ActiveRecallView - 新增 NotificationListView/SettingsView 等子页面 - 补全所有按钮 NavigationLink 跳转(0 个空白 action) - KnowledgeBase 模型对齐服务器数据 - Info.plist 补充 CFBundleIdentifier + ATS - 新增缺口分析文档 gap-analysis-1/2.md
79 lines
6.3 KiB
Swift
79 lines
6.3 KiB
Swift
import SwiftUI
|
|
|
|
struct ProfileView: View {
|
|
var body: some View {
|
|
ZStack {
|
|
ZXGradient.page.ignoresSafeArea()
|
|
ScrollView {
|
|
VStack(spacing: 16) {
|
|
HStack {
|
|
Text("我的").font(.system(size: 22, weight: .heavy)).foregroundColor(Color.zxF0).tracking(-0.5)
|
|
Spacer()
|
|
NavigationLink(destination: NotificationListView()) {
|
|
Image(systemName: "bell").font(.system(size: 18)).foregroundColor(Color.zxF05)
|
|
.frame(width: 36, height: 36).background(Color(hex:"#FFFFFF",opacity:0.05))
|
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
|
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.zxBorder008, lineWidth: 1))
|
|
}
|
|
NavigationLink(destination: SettingsView()) {
|
|
Image(systemName: "gearshape").font(.system(size: 18)).foregroundColor(Color.zxF05)
|
|
.frame(width: 36, height: 36).background(Color(hex:"#FFFFFF",opacity:0.05))
|
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
|
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.zxBorder008, lineWidth: 1))
|
|
}
|
|
}.padding(.horizontal, 20).padding(.top, ZXSpacing.statusBarH + 16).padding(.bottom, 4)
|
|
profileCard
|
|
VStack(spacing: 0) {
|
|
NavigationLink(destination: GoalSettingDetailView()) {
|
|
ZXProfileMenuRow(emoji: "🎯", title: "学习目标设置", desc: "调整你的学习目标")
|
|
}.foregroundColor(.primary)
|
|
ZXProfileDivider()
|
|
NavigationLink(destination: SettingsView()) {
|
|
ZXProfileMenuRow(emoji: "🔔", title: "复习提醒", desc: "间隔复习通知设置")
|
|
}.foregroundColor(.primary)
|
|
ZXProfileDivider()
|
|
NavigationLink(destination: MethodPreferenceView()) {
|
|
ZXProfileMenuRow(emoji: "🧩", title: "学习方法偏好", desc: "回忆 · 费曼 · 间隔")
|
|
}.foregroundColor(.primary)
|
|
ZXProfileDivider()
|
|
NavigationLink(destination: FeedbackFormView()) {
|
|
ZXProfileMenuRow(emoji: "💬", title: "帮助与反馈", desc: "问题报告 · 功能建议")
|
|
}.foregroundColor(.primary)
|
|
}.background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 20)).overlay(RoundedRectangle(cornerRadius: 20).stroke(Color.zxBorder006, lineWidth: 1))
|
|
achievementsSection.padding(.bottom, 120)
|
|
}.padding(.horizontal, 20)
|
|
}.scrollIndicators(.hidden)
|
|
}
|
|
}
|
|
private var profileCard: some View {
|
|
NavigationLink(destination: SettingsView()) {
|
|
VStack(spacing: 16) {
|
|
HStack {
|
|
ZStack { Circle().frame(width: 80, height: 80).foregroundColor(Color.zxPurpleBG(0.2)); Text("🧑🎓").font(.system(size: 36)) }
|
|
VStack(alignment: .leading, spacing: 4) { Text("学习者").font(.system(size: 20, weight: .bold)).foregroundColor(Color.zxF0); Text("user@example.com").font(.system(size: 12)).foregroundColor(Color.zxF04) }
|
|
Spacer(); Image(systemName: "chevron.right").font(.system(size: 14)).foregroundColor(Color.zxF03)
|
|
}
|
|
HStack(spacing: 0) { ZXProfileStat(value: "14", label: "连续天", color: Color.zxOrange); ZXProfileStat(value: "47", label: "知识点", color: Color.zxPurple); ZXProfileStat(value: "1,240", label: "积分", color: Color.zxTeal) }
|
|
}.padding(20).background(ZXGradient.profileCard).overlay(RoundedRectangle(cornerRadius: 20).stroke(Color(hex: "#7C6EFA", opacity: 0.2), lineWidth: 1)).clipShape(RoundedRectangle(cornerRadius: 20))
|
|
}.foregroundColor(.primary)
|
|
}
|
|
private var achievementsSection: some View {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
Text("成就").font(.system(size: 15, weight: .bold)).foregroundColor(Color.zxF0)
|
|
HStack(spacing: 8) { ZXAchievementBadge(emoji: "🔥", label: "连续 14 天", color: Color.zxOrange); ZXAchievementBadge(emoji: "🧠", label: "费曼达人", color: Color.zxPurple); ZXAchievementBadge(emoji: "📚", label: "知识收藏家", color: Color.zxTeal); ZXAchievementBadge(emoji: "⚡", label: "速学者", color: Color.zxYellow) }
|
|
}
|
|
}
|
|
}
|
|
struct ZXProfileStat: View { let v: String; let l: String; let c: Color; var body: some View { VStack(spacing: 2) { Text(v).font(.system(size: 18, weight: .bold)).foregroundColor(c); Text(l).font(.system(size: 11)).foregroundColor(Color.zxF04) }.frame(maxWidth: .infinity) }
|
|
init(value: String, label: String, color: Color) { self.v = value; self.l = label; self.c = color }
|
|
}
|
|
struct ZXProfileMenuRow: View { let emoji: String; let title: String; let desc: String
|
|
var body: some View { HStack(spacing: 12) { Text(emoji).font(.system(size: 20)).frame(width: 36, height: 36).background(Color.zxFill006).clipShape(RoundedRectangle(cornerRadius: 10)); VStack(alignment: .leading, spacing: 2) { Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF0); Text(desc).font(.system(size: 11)).foregroundColor(Color.zxF03) }; Spacer(); Image(systemName: "chevron.right").font(.system(size: 12)).foregroundColor(Color.zxF03) }.padding(.horizontal, 16).padding(.vertical, 14) }
|
|
}
|
|
struct ZXProfileDivider: View {
|
|
var body: some View { Rectangle().fill(Color.zxBorder008).frame(height: 1).padding(.leading, 64) }
|
|
}
|
|
struct ZXAchievementBadge: View { let emoji: String; let label: String; let color: Color
|
|
var body: some View { VStack(spacing: 6) { Text(emoji).font(.system(size: 24)).frame(width: 48, height: 48).background(color.opacity(0.12)).clipShape(RoundedRectangle(cornerRadius: 14)).overlay(RoundedRectangle(cornerRadius: 14).stroke(color.opacity(0.25), lineWidth: 1)); Text(label).font(.system(size: 10, weight: .semibold)).foregroundColor(Color.zxF04) }.frame(maxWidth: .infinity) }
|
|
}
|