diff --git a/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift b/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift index 997c14a..d8026a6 100644 --- a/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift +++ b/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift @@ -1109,6 +1109,28 @@ struct KnowledgeDetailPage: View { .padding(16).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14)) } Text(content).font(.system(size: 14)).foregroundColor(Color.zxF0).lineSpacing(6) + + // 阅读原文件 button + if let path = vm.localPath ?? (try? writeTempFile(content: content, itemId: item.id)), let mt = vm.detectedType ?? detectTypeFromContent(content, sourceType: item.sourceType) { + NavigationLink(value: Route.materialReader( + materialId: item.id, + filePath: path, + materialType: mt, + knowledgeBaseId: item.knowledgeBaseId, + title: item.title + )) { + HStack(spacing: 8) { + Image(systemName: "book") + Text("阅读原文件") + } + .font(.system(size: 15, weight: .bold)) + .foregroundColor(.white) + .frame(maxWidth: .infinity).frame(height: 48) + .background(LinearGradient(colors: [Color.zxPurple, Color.zxAccent], startPoint: .leading, endPoint: .trailing)) + .clipShape(RoundedRectangle(cornerRadius: 14)) + } + .padding(.top, 8) + } }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 100) }.scrollIndicators(.hidden) } @@ -1452,3 +1474,30 @@ struct EditKnowledgePage: View { }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) } } + +// MARK: - Helpers + +private func writeTempFile(content: String, itemId: String) throws -> String { + let dir = FileManager.default.temporaryDirectory + let url = dir.appendingPathComponent("kd_text_\(itemId).md") + try content.write(to: url, atomically: true, encoding: .utf8) + return url.path +} + +private func detectTypeFromContent(_ content: String, sourceType: String?) -> MaterialType? { + if let st = sourceType { + switch st.lowercased() { + case "markdown", "md": return .markdown + case "txt", "text": return .text + case "pdf": return .pdf + case "epub": return .epub + case "docx", "doc": return .word + case "xlsx", "xls": return .excel + case "pptx", "ppt": return .powerPoint + default: break + } + } + // Detect from content + if content.hasPrefix("#") || content.contains("```") { return .markdown } + return .text +}