diff --git a/AIStudyApp/AIStudyApp.xcodeproj/project.xcworkspace/xcuserdata/Admin1.xcuserdatad/UserInterfaceState.xcuserstate b/AIStudyApp/AIStudyApp.xcodeproj/project.xcworkspace/xcuserdata/Admin1.xcuserdatad/UserInterfaceState.xcuserstate index 400b1d4..8e62750 100644 Binary files a/AIStudyApp/AIStudyApp.xcodeproj/project.xcworkspace/xcuserdata/Admin1.xcuserdatad/UserInterfaceState.xcuserstate and b/AIStudyApp/AIStudyApp.xcodeproj/project.xcworkspace/xcuserdata/Admin1.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AIStudyApp/AIStudyApp/Core/Models/APIModels.swift b/AIStudyApp/AIStudyApp/Core/Models/APIModels.swift index be2f283..a8a6501 100644 --- a/AIStudyApp/AIStudyApp/Core/Models/APIModels.swift +++ b/AIStudyApp/AIStudyApp/Core/Models/APIModels.swift @@ -630,6 +630,7 @@ struct CreateFolderRequest: Codable { struct KnowledgeSource: Codable, Identifiable { let id: String let knowledgeBaseId: String? + let fileId: String? let title: String? let originalFilename: String? let type: String? diff --git a/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift b/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift index 34dea9d..04bbd82 100644 --- a/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift +++ b/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift @@ -262,13 +262,12 @@ struct LibraryDetailPage: View { Text("暂无资料来源").font(.system(size: 14)).foregroundColor(Color.zxF03).padding(.top, 40) } else { ForEach(sources) { src in - NavigationLink(value: Route.materialDetail( - knowledgeBaseId: knowledgeBaseId, - fileName: src.originalFilename ?? src.title ?? "未命名", - fileType: materialTypeFromMime(src.mimeType), - fileSize: 0, + NavigationLink(value: Route.materialReader( + materialId: src.id, filePath: "", - uploadDate: src.createdAt + materialType: materialTypeFromMime(src.mimeType), + knowledgeBaseId: knowledgeBaseId, + title: src.originalFilename ?? src.title ?? "未命名" )) { HStack(spacing: 12) { Image(systemName: src.type == "file" ? "doc" : "link") diff --git a/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift b/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift index bbd58e7..aadf06b 100644 --- a/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift +++ b/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift @@ -109,10 +109,19 @@ struct MaterialReaderView: View { @Environment(\.scenePhase) private var scenePhase @State private var isParsing = false @State private var parseMessage = "" + @State private var downloadedFilePath: String? private let title: String private let knowledgeBaseId: String? + /// Resolved file path: uses downloaded temp file if original is empty/missing + private var resolvedPath: String { + if !vm.filePath.isEmpty && FileManager.default.fileExists(atPath: vm.filePath) { + return vm.filePath + } + return downloadedFilePath ?? vm.filePath + } + // V2 session manager (primary) + V1 collector (fallback) private let sessionManager = ReadingRuntimeSessionManager.shared private let collector = ReadingEventCollector.shared @@ -239,7 +248,30 @@ struct MaterialReaderView: View { .padding(.bottom, 100) } } - .task { await vm.load() } + .task { + if vm.filePath.isEmpty || !FileManager.default.fileExists(atPath: vm.filePath) { + if let kbId = knowledgeBaseId { + print("[MaterialReader] No local file, downloading from COS: \(vm.materialId)") + do { + let source = try await KnowledgeSourceService.shared.detail(kbId: kbId, id: vm.materialId) + if let fileId = source.fileId { + let downloadUrl = try await FileUploadService.shared.getDownloadUrl(fileId: fileId) + let url = URL(string: downloadUrl)! + let (data, _) = try await URLSession.shared.data(from: url) + let ext = source.originalFilename?.split(separator: ".").last.map(String.init) ?? "md" + let localURL = FileManager.default.temporaryDirectory + .appendingPathComponent("source_\(vm.materialId).\(ext)") + try data.write(to: localURL) + downloadedFilePath = localURL.path + print("[MaterialReader] Downloaded to: \(localURL.path), size: \(data.count)") + } + } catch { + print("[MaterialReader] COS download failed: \(error.localizedDescription)") + } + } + } + await vm.load() + } .sheet(isPresented: $showQuickLook) { QuickLookPreview(url: URL(fileURLWithPath: vm.filePath)) }