feat(ios): 全局替换所有 systemName 为 Tabler SVG 图标

- 30+ 种 systemName 全部换为自定义 SVG
- 新增 list/clock/refresh/pencil 4 个 Tabler 图标
- 底部导航栏已使用自定义 SVG(无需改动)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
wangdl 2026-05-30 13:53:43 +08:00
parent 4889f6c832
commit 52756d3bb0
21 changed files with 191 additions and 43 deletions

View File

@ -0,0 +1,16 @@
{
"images": [
{
"filename": "icon-clock.svg",
"idiom": "universal"
}
],
"info": {
"author": "xcode",
"version": 1
},
"properties": {
"template-rendering-intent": "template",
"preserves-vector-representation": true
}
}

View File

@ -0,0 +1,20 @@
<!--
tags: [time, watch, alarm, clock, control, operation, function, interface, management]
category: System
version: "1.0"
unicode: "ea70"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
<path d="M12 7v5l3 3" />
</svg>

After

Width:  |  Height:  |  Size: 423 B

View File

@ -0,0 +1,16 @@
{
"images": [
{
"filename": "icon-list.svg",
"idiom": "universal"
}
],
"info": {
"author": "xcode",
"version": 1
},
"properties": {
"template-rendering-intent": "template",
"preserves-vector-representation": true
}
}

View File

@ -0,0 +1,24 @@
<!--
tags: [task, unordered, bullets, agenda, shopping, list, typography, writing, font, character]
category: Text
version: "1.2"
unicode: "eb6b"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M9 6l11 0" />
<path d="M9 12l11 0" />
<path d="M9 18l11 0" />
<path d="M5 6l0 .01" />
<path d="M5 12l0 .01" />
<path d="M5 18l0 .01" />
</svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@ -0,0 +1,16 @@
{
"images": [
{
"filename": "icon-pencil.svg",
"idiom": "universal"
}
],
"info": {
"author": "xcode",
"version": 1
},
"properties": {
"template-rendering-intent": "template",
"preserves-vector-representation": true
}
}

View File

@ -0,0 +1,20 @@
<!--
tags: [write, draft, edit, note, pencil, creative, artistic, visual, aesthetic, style]
category: Design
version: "1.1"
unicode: "eb04"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" />
<path d="M13.5 6.5l4 4" />
</svg>

After

Width:  |  Height:  |  Size: 444 B

View File

@ -0,0 +1,16 @@
{
"images": [
{
"filename": "icon-refresh.svg",
"idiom": "universal"
}
],
"info": {
"author": "xcode",
"version": 1
},
"properties": {
"template-rendering-intent": "template",
"preserves-vector-representation": true
}
}

View File

@ -0,0 +1,20 @@
<!--
tags: [synchronization, reload, restart, spinner, loader, ajax, update, arrows, refresh, navigation]
category: Arrows
version: "1.0"
unicode: "eb13"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
<path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
</svg>

After

Width:  |  Height:  |  Size: 467 B

View File

