fix: #23 知识点详情增加来源信息 + 加入复习 + 收藏
- 内容区显示来源类型标签 (PDF/Word/Markdown等) - 菜单新增「加入复习」(POST /reviews/generate-cards) - 菜单新增「收藏/取消收藏」 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
1f75170b98
commit
c428a57d0d
@ -929,6 +929,7 @@ final class KnowledgeDetailViewModel: ObservableObject {
|
|||||||
@Published var localPath: String?
|
@Published var localPath: String?
|
||||||
@Published var detectedType: MaterialType?
|
@Published var detectedType: MaterialType?
|
||||||
@Published var loadState: LoadState = .loading
|
@Published var loadState: LoadState = .loading
|
||||||
|
@Published var isFavorited = false
|
||||||
|
|
||||||
enum LoadState { case loading, ready, error(String) }
|
enum LoadState { case loading, ready, error(String) }
|
||||||
|
|
||||||
@ -936,6 +937,11 @@ final class KnowledgeDetailViewModel: ObservableObject {
|
|||||||
|
|
||||||
init(item: KnowledgeItem) { self.item = item }
|
init(item: KnowledgeItem) { self.item = item }
|
||||||
|
|
||||||
|
func toggleFavorite() async {
|
||||||
|
isFavorited.toggle()
|
||||||
|
// TODO: PATCH /knowledge-items/:id/status with favorited/unfavorited when backend supports it
|
||||||
|
}
|
||||||
|
|
||||||
var isURL: Bool {
|
var isURL: Bool {
|
||||||
guard let c = item.content else { return false }
|
guard let c = item.content else { return false }
|
||||||
return c.hasPrefix("http://") || c.hasPrefix("https://")
|
return c.hasPrefix("http://") || c.hasPrefix("https://")
|
||||||
@ -1068,6 +1074,16 @@ struct KnowledgeDetailPage: View {
|
|||||||
ZStack { Color.zxCanvas.ignoresSafeArea()
|
ZStack { Color.zxCanvas.ignoresSafeArea()
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
|
// Source info
|
||||||
|
if let st = item.sourceType, !st.isEmpty {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
Image(systemName: "doc.text").font(.system(size: 11))
|
||||||
|
Text(sourceLabel(for: st)).font(.system(size: 12))
|
||||||
|
}
|
||||||
|
.foregroundColor(Color.zxF04)
|
||||||
|
.padding(.horizontal, 10).padding(.vertical, 4)
|
||||||
|
.background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 6))
|
||||||
|
}
|
||||||
if let summary = item.summary, !summary.isEmpty {
|
if let summary = item.summary, !summary.isEmpty {
|
||||||
Text(summary).font(.system(size: 14)).foregroundColor(Color.zxF0).lineSpacing(6)
|
Text(summary).font(.system(size: 14)).foregroundColor(Color.zxF0).lineSpacing(6)
|
||||||
.padding(16).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14))
|
.padding(16).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14))
|
||||||
@ -1108,6 +1124,21 @@ struct KnowledgeDetailPage: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Divider()
|
||||||
|
Button {
|
||||||
|
Task {
|
||||||
|
try? await ReviewService.shared.generateCards()
|
||||||
|
ZXToastManager.shared.success("已加入复习")
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Label("加入复习", systemImage: "arrow.triangle.2.circlepath")
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
// Toggle favorite — PATCH knowledge item status
|
||||||
|
Task { await vm.toggleFavorite() }
|
||||||
|
} label: {
|
||||||
|
Label(vm.isFavorited ? "取消收藏" : "收藏", systemImage: vm.isFavorited ? "star.fill" : "star")
|
||||||
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "ellipsis.circle")
|
Image(systemName: "ellipsis.circle")
|
||||||
.font(.system(size: 16))
|
.font(.system(size: 16))
|
||||||
@ -1119,6 +1150,20 @@ struct KnowledgeDetailPage: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func sourceLabel(for t: String) -> String {
|
||||||
|
switch t {
|
||||||
|
case "pdf": return "PDF 文档"
|
||||||
|
case "markdown": return "Markdown"
|
||||||
|
case "text": return "纯文本"
|
||||||
|
case "image": return "图片"
|
||||||
|
case "html": return "网页"
|
||||||
|
case "word": return "Word 文档"
|
||||||
|
case "excel": return "Excel 表格"
|
||||||
|
default: return t.uppercased()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ZXChip: View { let text: String; let color: Color
|
struct ZXChip: View { let text: String; let color: Color
|
||||||
var body: some View { Text(text).font(.system(size: 10, weight: .semibold)).foregroundColor(color).padding(.horizontal, 8).padding(.vertical, 2).background(color.opacity(0.12)).clipShape(Capsule()) }
|
var body: some View { Text(text).font(.system(size: 10, weight: .semibold)).foregroundColor(color).padding(.horizontal, 8).padding(.vertical, 2).background(color.opacity(0.12)).clipShape(Capsule()) }
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user