feat(ios): 知识库列表卡片显示封面图
- ZLibraryCard 改用 coverUrl 显示封面图(56×56) - 无封面时回退到默认书本图标 - KnowledgeBase 模型新增 coverUrl 字段 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
d77a7fe50d
commit
587b61d564
@ -164,6 +164,7 @@ struct KnowledgeBase: Codable, Identifiable {
|
||||
let title: String
|
||||
let description: String?
|
||||
let coverKey: String?
|
||||
let coverUrl: String?
|
||||
let status: String?
|
||||
let itemCount: Int?
|
||||
let lastStudiedAt: String?
|
||||
|
||||
@ -36,7 +36,7 @@ struct LibraryHomeView: View {
|
||||
}
|
||||
ForEach(viewModel.knowledgeBases) { kb in
|
||||
NavigationLink(value: Route.libraryDetail(knowledgeBaseId: kb.id)) {
|
||||
ZLibraryCard(icon: "books.vertical.fill", name: kb.title, desc: kb.description ?? "", color: Color.zxPurple, items: kb.itemCount ?? 0, mastery: 50, tags: [], last: lastStudiedText(kb.lastStudiedAt))
|
||||
ZLibraryCard(coverUrl: kb.coverUrl, name: kb.title, desc: kb.description ?? "", items: kb.itemCount ?? 0, last: lastStudiedText(kb.lastStudiedAt))
|
||||
}
|
||||
}
|
||||
if viewModel.knowledgeBases.isEmpty && !viewModel.isLoading {
|
||||
@ -59,8 +59,33 @@ struct LibraryHomeView: View {
|
||||
return iso.prefix(10).description
|
||||
}
|
||||
}
|
||||
struct ZLibraryCard: View { let icon: String; let name: String; let desc: String; let color: Color; let items: Int; let mastery: Int; let tags: [String]; let last: String
|
||||
var body: some View { VStack(spacing: 0) { Rectangle().fill(ZXGradient.progressBar).frame(height: 3); HStack(spacing: 12) { Image(systemName: icon).font(.system(size: 20)).foregroundColor(color).frame(width: 44, height: 44).background(color.opacity(0.12)).clipShape(RoundedRectangle(cornerRadius: 13)).overlay(RoundedRectangle(cornerRadius: 13).stroke(color.opacity(0.3), lineWidth: 1)); VStack(alignment: .leading, spacing: 2) { Text(name).font(.system(size: 16, weight: .bold)).foregroundColor(Color.zxF0); Text(desc).font(.system(size: 12)).foregroundColor(Color.zxF04); Text("掌握 \(mastery)%").font(.system(size: 11)).foregroundColor(Color.zxF04) }; Spacer() }.padding(16); HStack { HStack(spacing: 4) { Image(systemName: "clock").font(.system(size: 10)); Text("\(items) 项 · \(last)").font(.system(size: 11)) }.foregroundColor(Color.zxF03); Spacer(); ForEach(tags.prefix(2), id: \.self) { t in Text(t).font(.system(size: 10, weight: .medium)).foregroundColor(Color.zxPurple).padding(.horizontal, 7).padding(.vertical, 2).background(Color(hex: "#7C6EFA", opacity: 0.08)).clipShape(Capsule()) } }.padding(.horizontal, 16).padding(.bottom, 12) }
|
||||
struct ZLibraryCard: View { let coverUrl: String?; let name: String; let desc: String; let items: Int; let last: String
|
||||
var body: some View { VStack(spacing: 0) {
|
||||
HStack(spacing: 12) {
|
||||
// 封面图
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 13).fill(Color.zxPurpleBG(0.12)).frame(width: 56, height: 56)
|
||||
if let url = coverUrl, let imageUrl = URL(string: url) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "books.vertical.fill").font(.system(size: 22)).foregroundColor(Color.zxPurple.opacity(0.5))
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(name).font(.system(size: 16, weight: .bold)).foregroundColor(Color.zxF0)
|
||||
if !desc.isEmpty { Text(desc).font(.system(size: 12)).foregroundColor(Color.zxF04).lineLimit(1) }
|
||||
}
|
||||
Spacer()
|
||||
}.padding(16)
|
||||
HStack {
|
||||
HStack(spacing: 4) { Image(systemName: "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)) }
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user