- 所有 SF Symbol .fill 图标替换为线性版本 - 自定义加载动画全部替换为原生 ProgressView/refreshable - StudyHomeView 重设计:优先级驱动主行动卡片 - ZLibraryCard 重新设计:封面图自适应、信息布局优化 - LibraryDetailPage:顶部KB信息区、···菜单、排序、长按操作 - 知识点列表:文件类型图标、学习时长、分割线样式 - 弥散渐变顶部背景 - 新增 icon-folder、icon-xmark SVG Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
185 lines
6.4 KiB
Swift
185 lines
6.4 KiB
Swift
import Combine
|
|
import Foundation
|
|
|
|
@MainActor
|
|
class LibraryViewModel: ObservableObject {
|
|
@Published var knowledgeBases: [KnowledgeBase] = []
|
|
@Published var isLoading = false
|
|
@Published var isRefreshing = false
|
|
@Published var isLoadingMore = false
|
|
@Published var errorMessage: String?
|
|
@Published var hasMore = true
|
|
|
|
private var currentPage = 1
|
|
private let pageSize = 20
|
|
|
|
var currentFilter: LibraryFilter = .all
|
|
|
|
enum LibraryFilter: String, CaseIterable { case all = "全部", mine = "我的", subscribed = "已订阅", official = "官方" }
|
|
|
|
func loadKnowledgeBases() async {
|
|
isLoading = true; errorMessage = nil; currentPage = 1
|
|
do {
|
|
knowledgeBases = try await fetchKBs(page: 1)
|
|
hasMore = knowledgeBases.count >= pageSize
|
|
} catch { if knowledgeBases.isEmpty { errorMessage = "加载知识库失败" } }
|
|
isLoading = false
|
|
}
|
|
|
|
func refresh() async {
|
|
isRefreshing = true; currentPage = 1
|
|
do { knowledgeBases = try await fetchKBs(page: 1); hasMore = knowledgeBases.count >= pageSize } catch {}
|
|
isRefreshing = false
|
|
}
|
|
|
|
func loadMore() async {
|
|
guard !isLoadingMore, hasMore else { return }
|
|
isLoadingMore = true; currentPage += 1
|
|
do {
|
|
let more = try await fetchKBs(page: currentPage)
|
|
knowledgeBases.append(contentsOf: more); hasMore = more.count >= pageSize
|
|
} catch { currentPage -= 1 }
|
|
isLoadingMore = false
|
|
}
|
|
|
|
func createKnowledgeBase(title: String, description: String?) async -> KnowledgeBase? {
|
|
do {
|
|
let kb = try await KnowledgeBaseService.shared.create(title: title, description: description)
|
|
knowledgeBases.insert(kb, at: 0)
|
|
ZXToastManager.shared.success("知识库已创建")
|
|
return kb
|
|
} catch {
|
|
ZXToastManager.shared.error("创建失败")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func deleteKnowledgeBase(id: String) async {
|
|
do {
|
|
_ = try await KnowledgeBaseService.shared.delete(id: id)
|
|
knowledgeBases.removeAll { $0.id == id }
|
|
ZXToastManager.shared.success("已删除")
|
|
} catch { ZXToastManager.shared.error("删除失败") }
|
|
}
|
|
|
|
func togglePin(id: String) async {
|
|
do {
|
|
let _: GenericSuccessResponse? = try? await APIClient.shared.request("/knowledge-bases/\(id)/pin", method: "POST")
|
|
await loadKnowledgeBases()
|
|
} catch {}
|
|
}
|
|
|
|
private func fetchKBs(page: Int) async throws -> [KnowledgeBase] {
|
|
switch currentFilter {
|
|
case .all: return try await KnowledgeBaseService.shared.list(page: page, limit: pageSize)
|
|
case .mine: return try await KnowledgeBaseService.shared.list(page: page, limit: pageSize) // default is user's own
|
|
case .subscribed: return try await KnowledgeBaseService.shared.listSubscribed(page: page, limit: pageSize)
|
|
case .official: return [] // TODO: when backend supports ownerType=official
|
|
}
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
class LibraryDetailViewModel: ObservableObject {
|
|
@Published var items: [KnowledgeItem] = []
|
|
@Published var knowledgeBase: KnowledgeBase?
|
|
@Published var isLoading = false
|
|
@Published var isRefreshing = false
|
|
@Published var isLoadingMore = false
|
|
@Published var errorMessage: String?
|
|
@Published var hasMore = true
|
|
|
|
private var currentPage = 1
|
|
private let pageSize = 20
|
|
|
|
func loadItems(knowledgeBaseId: String) async {
|
|
isLoading = true
|
|
errorMessage = nil
|
|
currentPage = 1
|
|
do {
|
|
async let kb = try? KnowledgeBaseService.shared.detail(id: knowledgeBaseId)
|
|
async let list = try? KnowledgeItemService.shared.list(knowledgeBaseId: knowledgeBaseId)
|
|
let (kbResult, listResult) = await (kb, list)
|
|
knowledgeBase = kbResult
|
|
items = listResult ?? []
|
|
hasMore = items.count >= pageSize
|
|
} catch {
|
|
if items.isEmpty { errorMessage = "加载知识点失败" }
|
|
}
|
|
isLoading = false
|
|
}
|
|
|
|
func refresh(knowledgeBaseId: String) async {
|
|
isRefreshing = true
|
|
currentPage = 1
|
|
do {
|
|
items = try await KnowledgeItemService.shared.list(knowledgeBaseId: knowledgeBaseId)
|
|
hasMore = items.count >= pageSize
|
|
} catch {}
|
|
isRefreshing = false
|
|
}
|
|
|
|
func loadMore(knowledgeBaseId: String) async {
|
|
guard !isLoadingMore, hasMore else { return }
|
|
isLoadingMore = true
|
|
currentPage += 1
|
|
do {
|
|
let more = try await KnowledgeItemService.shared.list(knowledgeBaseId: knowledgeBaseId)
|
|
items.append(contentsOf: more)
|
|
hasMore = more.count >= pageSize
|
|
} catch {
|
|
currentPage -= 1
|
|
}
|
|
isLoadingMore = false
|
|
}
|
|
|
|
func loadKnowledgeBase(id: String) async {
|
|
do {
|
|
knowledgeBase = try await KnowledgeBaseService.shared.detail(id: id)
|
|
} catch {}
|
|
}
|
|
|
|
func deleteKnowledgeBase(id: String) async {
|
|
do {
|
|
_ = try await KnowledgeBaseService.shared.delete(id: id)
|
|
ZXToastManager.shared.success("知识库已删除")
|
|
} catch {
|
|
ZXToastManager.shared.error("删除失败")
|
|
}
|
|
}
|
|
|
|
func addItem(knowledgeBaseId: String, title: String, content: String?) async -> KnowledgeItem? {
|
|
do {
|
|
let item = try await KnowledgeItemService.shared.create(
|
|
knowledgeBaseId: knowledgeBaseId, title: title, content: content
|
|
)
|
|
items.append(item)
|
|
ZXToastManager.shared.success("知识点已添加")
|
|
return item
|
|
} catch {
|
|
ZXToastManager.shared.error("添加失败")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func deleteItem(id: String) async {
|
|
do {
|
|
try await KnowledgeItemService.shared.delete(id: id)
|
|
items.removeAll { $0.id == id }
|
|
ZXToastManager.shared.success("知识点已删除")
|
|
} catch {
|
|
ZXToastManager.shared.error("删除失败")
|
|
}
|
|
}
|
|
|
|
func batchDeleteItems(ids: [String]) async {
|
|
do {
|
|
let resp = try await KnowledgeItemService.shared.batchDelete(ids: ids)
|
|
items.removeAll { ids.contains($0.id) }
|
|
ZXToastManager.shared.success(resp.message ?? "已删除")
|
|
} catch {
|
|
ZXToastManager.shared.error("批量删除失败")
|
|
}
|
|
}
|
|
}
|