#if os(iOS) import SwiftUI struct BookListView: View { @ObservedObject var importer: BundleImporter @ObservedObject var vm: LibraryViewModel @State private var selected: BookMeta? = nil private func bundleDir(of id: String) -> URL? { // 取最新导入目录 guard let root = try? FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("ImportedBundle") else { return nil } let subs = (try? FileManager.default.contentsOfDirectory(at: root, includingPropertiesForKeys: nil)) ?? [] return subs.sorted { $0.lastPathComponent > $1.lastPathComponent }.first } var body: some View { VStack(spacing: 0) { HStack { TextField("搜索书名/作者", text: $vm.searchText) .textFieldStyle(.roundedBorder) Button("导入") { importer.presentPicker() } if let msg = importer.progressMessage { Text(msg).font(.footnote).foregroundColor(.secondary) } }.padding(.horizontal).padding(.top,8) Divider() if vm.filteredBooks.isEmpty { EmptyStateView(message: "无数据,点击导入按钮加载 ZIP", actionTitle: "导入") { importer.presentPicker() } .frame(maxWidth: .infinity, maxHeight: .infinity) } else { List(vm.filteredBooks) { book in Button { selected = book } label: { HStack(alignment:.top, spacing:12) { if let dir = bundleDir(of: book.id) { CoverImageView(book: book, bundleDir: dir).frame(width:70,height:100) } VStack(alignment:.leading, spacing:4) { Text(book.title).font(.headline) Text(book.author).font(.subheadline).foregroundColor(.secondary) if let rt = book.readtime_year { Text("全年阅读: \(rt/60) 小时").font(.caption).foregroundColor(.secondary) } if book.is_finished_this_year == true { Text("今年已读完 ✅").font(.caption2).foregroundColor(.green) } } Spacer() } } } } } .sheet(item: $selected) { b in if let idx = importer.bundleIndex, let dir = bundleDir(of: b.id) { BookDetailView(book: b, index: idx, bundleDir: dir) } else { Text("数据缺失") } } } } #endif