@ -17,7 +17,7 @@ struct AIChatPage: View {
}.frame(maxWidth: .infinity, maxHeight: .infinity)
} else if let error = vm.sessionError {
VStack(spacing: 16) {
Image(systemName: "exclamationmark.triangle").font(.system(size: 36)).foregroundColor(Color.zxF04)
Image("icon-warning").font(.system(size: 36)).foregroundColor(Color.zxF04)
Text(error).font(.system(size: 14)).foregroundColor(Color.zxF04)
}.frame(maxWidth: .infinity, maxHeight: .infinity)
} else {
@ -32,7 +32,7 @@ struct AIChatPage: View {
VStack(spacing: 4) {
ForEach(citations.prefix(3)) { c in
HStack(spacing: 4) {
Image(systemName: "doc.text").font(.system(size: 9)).foregroundColor(Color.zxF04)
Image("icon-file").font(.system(size: 9)).foregroundColor(Color.zxF04)
Text(c.excerptText?.prefix(60).description ?? "").font(.system(size: 10)).foregroundColor(Color.zxF04).lineLimit(1)
}.padding(.horizontal, 8).padding(.vertical, 4)
.background(Color.zxFill004).clipShape(Capsule())
@ -54,7 +54,7 @@ struct AIChatPage: View {
}
if vm.isSending {
HStack(spacing: 8) {
Image(systemName: "brain.head.profile").foregroundColor(Color.zxPurple)
Image("icon-brain").foregroundColor(Color.zxPurple)
.frame(width: 28, height: 28).background(Color(hex: "#7C6EFA", opacity: 0.15)).clipShape(Circle())
ZXDotLoader(color: Color.zxPurple).padding(.leading, 4); Spacer()
}.padding(.horizontal, 20)
@ -73,7 +73,7 @@ struct AIChatPage: View {
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button { Task { sessions = (try? await RagChatService.shared.listSessions()) ?? []; showSessions = true } } label: {
Image(systemName: "list.bullet.rectangle").font(.system(size: 16)).foregroundColor(Color.zxF05)
Image("icon-list").font(.system(size: 16)).foregroundColor(Color.zxF05)
}
}
}
@ -111,7 +111,7 @@ struct AIChatPage: View {
private func chatBubble(_ m: AIMessage) -> some View {
HStack(alignment: .top, spacing: 8) {
if m.role == .ai {
Image(systemName: "brain.head.profile").foregroundColor(Color.zxPurple)
Image("icon-brain").foregroundColor(Color.zxPurple)
.frame(width: 28, height: 28).background(Color(hex: "#7C6EFA", opacity: 0.15)).clipShape(Circle())
}
Text(m.content).zxFontScaled(size: 14)

View File

@ -149,7 +149,7 @@ struct AIHomeView: View {
//
Button { Task { await checkServer() } } label: {
Image(systemName: "arrow.clockwise")
Image("icon-refresh")
.font(.system(size: 16, weight: .medium))
.foregroundColor(Color.zxInkSecondary)
.frame(width: 40, height: 40)
@ -165,7 +165,7 @@ struct AIHomeView: View {
VStack(alignment: .leading, spacing: 10) {
// Tag
HStack(spacing: 6) {
Image(systemName: "sparkles")
Image("icon-sparkles")
.font(.system(size: 11))
Text("AI 驱动学习")
.font(.system(size: ZXFont.caption2.size, weight: .semibold))
@ -290,7 +290,7 @@ struct AIHomeView: View {
VStack(alignment: .leading, spacing: 14) {
// Header
HStack {
Image(systemName: "sparkles")
Image("icon-sparkles")
.font(.system(size: 13))
.foregroundColor(Color.zxPrimary)
.frame(width: 30, height: 30)
@ -407,7 +407,7 @@ struct AIHomeView: View {
private var inputBar: some View {
HStack(spacing: 10) {
Image(systemName: "sparkles")
Image("icon-sparkles")
.font(.system(size: 15))
.foregroundColor(Color.zxPrimary)
@ -419,7 +419,7 @@ struct AIHomeView: View {
//
Button {} label: {
Image(systemName: "mic.fill")
Image("icon-mic")
.font(.system(size: 17))
.foregroundColor(Color.zxInkTertiary)
}
@ -428,7 +428,7 @@ struct AIHomeView: View {
Button {
navigateToChat = true
} label: {
Image(systemName: "arrow.up")
Image("icon-upload")
.font(.system(size: 14, weight: .bold))
.foregroundColor(Color.zxOnPrimary)
.frame(width: 32, height: 32)

View File

@ -85,11 +85,11 @@ struct ActiveRecallView: View {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 8) {
if current.isVoice {
Image(systemName: "mic.fill").font(.system(size: 12)).foregroundColor(Color.zxOrange)
Image("icon-mic").font(.system(size: 12)).foregroundColor(Color.zxOrange)
Text("语音题").font(.system(size: 10, weight: .bold)).foregroundColor(Color.zxOrange)
.padding(.horizontal, 6).padding(.vertical, 2).background(Color.zxOrangeBG(0.1)).clipShape(Capsule())
} else {
Image(systemName: "pencil.line").font(.system(size: 12)).foregroundColor(Color.zxPurple)
Image("icon-pencil").font(.system(size: 12)).foregroundColor(Color.zxPurple)
Text("文字题").font(.system(size: 10, weight: .bold)).foregroundColor(Color.zxPurple)
.padding(.horizontal, 6).padding(.vertical, 2).background(Color.zxPurpleBG(0.1)).clipShape(Capsule())
}
@ -160,7 +160,7 @@ struct ActiveRecallView: View {
VStack(spacing: 12) {
ZStack {
Circle().fill(Color.zxOrangeBG(0.1)).frame(width: 80, height: 80)
Image(systemName: "mic.fill").font(.system(size: 32)).foregroundColor(Color.zxOrange)
Image("icon-mic").font(.system(size: 32)).foregroundColor(Color.zxOrange)
}
Text("点击按钮开始录音,用费曼方法口头解释").font(.system(size: 12)).foregroundColor(Color.zxF04)
}

View File

@ -60,12 +60,12 @@ struct AnalysisHomeView: View {
// AI
if let summary = viewModel.summary {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 8) { Image(systemName: "brain.head.profile").font(.system(size: 14)).foregroundColor(Color.zxPurple); Text("AI 综合分析").font(.system(size: 14, weight: .bold)).foregroundColor(Color.zxF0) }
HStack(spacing: 8) { Image("icon-brain").font(.system(size: 14)).foregroundColor(Color.zxPurple); Text("AI 综合分析").font(.system(size: 14, weight: .bold)).foregroundColor(Color.zxF0) }
Text(aiAnalysisText).font(.system(size: 13)).foregroundColor(Color.zxF05).lineSpacing(4)
}.padding(16).background(Color.zxFill004).overlay(RoundedRectangle(cornerRadius: 20).stroke(Color.zxBorder006, lineWidth: 1)).clipShape(RoundedRectangle(cornerRadius: 20))
}
VStack(alignment: .leading, spacing: 12) {
HStack { HStack(spacing: 8) { Image(systemName: "exclamationmark.triangle.fill").font(.system(size: 14)).foregroundColor(Color.zxYellow); Text("薄弱知识点").font(.system(size: 15, weight: .bold)).foregroundColor(Color.zxF0) }; Spacer(); NavigationLink(value: Route.weakPoints) { Text("全部 \(viewModel.focusItems.count)").font(.system(size: 12)).foregroundColor(Color.zxPurple) } }
HStack { HStack(spacing: 8) { Image("icon-warning").font(.system(size: 14)).foregroundColor(Color.zxYellow); Text("薄弱知识点").font(.system(size: 15, weight: .bold)).foregroundColor(Color.zxF0) }; Spacer(); NavigationLink(value: Route.weakPoints) { Text("全部 \(viewModel.focusItems.count)").font(.system(size: 12)).foregroundColor(Color.zxPurple) } }
ForEach(viewModel.focusItems.prefix(5)) { item in ZXWeakRow(score: item.masteryScore ?? 0, topic: item.title, lib: item.knowledgeBaseId ?? "", priority: item.priority ?? "normal") }
if viewModel.focusItems.isEmpty && !viewModel.isLoading { Text("暂无薄弱知识点").font(.system(size: 13)).foregroundColor(Color.zxF03) }
}

View File

@ -24,7 +24,7 @@ struct LibraryHomeView: View {
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 12)
//
HStack(spacing: 8) { Image(systemName: "magnifyingglass").font(.system(size: 16)).foregroundColor(Color.zxF03); TextField("搜索知识库或知识点…", text: $s).font(.system(size: 14)).tint(Color.zxPurple) }
HStack(spacing: 8) { Image("icon-search").font(.system(size: 16)).foregroundColor(Color.zxF03); TextField("搜索知识库或知识点…", text: $s).font(.system(size: 14)).tint(Color.zxPurple) }
.padding(.horizontal, 14).frame(height: 44).background(Color.zxFill004).overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1)).clipShape(RoundedRectangle(cornerRadius: 14)).padding(.horizontal, 20).padding(.bottom, 12)
// chips
@ -92,17 +92,17 @@ struct ZLibraryCard: View { let coverUrl: String?; let name: String; let desc: S
AsyncImage(url: imageUrl) { phase in
switch phase {
case .success(let img): img.resizable().scaledToFill().frame(width: 56, height: 56).clipShape(RoundedRectangle(cornerRadius: 13))
default: Image(systemName: "books.vertical.fill").font(.system(size: 22)).foregroundColor(Color.zxPurple.opacity(0.5))
default: Image("icon-books").font(.system(size: 22)).foregroundColor(Color.zxPurple.opacity(0.5))
}
}
} else {
Image(systemName: "books.vertical.fill").font(.system(size: 22)).foregroundColor(Color.zxPurple.opacity(0.5))
Image("icon-books").font(.system(size: 22)).foregroundColor(Color.zxPurple.opacity(0.5))
}
}
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 6) {
Text(name).font(.system(size: 16, weight: .bold)).foregroundColor(Color.zxF0)
if isPinned { Image(systemName: "pin.fill").font(.system(size: 10)).foregroundColor(Color.zxOrange) }
if isPinned { Image("icon-pin").font(.system(size: 10)).foregroundColor(Color.zxOrange) }
if visibility == "public" { Text("公开").font(.system(size: 9, weight: .semibold)).foregroundColor(Color.zxGreen).padding(.horizontal, 5).padding(.vertical, 1).background(Color.zxGreen.opacity(0.12)).clipShape(Capsule()) }
}
if !desc.isEmpty { Text(desc).font(.system(size: 12)).foregroundColor(Color.zxF04).lineLimit(1) }
@ -110,7 +110,7 @@ struct ZLibraryCard: View { let coverUrl: String?; let name: String; let desc: S
Spacer()
}.padding(16)
HStack {
HStack(spacing: 4) { Image(systemName: "clock").font(.system(size: 10)); Text("\(items) 项 · \(last)").font(.system(size: 11)) }.foregroundColor(Color.zxF03)
HStack(spacing: 4) { Image("icon-clock").font(.system(size: 10)); Text("\(items) 项 · \(last)").font(.system(size: 11)) }.foregroundColor(Color.zxF03)
Spacer()
}.padding(.horizontal, 16).padding(.bottom, 12) }
.background(Color.zxFill003).clipShape(RoundedRectangle(cornerRadius: 20)).overlay(RoundedRectangle(cornerRadius: 20).stroke(Color.zxBorder006, lineWidth: 1)) }
@ -121,13 +121,13 @@ struct LibrarySearchView: View {
var body: some View {
ZStack { Color.zxBg0.ignoresSafeArea()
VStack(spacing: 0) {
HStack(spacing: 8) { Image(systemName: "magnifyingglass").font(.system(size: 16)).foregroundColor(Color.zxF03); TextField("搜索知识库或知识点…", text: $query).font(.system(size: 14)).tint(Color.zxPurple) }
HStack(spacing: 8) { Image("icon-search").font(.system(size: 16)).foregroundColor(Color.zxF03); TextField("搜索知识库或知识点…", text: $query).font(.system(size: 14)).tint(Color.zxPurple) }
.padding(.horizontal, 14).frame(height: 44).background(Color.zxFill004).overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1)).clipShape(RoundedRectangle(cornerRadius: 14))
.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 16)
ScrollView { VStack(spacing: 12) {
if query.isEmpty {
VStack(spacing: 12) {
Image(systemName: "magnifyingglass").font(.system(size: 36)).foregroundColor(Color.zxF03)
Image("icon-search").font(.system(size: 36)).foregroundColor(Color.zxF03)
Text("搜索知识点、知识库或标签").font(.system(size: 13)).foregroundColor(Color.zxF03)
}.padding(.top, 80)
}

View File

@ -87,7 +87,7 @@ struct CreateLibraryPage: View {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { showCoverPicker = true }
} label: {
HStack(spacing: 12) {
Image(systemName: "photo.on.rectangle").font(.system(size: 20)).foregroundColor(Color.zxPrimary).frame(width: 40, height: 40).background(Color.zxPrimarySoft).clipShape(RoundedRectangle(cornerRadius: 10))
Image("icon-camera").font(.system(size: 20)).foregroundColor(Color.zxPrimary).frame(width: 40, height: 40).background(Color.zxPrimarySoft).clipShape(RoundedRectangle(cornerRadius: 10))
VStack(alignment: .leading, spacing: 2) {
Text("从相册选择").font(.system(size: 15, weight: .medium)).foregroundColor(Color.zxF0)
Text("选择一张图片作为封面").font(.system(size: 12)).foregroundColor(Color.zxF04)
@ -268,7 +268,7 @@ struct LibraryDetailPage: View {
}
ToolbarItem(placement: .topBarTrailing) {
NavigationLink(value: Route.quizList(knowledgeBaseId: knowledgeBaseId)) {
Image(systemName: "questionmark.circle").font(.system(size: 16)).foregroundColor(Color.zxF05)
Image("icon-question").font(.system(size: 16)).foregroundColor(Color.zxF05)
}
}
ToolbarItem(placement: .topBarTrailing) {
@ -381,7 +381,7 @@ struct AddKnowledgePage: View {
HStack(spacing: 8) {
Button { showFilePicker = true } label: {
HStack {
Image(systemName: "doc.badge.plus")
Image("icon-plus")
Text("选择文件")
}
.font(.system(size: 14, weight: .medium))
@ -392,7 +392,7 @@ struct AddKnowledgePage: View {
}
Button { showPhotoPicker = true } label: {
HStack {
Image(systemName: "photo.on.rectangle")
Image("icon-camera")
Text("图片")
}
.font(.system(size: 14, weight: .medium))
@ -619,7 +619,7 @@ struct KnowledgeDetailPage: View {
ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) {
HStack { Spacer()
NavigationLink(value: Route.editKnowledge(item: item)) {
Image(systemName: "pencil").font(.system(size: 16)).foregroundColor(Color.zxF05)
Image("icon-pencil").font(.system(size: 16)).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))
@ -664,7 +664,7 @@ struct ImportPage: View {
ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) {
ScrollView { VStack(spacing: 12) {
if let error = importError {
HStack(spacing: 8) { Image(systemName: "exclamationmark.triangle.fill").foregroundColor(.red); Text(error).font(.system(size: 13)).foregroundColor(.red) }
HStack(spacing: 8) { Image("icon-warning").foregroundColor(.red); Text(error).font(.system(size: 13)).foregroundColor(.red) }
.padding(12)
}

View File

@ -163,7 +163,7 @@ struct EditProfilePage: View {
private var defaultAvatar: some View {
ZStack {
Circle().fill(Color.zxPurpleBG(0.2)).frame(width: 88, height: 88)
Image(systemName: "person.crop.circle.fill")
Image("icon-brain")
.font(.system(size: 40))
.foregroundColor(Color.zxPurple)
}

View File

@ -23,7 +23,7 @@ struct NotificationListView: View {
if isLoading && notifications.isEmpty {
VStack(spacing: 12) { ProgressView().tint(Color.zxPurple); Text("加载中…").font(.system(size: 13)).foregroundColor(Color.zxF04) }.padding(.top, 120)
} else if notifications.isEmpty {
VStack(spacing: 12) { Image(systemName: "bell.slash").font(.system(size: 40)).foregroundColor(Color.zxF03); Text("暂无通知").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF03) }.padding(.top, 120)
VStack(spacing: 12) { Image("icon-bell-off").font(.system(size: 40)).foregroundColor(Color.zxF03); Text("暂无通知").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF03) }.padding(.top, 120)
} else {
if !todayItems.isEmpty { sectionView("今天", items: todayItems) }
if !weekItems.isEmpty { sectionView("本周", items: weekItems) }

View File

@ -49,7 +49,7 @@ struct ProfileView: View {
private var defaultAvatarIcon: some View {
ZStack {
Circle().fill(Color.zxPurpleBG(0.2)).frame(width: 80, height: 80)
Image(systemName: "person.crop.circle.fill")
Image("icon-brain")
.font(.system(size: 36))
.foregroundColor(Color.zxPurple)
}
@ -94,7 +94,7 @@ struct ProfileView: View {
VStack(spacing: 0) {
NavigationLink(value: Route.libraryCreate) {
HStack {
Image(systemName: "books.vertical.fill").resizable().scaledToFit().frame(width: 20, height: 20).foregroundColor(Color.zxF05)
Image("icon-books").resizable().scaledToFit().frame(width: 20, height: 20).foregroundColor(Color.zxF05)
Text("学习资产").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF0)
Spacer()
@ -105,7 +105,7 @@ struct ProfileView: View {
ZXProfileDivider()
NavigationLink(value: Route.notificationList) {
HStack {
Image(systemName: "bell.fill").resizable().scaledToFit().frame(width: 20, height: 20).foregroundColor(Color.zxF05)
Image("icon-bell-on").resizable().scaledToFit().frame(width: 20, height: 20).foregroundColor(Color.zxF05)
Text("消息中心").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF0)
Spacer(); Image("icon-chevron-right").resizable().scaledToFit().frame(width: 16, height: 16).foregroundColor(Color.zxF03)
@ -113,7 +113,7 @@ struct ProfileView: View {
}.foregroundColor(.primary)
ZXProfileDivider()
HStack {
Image(systemName: "externaldrive.fill").resizable().scaledToFit().frame(width: 20, height: 20).foregroundColor(Color.zxF05)
Image("icon-storage").resizable().scaledToFit().frame(width: 20, height: 20).foregroundColor(Color.zxF05)
VStack(alignment: .leading, spacing: 2) {
Text("存储空间").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF0)

View File

@ -16,7 +16,7 @@ struct QuizListView: View {
VStack(spacing: 12) { ProgressView().tint(Color.zxPurple); Text("加载中…").font(.system(size: 13)).foregroundColor(Color.zxF04) }.frame(maxWidth: .infinity, maxHeight: .infinity)
} else if quizzes.isEmpty {
VStack(spacing: 16) {
Image(systemName: "questionmark.circle").font(.system(size: 40)).foregroundColor(Color.zxF03)
Image("icon-question").font(.system(size: 40)).foregroundColor(Color.zxF03)
Text("暂无测验").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF04)
Text("基于知识库内容自动生成测验题目").font(.system(size: 12)).foregroundColor(Color.zxF03)
Button {

View File

@ -144,7 +144,7 @@ struct LearningSessionView: View {
private var tipsCard: some View {
VStack(alignment: .leading, spacing: 10) {
HStack(spacing: 8) {
Image(systemName: "lightbulb.fill").font(.system(size: 14)).foregroundColor(Color.zxYellow)
Image("icon-lightbulb").font(.system(size: 14)).foregroundColor(Color.zxYellow)
Text("学习小贴士").font(.system(size: 13, weight: .bold)).foregroundColor(Color.zxF0)
}
Text("保持专注25-30 分钟后休息 5 分钟能有效提升记忆效果。学习时尽量避免切换任务。")

View File

@ -98,7 +98,7 @@ struct ReviewCardView: View {
VStack(spacing: 6) {
Rectangle().fill(Color.zxBorder008).frame(height: 1).padding(.vertical, 12)
HStack(spacing: 4) {
Image(systemName: "book.closed.fill").font(.system(size: 10)).foregroundColor(Color.zxF03)
Image("icon-method").font(.system(size: 10)).foregroundColor(Color.zxF03)
Text(current.source).zxFontScaled(size: 11).foregroundColor(Color.zxF04)
}
}

View File

@ -18,7 +18,7 @@ struct StudyHomeView: View {
HStack {
Spacer()
HStack(spacing: 4) {
Image(systemName: "flame.fill")
Image("icon-flame")
.font(.system(size: 14)).foregroundColor(Color.zxOrange)
Text("\(streakDays) 天连续")
.font(.system(size: 13, weight: .bold)).foregroundColor(Color.zxOrange)
@ -55,14 +55,14 @@ struct StudyHomeView: View {
HStack(spacing: 12) {
NavigationLink(value: Route.aiChat) {
VStack(spacing: 6) {
Image(systemName: "sparkles").font(.system(size: 18)).foregroundColor(Color.zxPurple).frame(width: 44, height: 44)
Image("icon-sparkles").font(.system(size: 18)).foregroundColor(Color.zxPurple).frame(width: 44, height: 44)
Text("AI 问答").font(.system(size: 11)).foregroundColor(Color.zxF04)
}.frame(maxWidth: .infinity)
}.foregroundColor(.primary)
NavigationLink(value: Route.activeRecall) {
VStack(spacing: 6) {
Image(systemName: "brain.head.profile").font(.system(size: 18)).foregroundColor(Color.zxOrange).frame(width: 44, height: 44)
Image("icon-brain").font(.system(size: 18)).foregroundColor(Color.zxOrange).frame(width: 44, height: 44)
Text("自测").font(.system(size: 11)).foregroundColor(Color.zxF04)
}.frame(maxWidth: .infinity)
@ -82,7 +82,7 @@ struct StudyHomeView: View {
Text("今日任务").font(.system(size: 15, weight: .bold)).foregroundColor(Color.zxF0)
Spacer()
HStack(spacing: 4) {
Image(systemName: "calendar").font(.system(size: 12)).foregroundColor(Color.zxF04)
Image("icon-calendar").font(.system(size: 12)).foregroundColor(Color.zxF04)
Text("AI 自动排期").font(.system(size: 12)).foregroundColor(Color.zxF04)
}
}
@ -165,7 +165,7 @@ struct StudyHomeView: View {
private var dailyThinkingCard: some View {
VStack(alignment: .leading, spacing: 14) {
HStack {
Image(systemName: "sparkles").font(.system(size: 13)).foregroundColor(Color.zxPrimary)
Image("icon-sparkles").font(.system(size: 13)).foregroundColor(Color.zxPrimary)
.frame(width: 30, height: 30).background(Color.zxPrimarySoft).clipShape(RoundedRectangle(cornerRadius: ZXRadius.sm))
Text("每日思考题").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxInkPrimary)
Spacer()