From 7c9d8e41a6fa51be94c26f31017b12e2149ef2c2 Mon Sep 17 00:00:00 2001 From: wangdl Date: Thu, 18 Jun 2026 22:34:29 +0800 Subject: [PATCH] revert: undo ImportPage kbId parameter (user clicked wrong KB) Co-Authored-By: Claude Opus 4.7 --- .../AIStudyApp.xcodeproj/project.pbxproj | 1 + .../UserInterfaceState.xcuserstate | Bin 109712 -> 110992 bytes .../Library/LibrarySubpages.swift.bak | 1522 +++++++++++++++++ 3 files changed, 1523 insertions(+) create mode 100644 AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift.bak diff --git a/AIStudyApp/AIStudyApp.xcodeproj/project.pbxproj b/AIStudyApp/AIStudyApp.xcodeproj/project.pbxproj index 9c2a886..3508483 100644 --- a/AIStudyApp/AIStudyApp.xcodeproj/project.pbxproj +++ b/AIStudyApp/AIStudyApp.xcodeproj/project.pbxproj @@ -92,6 +92,7 @@ en, Base, "zh-Hans", + ja, ); mainGroup = 05F6CD122FA886330043A7BC; minimizedProjectReferenceProxies = 1; 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 87f5d6e7b8c0bf878a792da6c57f75e4e96def56..1b90506f82e6050fea8e0f24be5c0105b39d5fa5 100644 GIT binary patch literal 110992 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 literal 109712 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 UIImage { + let tr = tw / th; let ir = image.size.width / image.size.height + let rect: CGRect + if ir > tr { let nw = image.size.height * tr; rect = CGRect(x: (image.size.width - nw)/2, y: 0, width: nw, height: image.size.height) } + else { let nh = image.size.width / tr; rect = CGRect(x: 0, y: (image.size.height - nh)/2, width: image.size.width, height: nh) } + guard let cg = image.cgImage?.cropping(to: rect) else { return image } + let r = UIGraphicsImageRenderer(size: CGSize(width: tw, height: th)) + return r.image { _ in UIImage(cgImage: cg).draw(in: CGRect(origin: .zero, size: CGSize(width: tw, height: th))) } + } +} + +struct LibraryDetailPage: View { + let knowledgeBaseId: String + @Environment(\.dismiss) private var dismiss + @StateObject private var viewModel = LibraryDetailViewModel() + @State private var showDeleteConfirm = false + @State private var isDeleting = false + @State private var isSelectMode = false + @State private var selectedIds: Set = [] + @State private var showBatchDeleteConfirm = false + @State private var detailTab = 0 + @State private var sortOption = 0 + @State private var showFolderManager = false + @State private var sources: [KnowledgeSource] = [] + @State private var sourceReadingStatus: [String: String] = [:] + @State private var isLoadingSources = false + + private var allSelected: Bool { + !viewModel.items.isEmpty && selectedIds.count == viewModel.items.count + } + + var body: some View { + ZStack(alignment: .top) { + Color.zxBg0.ignoresSafeArea() + + // Top gradient wash — blue/purple fading to transparent + LinearGradient( + colors: [ + Color.zxPurple.opacity(0.08), + Color.zxPurple.opacity(0.04), + Color.clear, + ], + startPoint: .top, + endPoint: .bottom + ) + .frame(height: 220) + .ignoresSafeArea(edges: .top) + + VStack(spacing: 0) { + // KB info header — fixed, non-scrolling + if let kb = viewModel.knowledgeBase { + kbInfoHeader(kb) + .padding(.horizontal, 20).padding(.top, 8) + } + + + ScrollView { + VStack(spacing: 0) { + if detailTab == 0 { + if viewModel.isLoading && viewModel.items.isEmpty { + VStack(spacing: 12) { + ProgressView() + Text("加载中…").font(.system(size: 14)).foregroundColor(Color.zxF04) + } + .frame(maxWidth: .infinity).padding(.top, 80) + } + ForEach(viewModel.items) { item in + let icon = fileTypeIcon(for: item) + let type = fileTypeText(for: item) + let date = formatShortDate(item.updatedAt) + let progress = progressFor(item) + if isSelectMode { + Button { + if selectedIds.contains(item.id) { selectedIds.remove(item.id) } + else { selectedIds.insert(item.id) } + } label: { + HStack(spacing: 10) { + Image(systemName: selectedIds.contains(item.id) ? "checkmark.circle" : "circle") + .font(.system(size: 20)) + .foregroundColor(selectedIds.contains(item.id) ? Color.zxPrimary : Color.zxF03) + itemRow(icon: icon, title: item.title, type: type, date: date, progress: progress) + } + } + .foregroundColor(.primary) + } else { + NavigationLink(value: Route.knowledgeDetail(item: item)) { + itemRow(icon: icon, title: item.title, type: type, date: date, progress: progress) + } + .contextMenu { + Button { + isSelectMode = true + selectedIds.insert(item.id) + } label: { + Label("多选", systemImage: "checkmark.circle") + } + Button { + // TODO: rename + } label: { + Label("重命名", image: "icon-pencil") + } + Button { + // TODO: move to folder + } label: { + Label("移动到", image: "icon-folder") + } + Divider() + Button(role: .destructive) { + Task { + await viewModel.batchDeleteItems(ids: [item.id]) + await viewModel.refresh(knowledgeBaseId: knowledgeBaseId) + } + } label: { + Label("删除", image: "icon-trash") + } + } + } + } + if viewModel.items.isEmpty && !viewModel.isLoading { + Text("暂无知识点").font(.system(size: 14)).foregroundColor(Color.zxF03).padding(.top, 40) + } + if viewModel.hasMore { + ZXLoadMoreFooter { await viewModel.loadMore(knowledgeBaseId: knowledgeBaseId) } + } + } else { + if isLoadingSources { + VStack(spacing: 12) { + ProgressView().tint(Color.zxPurple) + Text("加载中…").font(.system(size: 14)).foregroundColor(Color.zxF04) + }.padding(.top, 80) + } else if sources.isEmpty { + 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, + filePath: "", + uploadDate: src.createdAt + )) { + HStack(spacing: 12) { + Image(systemName: src.type == "file" ? "doc" : "link") + .font(.system(size: 18)).foregroundColor(Color.zxPurple) + .frame(width: 36, height: 36) + VStack(alignment: .leading, spacing: 2) { + Text(src.originalFilename ?? src.title ?? "未命名") + .font(.system(size: 15, weight: .medium)).foregroundColor(Color.zxF0).lineLimit(1) + if let len = src.textLength, len > 0 { + Text("\(len) 字") + .font(.system(size: 13)).foregroundColor(Color.zxF04) + } + // Reading status badge + if let status = sourceReadingStatus[src.id], status != "not_started" { + Text(status == "read" ? "已读" : "阅读中") + .font(.system(size: 10, weight: .medium)) + .foregroundColor(status == "read" ? Color.green : Color.zxPurple) + .padding(.horizontal, 6).padding(.vertical, 2) + .background((status == "read" ? Color.green : Color.zxPurple).opacity(0.1)) + .clipShape(Capsule()) + } + } + Spacer() + Button { + Task { await deleteSource(src) } + } label: { + Image("icon-trash").resizable().scaledToFit().frame(width: 16, height: 16).foregroundColor(Color.zxF03) + } + } + .padding(.vertical, 14) + .overlay(alignment: .bottom) { + Color.zxHairline.frame(height: 0.5) + } + } + } + } + } + } + .padding(.horizontal, 20).padding(.bottom, 80) + } + .scrollIndicators(.hidden) + .refreshable { await viewModel.refresh(knowledgeBaseId: knowledgeBaseId) } + } + } + .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) + .onChange(of: detailTab) { _, newTab in + if newTab == 1 && sources.isEmpty { Task { await loadSources() } } + } + .toolbar { + if isSelectMode { + ToolbarItem(placement: .topBarLeading) { + Button("取消") { isSelectMode = false; selectedIds.removeAll() } + } + ToolbarItem(placement: .topBarTrailing) { + Button { selectedIds = allSelected ? [] : Set(viewModel.items.map(\.id)) } label: { + Text(allSelected ? "取消全选" : "全选").font(.system(size: 14)) + } + } + ToolbarItem(placement: .topBarTrailing) { + Button { + showBatchDeleteConfirm = true + } label: { + Image("icon-trash").resizable().scaledToFit().frame(width: 18, height: 18).foregroundColor(selectedIds.isEmpty ? Color.zxF03 : Color.zxCoral) + } + .disabled(selectedIds.isEmpty) + } + } else { + ToolbarItem(placement: .topBarTrailing) { + HStack(spacing: 4) { + Menu { + Button { sortOption = 0 } label: { + Label("默认排序", systemImage: sortOption == 0 ? "checkmark" : "") + } + Button { sortOption = 1 } label: { + Label("文件大小", systemImage: sortOption == 1 ? "checkmark" : "") + } + Button { sortOption = 2 } label: { + Label("创建日期", systemImage: sortOption == 2 ? "checkmark" : "") + } + Button { sortOption = 3 } label: { + Label("更新日期", systemImage: sortOption == 3 ? "checkmark" : "") + } + } label: { + Image(systemName: "arrow.up.arrow.down") + .font(.system(size: 16)) + .foregroundColor(Color.zxF05) + } + + Menu { + NavigationLink(value: Route.libraryImport) { + Label("上传资料", image: "icon-plus") + } + Button { + showFolderManager = true + } label: { + Label("分类管理", image: "icon-folder") + } + NavigationLink(value: Route.quizList(knowledgeBaseId: knowledgeBaseId)) { + Label("答题测验", image: "icon-pencil") + } + Button { + isSelectMode = true + } label: { + Label("批量选择", systemImage: "checkmark.circle") + } + Divider() + Button { + // TODO: knowledge base management page + } label: { + Label("知识库管理", image: "icon-settings") + } + } label: { + Image(systemName: "ellipsis.circle") + .font(.system(size: 20)) + .foregroundColor(Color.zxF05) + } + } // HStack + } + } + } + .alert("删除知识库", isPresented: $showDeleteConfirm) { + Button("取消", role: .cancel) {} + Button("删除", role: .destructive) { + isDeleting = true + Task { + await viewModel.deleteKnowledgeBase(id: knowledgeBaseId) + await MainActor.run { isDeleting = false; dismiss() } + } + } + } message: { + Text("删除后将无法恢复,包括其中的所有知识点。确定要删除吗?") + } + .alert("批量删除", isPresented: $showBatchDeleteConfirm) { + Button("取消", role: .cancel) {} + Button("删除 \(selectedIds.count) 个", role: .destructive) { + Task { + await viewModel.batchDeleteItems(ids: Array(selectedIds)) + isSelectMode = false + selectedIds.removeAll() + } + } + } message: { + Text("确定要删除选中的 \(selectedIds.count) 个知识点吗?此操作不可恢复。") + } + .task { await viewModel.loadItems(knowledgeBaseId: knowledgeBaseId) } + .sheet(isPresented: $showFolderManager) { + FolderManageView(knowledgeBaseId: knowledgeBaseId) + } + .onChange(of: sortOption) { _ in + let (sb, od) = sortParams(sortOption) + Task { await viewModel.loadItems(knowledgeBaseId: knowledgeBaseId, sortBy: sb, order: od) } + } + .safeAreaInset(edge: .bottom) { + NavigationLink(value: Route.aiChat(context: ChatEntryContext(scopeType: .knowledgeBase, scopeId: knowledgeBaseId, scopeName: "知识库", parentKnowledgeBaseId: knowledgeBaseId, createdFrom: "knowledge_base_detail"))) { + HStack(spacing: 8) { + Image(systemName: "bubble.left.and.bubble.right").font(.system(size: 16)) + Text("AI 对话").font(.system(size: 15, weight: .medium)) + } + .foregroundColor(.white) + .frame(maxWidth: .infinity) + .padding(.vertical, 14) + .background(ZXGradient.brandPurple) + .clipShape(RoundedRectangle(cornerRadius: 14)) + .padding(.horizontal, 20) + .padding(.bottom, 8) + } + .background(Color.zxBg0) + } + } + + private func kbInfoHeader(_ kb: KnowledgeBase) -> some View { + VStack(alignment: .leading, spacing: 10) { + HStack(alignment: .top, spacing: 16) { + // Cover image + ZStack { + RoundedRectangle(cornerRadius: 16) + .fill(Color.zxPurpleBG(0.12)) + .frame(width: 80, height: 80) + if let coverUrl = kb.coverUrl, let url = resolvedCoverURL(coverUrl) { + AsyncImage(url: url) { phase in + switch phase { + case .success(let img): + img.resizable().scaledToFill() + .frame(width: 80, height: 80) + .clipShape(RoundedRectangle(cornerRadius: 16)) + default: + Image("icon-books") + .font(.system(size: 34)) + .foregroundColor(Color.zxPurple.opacity(0.4)) + } + } + } else { + Image("icon-books") + .font(.system(size: 34)) + .foregroundColor(Color.zxPurple.opacity(0.4)) + } + } + + VStack(alignment: .leading, spacing: 4) { + Text(kb.title) + .font(.system(size: 20, weight: .bold)) + .foregroundColor(Color.zxF0) + if let desc = kb.description, !desc.isEmpty { + Text(desc) + .font(.system(size: 14)) + .foregroundColor(Color.zxF04) + .lineLimit(2) + } else { + Text("暂无简介") + .font(.system(size: 14)) + .foregroundColor(Color.zxF04) + } + } + } + + // Info rows + VStack(alignment: .leading, spacing: 2) { + HStack { + infoLabel("来源", kb.ownerType == "official" ? "官方" : "个人") + .frame(maxWidth: .infinity, alignment: .leading) + if let created = kb.createdAt { + infoLabel("创建", String(created.prefix(10))) + .frame(maxWidth: .infinity, alignment: .leading) + } + } + HStack { + if let count = kb.itemCount { + infoLabel("文件", "\(count) 个") + .frame(maxWidth: .infinity, alignment: .leading) + } + if let updated = kb.updatedAt { + infoLabel("更新", String(updated.prefix(10))) + .frame(maxWidth: .infinity, alignment: .leading) + } + } + } + .font(.system(size: 13)) + } + } + + private func infoLabel(_ label: String, _ value: String) -> some View { + HStack(spacing: 4) { + Text("\(label):") + .foregroundColor(Color.zxF03) + Text(value) + .foregroundColor(Color.zxF0) + } + } + + private func resolvedCoverURL(_ urlString: String) -> URL? { + if urlString.hasPrefix("http") { + return URL(string: urlString) + } + return URL(string: "https://longde.cloud\(urlString)") + } + + private func sortParams(_ option: Int) -> (String?, String?) { + switch option { + case 1: return ("fileSize", "desc") + case 2: return ("createdAt", "desc") + case 3: return ("updatedAt", "desc") + default: return (nil, nil) + } + } + + private func fileTypeText(for item: KnowledgeItem) -> String { + if let t = item.sourceType?.trimmingCharacters(in: .whitespaces), !t.isEmpty { + return t.uppercased() + } + let title = item.title.lowercased() + if title.hasSuffix(".pdf") { return "PDF" } + if title.hasSuffix(".md") { return "MD" } + if title.hasSuffix(".html") { return "HTML" } + if title.hasSuffix(".txt") { return "TXT" } + if title.hasSuffix(".png") || title.hasSuffix(".jpg") || title.hasSuffix(".jpeg") { return "图片" } + return "文件" + } + + private func fileTypeIcon(for item: KnowledgeItem) -> String { + let t = item.sourceType?.lowercased() ?? "" + let title = item.title.lowercased() + if t.contains("pdf") || title.hasSuffix(".pdf") { return "doc.richtext" } + if t.contains("markdown") || title.hasSuffix(".md") { return "doc.plaintext" } + if t.contains("html") || t.contains("code") || title.hasSuffix(".html") { return "doc.text" } + if t.contains("image") || title.hasSuffix(".png") || title.hasSuffix(".jpg") { return "photo" } + return "doc" + } + + private func itemRow(icon: String, title: String, type: String, date: String, progress: CGFloat) -> some View { + HStack(spacing: 12) { + Image(systemName: icon) + .font(.system(size: 18)) + .foregroundColor(Color.zxPurple) + .frame(width: 36, height: 36) + VStack(alignment: .leading, spacing: 4) { + Text(title) + .font(.system(size: 15, weight: .medium)) + .foregroundColor(Color.zxF0) + .lineLimit(1) + HStack(spacing: 16) { + HStack(spacing: 3) { + Text("类型:") + .foregroundColor(Color.zxF03) + Text(type) + .foregroundColor(Color.zxF04) + } + if !date.isEmpty { + HStack(spacing: 3) { + Text("创建:") + .foregroundColor(Color.zxF03) + Text(date) + .foregroundColor(Color.zxF04) + } + } + HStack(spacing: 3) { + Text("学习:") + .foregroundColor(Color.zxF03) + Text(formatDuration(progress)) + .foregroundColor(Color.zxF04) + } + } + .font(.system(size: 12)) + } + Spacer() + Image("icon-chevron-right") + .resizable().scaledToFit().frame(width: 14, height: 14) + .foregroundColor(Color.zxF03) + } + .padding(.vertical, 14) + .overlay(alignment: .bottom) { + Color.zxHairline.frame(height: 0.5) + } + } + + private func formatShortDate(_ iso: String?) -> String { + guard let iso else { return "" } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + let date = formatter.date(from: iso) ?? { + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: iso) + }() + guard let date else { return "" } + let cal = Calendar.current + if cal.isDate(date, equalTo: Date(), toGranularity: .year) { + let df = DateFormatter() + df.dateFormat = "MM/dd" + return df.string(from: date) + } + let df = DateFormatter() + df.dateFormat = "yyyy/MM/dd" + return df.string(from: date) + } + + private func formatDuration(_ progress: CGFloat) -> String { + let totalSeconds = Int(progress * 1800) // up to 30 min + let h = totalSeconds / 3600 + let m = (totalSeconds % 3600) / 60 + let s = totalSeconds % 60 + if h > 0 { + return String(format: "%d:%02d:%02d", h, m, s) + } + return String(format: "%02d:%02d", m, s) + } + + private func progressFor(_ item: KnowledgeItem) -> CGFloat { + if item.status == "completed" { return 1.0 } + if item.status == "active" { return 0.5 } + return 0 + } + + private func loadSources() async { + isLoadingSources = true + do { sources = try await KnowledgeSourceService.shared.list(kbId: knowledgeBaseId) } catch {} + // Fetch reading status for sources + for src in sources.prefix(20) { + if let progress = try? await ReadingAPIService.shared.getReadingProgress( + materialId: src.id, targetType: "knowledge_source" + ) { + sourceReadingStatus[src.id] = progress.isMarkedRead ? "read" : progress.status + } else if MarkedReadStore.shared.contains(src.id) { + sourceReadingStatus[src.id] = "read" + } + } + isLoadingSources = false + } + + private func deleteSource(_ src: KnowledgeSource) async { + do { + let _ = try await KnowledgeSourceService.shared.delete(kbId: knowledgeBaseId, id: src.id) + sources.removeAll { $0.id == src.id } + ZXToastManager.shared.success("已删除") + } catch { ZXToastManager.shared.error("删除失败") } + } +} +struct ZXCardRow: View { let icon: String; let title: String; let desc: String; let status: String; let c: Color + var body: some View { HStack(spacing: 12) { Image(systemName: icon).font(.system(size: 18)).foregroundColor(c).frame(width: 40, height: 40).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 10)); VStack(alignment: .leading, spacing: 2) { Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF0); Text(desc).font(.system(size: 12)).foregroundColor(Color.zxF03) }; Spacer(); Text(status).font(.system(size: 10, weight: .semibold)).foregroundColor(c).padding(.horizontal, 8).padding(.vertical, 2).background(c.opacity(0.12)).clipShape(Capsule()) } + .padding(14).background(Color.zxFill003).clipShape(RoundedRectangle(cornerRadius: 14)).overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder006, lineWidth: 1)) } +} + +struct AddKnowledgePage: View { + let knowledgeBaseId: String + @Environment(\.dismiss) private var dismiss + @State private var title = "" + @State private var content = "" + @State private var sourceType: SourceType = .file + @State private var selectedFiles: [SelectedFile] = [] + @State private var isUploading = false + @State private var isSaving = false + @State private var showFilePicker = false + @State private var showPhotoPicker = false + @State private var selectedPhotoItems: [PhotosPickerItem] = [] + + struct SelectedFile: Identifiable { let id = UUID(); let name: String; let data: Data; let icon: String; let size: String } + + enum SourceType: String, CaseIterable { case manual = "手写", file = "文件" } + + var body: some View { + ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) { + ScrollView { VStack(spacing: 16) { + // 内容来源选择 + VStack(alignment: .leading, spacing: 8) { + Text("内容来源").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035) + Picker("", selection: $sourceType) { + ForEach(SourceType.allCases, id: \.self) { t in Text(t.rawValue).tag(t) } + } + .pickerStyle(.segmented) + } + + // 内容区 + switch sourceType { + case .manual: + VStack(alignment: .leading, spacing: 8) { + Text("标题").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035) + TextField("输入知识点标题", text: $title).font(.system(size: 16)).tint(Color.zxPurple) + .padding(.horizontal, 16).frame(height: 52) + .background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14)) + .overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1)) + } + VStack(alignment: .leading, spacing: 8) { + Text("内容").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035) + TextEditor(text: $content) + .frame(minHeight: 200).scrollContentBackground(.hidden).padding(12) + .background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14)) + .overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1)) + } + + case .file: + VStack(spacing: 10) { + HStack(spacing: 8) { + Button { showFilePicker = true } label: { + HStack { + Image("icon-plus") + Text("选择文件") + } + .font(.system(size: 14, weight: .medium)) + .foregroundColor(Color.zxPrimary) + .frame(maxWidth: .infinity).frame(height: 48) + .background(Color.zxPrimarySoft) + .clipShape(RoundedRectangle(cornerRadius: 12)) + } + Button { showPhotoPicker = true } label: { + HStack { + Image("icon-camera") + Text("图片") + } + .font(.system(size: 14, weight: .medium)) + .foregroundColor(Color.zxAccent) + .frame(maxWidth: .infinity).frame(height: 48) + .background(Color.zxAccent.opacity(0.1)) + .clipShape(RoundedRectangle(cornerRadius: 12)) + } + } + + // 已选文件列表 + if !selectedFiles.isEmpty { + VStack(spacing: 6) { + ForEach(selectedFiles) { f in + HStack(spacing: 8) { + Image(systemName: f.icon).foregroundColor(Color.zxGreen) + Text(f.name).font(.system(size: 14)).foregroundColor(Color.zxF0).lineLimit(1) + Spacer() + Text(f.size).font(.system(size: 12)).foregroundColor(Color.zxF04) + Button { + selectedFiles.removeAll { $0.id == f.id } + } label: { + Image(systemName: "xmark.circle").font(.system(size: 16)).foregroundColor(Color.zxF04) + } + } + .padding(.horizontal, 12).padding(.vertical, 8) + .background(Color.zxFill004) + .clipShape(RoundedRectangle(cornerRadius: 12)) + } + } + } + + HStack { + Image(systemName: "info.circle").font(.system(size: 12)) + Text("支持多选,每个文件生成一个知识点") + } + .font(.system(size: 12)).foregroundColor(Color.zxF04) + } + + if isUploading { + HStack(spacing: 8) { + ProgressView() + Text("上传中 \(currentUploadIndex)/\(selectedFiles.count)...").font(.system(size: 14)).foregroundColor(Color.zxF04) + } + } + } + + // 保存按钮 + Button { + Task { await save() } + } label: { + HStack(spacing: 8) { + if isSaving { ProgressView().tint(.white) } + Text(sourceType == .file && selectedFiles.count > 1 ? "批量添加 (\(selectedFiles.count) 个)" : "保存").font(.system(size: 14, weight: .bold)) + } + .foregroundColor(.white).frame(maxWidth: .infinity).frame(height: 52) + .background(canSave ? AnyView(ZXGradient.ctaPurple) : AnyView(Color.zxHairlineStrong)) + .clipShape(RoundedRectangle(cornerRadius: 16)) + } + .disabled(!canSave || isSaving) + }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) } + } + .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) + .fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.plainText, .pdf, .image], allowsMultipleSelection: true) { result in + if case .success(let urls) = result { handleFiles(urls) } + } + .photosPicker(isPresented: $showPhotoPicker, selection: $selectedPhotoItems, maxSelectionCount: 10, matching: .images) + .onChange(of: selectedPhotoItems) { _, items in + guard !items.isEmpty else { return } + Task { await handlePhotos(items) } + } + } + + // MARK: - File handling + + @State private var currentUploadIndex = 0 + + private var canSave: Bool { + switch sourceType { + case .manual: return !title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + case .file: return !selectedFiles.isEmpty && !isUploading + } + } + + private func handleFiles(_ urls: [URL]) { + for url in urls { + guard url.startAccessingSecurityScopedResource() else { continue } + defer { url.stopAccessingSecurityScopedResource() } + guard let data = try? Data(contentsOf: url) else { continue } + let name = url.lastPathComponent + selectedFiles.append(SelectedFile( + name: name, + data: data, + icon: fileIcon(name: name), + size: formatSize(data.count) + )) + } + } + + private func handlePhotos(_ items: [PhotosPickerItem]) async { + for item in items { + guard let data = try? await item.loadTransferable(type: Data.self) else { continue } + let compressed: Data + if let image = UIImage(data: data), data.count > 2 * 1024 * 1024 { + compressed = image.jpegData(compressionQuality: 0.6) ?? data + } else { + compressed = data + } + let name = "image_\(Int(Date().timeIntervalSince1970))_\(selectedFiles.count).jpg" + selectedFiles.append(SelectedFile( + name: name, + data: compressed, + icon: "photo", + size: formatSize(compressed.count) + )) + } + selectedPhotoItems = [] + } + + private func save() async { + isSaving = true + defer { isSaving = false } + + switch sourceType { + case .manual: + do { + _ = try await KnowledgeItemService.shared.create( + knowledgeBaseId: knowledgeBaseId, + title: title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "手写笔记" : title, + content: content, + itemType: "manual" + ) + ZXToastManager.shared.success("知识点已添加") + dismiss() + } catch { + ZXToastManager.shared.error("添加失败: \(error.localizedDescription)") + } + + case .file: + isUploading = true + defer { isUploading = false } + var successCount = 0 + let total = selectedFiles.count + + for (i, file) in selectedFiles.enumerated() { + currentUploadIndex = i + 1 + do { + let mime = mimeType(name: file.name) + let ext = file.name.lowercased() + let itemType = ext.hasSuffix(".md") || ext.hasSuffix(".markdown") ? "markdown" + : ext.hasSuffix(".txt") ? "text" + : ext.hasSuffix(".pdf") ? "pdf" + : ext.hasSuffix(".jpg") || ext.hasSuffix(".jpeg") || ext.hasSuffix(".png") || ext.hasSuffix(".heic") ? "image" + : "file" + + let fileId: String + if let image = UIImage(data: file.data) { + fileId = try await FileUploadService.shared.uploadImage(image, filename: file.name) + } else { + fileId = try await FileUploadService.shared.uploadData(file.data, filename: file.name, mimeType: mime) + } + let downloadUrl = try await FileUploadService.shared.getDownloadUrl(fileId: fileId) + + // 标题:优先用户填写,否则用文件名 + let itemTitle: String + if !title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + itemTitle = total == 1 ? title : "\(title) (\(i+1))" + } else { + itemTitle = file.name + } + + _ = try await KnowledgeItemService.shared.create( + knowledgeBaseId: knowledgeBaseId, + title: itemTitle, + content: downloadUrl, + itemType: itemType + ) + successCount += 1 + } catch { + ZXToastManager.shared.error("「\(file.name)」上传失败") + } + } + + if successCount == total { + ZXToastManager.shared.success("\(total) 个知识点已添加") + dismiss() + } else if successCount > 0 { + ZXToastManager.shared.success("\(successCount)/\(total) 个知识点已添加") + dismiss() + } + } + } + + private func fileIcon(name: String) -> String { + let ext = name.lowercased() + if ext.hasSuffix(".md") || ext.hasSuffix(".markdown") { return "doc.richtext" } + if ext.hasSuffix(".txt") { return "doc.plaintext" } + if ext.hasSuffix(".pdf") { return "doc" } + if ext.hasSuffix(".jpg") || ext.hasSuffix(".jpeg") || ext.hasSuffix(".png") || ext.hasSuffix(".heic") { return "photo" } + return "doc" + } + + private func formatSize(_ size: Int) -> String { + if size < 1024 { return "\(size) B" } + if size < 1024 * 1024 { return "\(size / 1024) KB" } + return String(format: "%.1f MB", Double(size) / 1024 / 1024) + } + + private func mimeType(name: String) -> String { + let ext = name.lowercased() + if ext.hasSuffix(".md") || ext.hasSuffix(".markdown") { return "text/markdown" } + if ext.hasSuffix(".txt") { return "text/plain" } + if ext.hasSuffix(".pdf") { return "application/pdf" } + if ext.hasSuffix(".jpg") || ext.hasSuffix(".jpeg") { return "image/jpeg" } + if ext.hasSuffix(".png") { return "image/png" } + if ext.hasSuffix(".heic") { return "image/heic" } + return "application/octet-stream" + } +} + +// MARK: - Knowledge Detail ViewModel + +@MainActor +final class KnowledgeDetailViewModel: ObservableObject { + @Published var localPath: String? + @Published var detectedType: MaterialType? + @Published var loadState: LoadState = .loading + @Published var isFavorited = false + + enum LoadState { case loading, ready, error(String) } + + let item: KnowledgeItem + + 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 { + guard let c = item.content else { return false } + return c.hasPrefix("http://") || c.hasPrefix("https://") + } + + func load() async { + print("[KD_DETAIL] load() start — item.id=\(item.id), title=\(item.title)") + print("[KD_DETAIL] isURL=\(isURL), content prefix=\(item.content?.prefix(200) ?? "nil")") + + guard isURL, let urlStr = item.content, let url = URL(string: urlStr) else { + // Not a URL — plain text content, ready immediately + let contentLen = item.content?.count ?? 0 + print("[KD_DETAIL] plain text path — content length=\(contentLen), setting .ready") + loadState = .ready + return + } + loadState = .loading + let ext = url.pathExtension.isEmpty ? "bin" : url.pathExtension.lowercased() + let localURL = FileManager.default.temporaryDirectory + .appendingPathComponent("kd_\(item.id).\(ext)") + print("[KD_DETAIL] URL download — ext=\(ext), local=\(localURL.path)") + + // Check cached file — skip if it's a COS error XML + if FileManager.default.fileExists(atPath: localURL.path) { + let fileSize = (try? FileManager.default.attributesOfItem(atPath: localURL.path)[.size] as? Int) ?? -1 + // Detect COS error responses (small XML files < 2KB) + if fileSize > 0 && fileSize < 2048 { + if let content = try? String(contentsOfFile: localURL.path, encoding: .utf8), + content.contains(""), content.contains("AccessDenied") { + print("[KD_DETAIL] cached file is COS error, deleting and re-fetching...") + try? FileManager.default.removeItem(at: localURL) + } + } + if FileManager.default.fileExists(atPath: localURL.path) { + print("[KD_DETAIL] file cached — size=\(fileSize), type=\(typeFromExtension(ext))") + localPath = localURL.path + detectedType = typeFromExtension(ext) + loadState = .ready + return + } + } + + // Re-fetch item from API to get a fresh signed URL + print("[KD_DETAIL] re-fetching item from API for fresh URL...") + let freshItem = try? await KnowledgeItemService.shared.detail(id: item.id) + let downloadURL: URL + if let fresh = freshItem, let freshStr = fresh.content, let freshURL = URL(string: freshStr) { + print("[KD_DETAIL] got fresh URL") + downloadURL = freshURL + } else { + print("[KD_DETAIL] re-fetch failed, using original URL") + downloadURL = url + } + + do { + let (data, _) = try await URLSession.shared.data(from: downloadURL) + print("[KD_DETAIL] download done — size=\(data.count)") + // If it's a COS error XML, show error + if data.count < 2048, let text = String(data: data, encoding: .utf8), text.contains("") { + print("[KD_DETAIL] downloaded content is an error XML: \(text.prefix(200))") + loadState = .error("文件访问已过期,请刷新后重试") + return + } + try data.write(to: localURL) + localPath = localURL.path + detectedType = typeFromExtension(ext) + print("[KD_DETAIL] saved — path=\(localURL.path), type=\(String(describing: detectedType))") + loadState = .ready + } catch { + print("[KD_DETAIL] download ERROR — \(error.localizedDescription)") + loadState = .error(error.localizedDescription) + } + } + + private func typeFromExtension(_ ext: String) -> MaterialType { + switch ext { + case "md", "markdown": return .markdown + case "txt", "text": return .text + case "pdf": return .pdf + case "png", "jpg", "jpeg", "webp", "gif": return .image + case "doc", "docx": return .word + case "xls", "xlsx": return .excel + case "ppt", "pptx": return .powerPoint + case "epub": return .epub + default: return .unknown + } + } +} + +// MARK: - Knowledge Detail Page + +struct KnowledgeDetailPage: View { + let item: KnowledgeItem + @StateObject private var vm: KnowledgeDetailViewModel + + @State private var showQuickLook = false + @State private var showNoteSheet = false + + init(item: KnowledgeItem) { + self.item = item + _vm = StateObject(wrappedValue: KnowledgeDetailViewModel(item: item)) + } + + @State private var navigateToReader = false + @State private var readerPath: String = "" + @State private var readerType: MaterialType = .text + + var body: some View { + Group { + switch vm.loadState { + case .loading: + VStack(spacing: 12) { + ProgressView().tint(Color.zxPrimary) + Text("加载中…").font(.system(size: 14)).foregroundColor(Color.zxF04) + }.frame(maxWidth: .infinity, maxHeight: .infinity).background(Color.zxCanvas) + case .error(let msg): + VStack(spacing: 16) { + Image(systemName: "exclamationmark.triangle").font(.system(size: 40)).foregroundColor(Color.zxCoral) + Text(msg).font(.system(size: 14)).foregroundColor(Color.zxF04) + // Fallback: show summary or raw text + if let summary = item.summary, !summary.isEmpty { + ScrollView { Text(summary).font(.system(size: 14)).foregroundColor(Color.zxF0).lineSpacing(6).padding(20) } + } + Button("重试") { Task { await vm.load() } } + .font(.system(size: 14, weight: .medium)).foregroundColor(Color.zxPrimary) + .padding(.horizontal, 24).padding(.vertical, 10) + .background(Color.zxPrimarySoft).clipShape(RoundedRectangle(cornerRadius: 10)) + }.frame(maxWidth: .infinity, maxHeight: .infinity).background(Color.zxCanvas) + case .ready: + if let path = vm.localPath, let mt = vm.detectedType { + MaterialReaderView(materialId: item.id, filePath: path, materialType: mt, title: item.title, showQuickLook: $showQuickLook, showNoteSheet: $showNoteSheet) + } else if let content = item.content { + // Plain text content — render directly + ZStack { Color.zxCanvas.ignoresSafeArea() + ScrollView { + 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 { + Text(summary).font(.system(size: 14)).foregroundColor(Color.zxF0).lineSpacing(6) + .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) + } + } + } + } + .navigationTitle(item.title) + .navigationBarTitleDisplayMode(.inline) + .toolbar(.hidden, for: .tabBar) + .toolbarBackground(.hidden, for: .navigationBar) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Menu { + NavigationLink(value: Route.aiChat(context: ChatEntryContext(scopeType: .knowledgeItem, scopeId: item.id, scopeName: item.title, parentKnowledgeBaseId: item.knowledgeBaseId, createdFrom: "knowledge_item_detail"))) { + Label("AI 对话", systemImage: "bubble.left.and.bubble.right") + } + NavigationLink(value: Route.studyHome) { + Label("学习", systemImage: "arrow.triangle.2.circlepath") + } + NavigationLink(value: Route.editKnowledge(item: item)) { + Label("编辑", systemImage: "pencil") + } + if let mt = vm.detectedType { + let pm = previewMode(for: mt) + if pm == .nativeReader { + Button { showNoteSheet = true } label: { + Label("笔记", systemImage: "square.and.pencil") + } + } + if pm == .platformPreview { + Button { showQuickLook = true } label: { + Label("预览", systemImage: "eye") + } + } + } + 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: { + Image(systemName: "ellipsis.circle") + .font(.system(size: 16)) + .foregroundColor(Color.zxF05) + } + } + } + .task { await vm.load() } + } + + 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 + 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()) } +} + +struct ImportPage: View { + @Environment(\.dismiss) private var dismiss + @State private var showFilePicker = false + @State private var showPhotoPicker = false + @State private var showLinkSheet = false + @State private var linkURL = "" + @State private var isImporting = false + @State private var kbId: String? + @State private var statusMessage = ""; @State private var importError: String? + @State private var selectedPhotoItem: PhotosPickerItem? + + var body: some View { + ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) { + ScrollView { VStack(spacing: 12) { + if let error = importError { + HStack(spacing: 8) { Image(systemName: "exclamationmark.triangle").foregroundColor(.red); Text(error).font(.system(size: 14)).foregroundColor(.red) } + .padding(12) + + } + if !statusMessage.isEmpty { + HStack(spacing: 8) { ProgressView(); Text(statusMessage).font(.system(size: 14)).foregroundColor(Color.zxF04) } + .padding(12) + } + Button { showFilePicker = true } label: { + ZXImportRow(icon: "doc.text", title: "文件导入", desc: "支持 PDF、Word、Markdown、TXT") + } + Button { showPhotoPicker = true } label: { + ZXImportRow(icon: "photo.on.rectangle", title: "相册导入", desc: "从相册选择截图或图片,AI 自动识别文字") + } + Button { showLinkSheet = true } label: { + ZXImportRow(icon: "link", title: "链接导入", desc: "粘贴网页链接,自动提取内容") + } + }.padding(.horizontal, 20).padding(.top, 8) }.scrollIndicators(.hidden) } + } + .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) + .disabled(isImporting) + .task { do { let kbs = try await KnowledgeBaseService.shared.list(page: 1, limit: 1); kbId = kbs.first?.id } catch {} } + .fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.pdf, .plainText], allowsMultipleSelection: true) { result in + if case .success(let urls) = result { Task { await handleFiles(urls) } } + } + .photosPicker(isPresented: $showPhotoPicker, selection: $selectedPhotoItem, matching: .images) + .onChange(of: selectedPhotoItem) { _, item in + guard let item else { return } + Task { await handlePhoto(item) } + } + .alert("链接导入", isPresented: $showLinkSheet) { + TextField("输入网页 URL", text: $linkURL) + Button("导入") { Task { await handleLink() } } + Button("取消", role: .cancel) {} + } message: { Text("输入要导入的网页链接地址") } + } + + private func ensureKB() async -> String? { + if let id = kbId { return id } + do { let kbs = try await KnowledgeBaseService.shared.list(page: 1, limit: 1); kbId = kbs.first?.id; return kbId } catch { return nil } + } + + private func handleFiles(_ urls: [URL]) async { + guard let kb = await ensureKB() else { importError = "请先创建一个知识库"; return } + isImporting = true; importError = nil + for url in urls { + guard url.startAccessingSecurityScopedResource() else { continue } + defer { url.stopAccessingSecurityScopedResource() } + guard let data = try? Data(contentsOf: url) else { continue } + let name = url.lastPathComponent + statusMessage = "上传 \(name)..." + do { + let mime = url.pathExtension.lowercased() == "pdf" ? "application/pdf" : "text/plain" + let _ = try await FileUploadService.shared.uploadData(data, filename: name, mimeType: mime) + statusMessage = "开始导入 \(name)..." + let _ = try await DocumentImportService.shared.create(knowledgeBaseId: kb, fileName: name, sourceType: "file") + statusMessage = "\(name) 导入任务已创建" + } catch { importError = "\(name) 导入失败: \(error.localizedDescription)" } + } + isImporting = false; statusMessage = "" + if importError == nil { ZXToastManager.shared.success("导入完成"); dismiss() } + } + + private func handlePhoto(_ item: PhotosPickerItem) async { + guard let kb = await ensureKB() else { importError = "请先创建一个知识库"; return } + isImporting = true; importError = nil; selectedPhotoItem = nil + guard let data = try? await item.loadTransferable(type: Data.self), + let image = UIImage(data: data) else { isImporting = false; return } + let name = "photo_\(Int(Date().timeIntervalSince1970)).jpg" + statusMessage = "上传图片..." + do { + let _ = try await FileUploadService.shared.uploadImage(image, filename: name) + statusMessage = "开始识别..." + let _ = try await DocumentImportService.shared.create(knowledgeBaseId: kb, fileName: name, sourceType: "file") + ZXToastManager.shared.success("图片已提交导入") + dismiss() + } catch { importError = "导入失败: \(error.localizedDescription)" } + isImporting = false; statusMessage = "" + } + + private func handleLink() async { + guard !linkURL.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return } + guard let kb = await ensureKB() else { importError = "请先创建一个知识库"; return } + isImporting = true; importError = nil + do { + let _ = try await DocumentImportService.shared.create(knowledgeBaseId: kb, sourceType: "link", rawText: linkURL) + ZXToastManager.shared.success("链接已提交导入") + dismiss() + } catch { importError = "导入失败: \(error.localizedDescription)" } + isImporting = false + } +} + +struct ZXImportRow: View { let icon: String; let title: String; let desc: String + var body: some View { HStack(spacing: 14) { Image(systemName: icon).font(.system(size: 22)).foregroundColor(Color.zxPurple).frame(width: 48, height: 48) +; VStack(alignment: .leading, spacing: 2) { Text(title).font(.system(size: 16, weight: .semibold)).foregroundColor(Color.zxF0); Text(desc).font(.system(size: 12)).foregroundColor(Color.zxF04) }; Spacer(); Image("icon-chevron-right").resizable().scaledToFit().frame(width: 16, height: 16).foregroundColor(Color.zxF03) }.padding(16).background(Color.zxFill003).clipShape(RoundedRectangle(cornerRadius: 16)).overlay(RoundedRectangle(cornerRadius: 16).stroke(Color.zxBorder006, lineWidth: 1)) } +} + +// MARK: - Import Review + +struct ImportReviewPage: View { + let sourceId: String + @Environment(\.dismiss) private var dismiss + @State private var candidates: [ImportCandidate] = [] + @State private var isLoading = true + @State private var isProcessing = false + @State private var errorMessage: String? + @State private var expandedId: String? + + var body: some View { + ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) { + if isLoading { + VStack(spacing: 12) { ProgressView().tint(Color.zxPurple); Text("加载候选...").font(.system(size: 14)).foregroundColor(Color.zxF04) } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } else if candidates.isEmpty { + VStack(spacing: 12) { + Image(systemName: "checkmark.circle").font(.system(size: 36)).foregroundColor(Color.zxGreen) + Text("没有待审批的候选").font(.system(size: 14)).foregroundColor(Color.zxF04) + }.frame(maxWidth: .infinity, maxHeight: .infinity) + } else { + ScrollView { + VStack(spacing: 12) { + HStack { + Text("\(candidates.count) 个候选知识点").font(.system(size: 14, weight: .medium)).foregroundColor(Color.zxF04) + Spacer() + Button { + Task { await batchAccept() } + } label: { + Text("全部接受").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxPrimary) + } + .disabled(isProcessing) + } + ForEach(candidates) { c in + VStack(spacing: 0) { + Button { + withAnimation { expandedId = expandedId == c.id ? nil : c.id } + } label: { + HStack(spacing: 12) { + if let conf = c.confidence { + Text("\(Int(conf * 100))%").font(.system(size: 10, weight: .bold)) + .foregroundColor(conf > 0.7 ? Color.zxGreen : Color.zxAmber) + .padding(.horizontal, 6).padding(.vertical, 2) + .background((conf > 0.7 ? Color.zxGreen : Color.zxAmber).opacity(0.12)) + .clipShape(Capsule()) + } + VStack(alignment: .leading, spacing: 4) { + Text(c.title ?? "无标题").font(.system(size: 14, weight: .semibold)).foregroundColor(Color.zxF0).lineLimit(1) + if let content = c.content { + Text(content).font(.system(size: 12)).foregroundColor(Color.zxF04).lineLimit(2) + } + } + Spacer() + Image(systemName: expandedId == c.id ? "chevron.up" : "chevron.down").font(.system(size: 12)).foregroundColor(Color.zxF03) + } + .padding(12).background(Color.zxFill003).clipShape(RoundedRectangle(cornerRadius: 14)) + } + .foregroundColor(.primary) + + if expandedId == c.id { + HStack(spacing: 8) { + Button { + Task { await rejectCandidate(c) } + } label: { + Label("拒绝", systemImage: "xmark").font(.system(size: 14, weight: .medium)) + .foregroundColor(Color.zxCoral).frame(maxWidth: .infinity).frame(height: 40) + + + } + Button { + Task { await acceptCandidate(c) } + } label: { + Label("接受", systemImage: "checkmark").font(.system(size: 14, weight: .medium)) + .foregroundColor(Color.zxGreen).frame(maxWidth: .infinity).frame(height: 40) + + + } + } + .padding(.horizontal, 12).padding(.top, 8) + } + } + } + } + .padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 100) + } + .scrollIndicators(.hidden) + } + }} + .navigationTitle("候选审批").navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) + .disabled(isProcessing) + .task { await load() } + } + + private func load() async { + isLoading = true; errorMessage = nil + do { candidates = try await ImportCandidateService.shared.listBySource(sourceId: sourceId) } catch { errorMessage = error.localizedDescription } + isLoading = false + } + + private func acceptCandidate(_ c: ImportCandidate) async { + isProcessing = true + do { + let _ = try await ImportCandidateService.shared.accept(id: c.id) + candidates.removeAll { $0.id == c.id } + ZXToastManager.shared.success("已接受") + } catch { ZXToastManager.shared.error("操作失败") } + isProcessing = false + } + + private func rejectCandidate(_ c: ImportCandidate) async { + isProcessing = true + do { + let _ = try await ImportCandidateService.shared.reject(id: c.id) + candidates.removeAll { $0.id == c.id } + ZXToastManager.shared.success("已拒绝") + } catch { ZXToastManager.shared.error("操作失败") } + isProcessing = false + } + + private func batchAccept() async { + isProcessing = true + do { + let _ = try await ImportCandidateService.shared.batchAccept(sourceId: sourceId) + candidates.removeAll() + ZXToastManager.shared.success("全部接受") + } catch { ZXToastManager.shared.error("操作失败") } + isProcessing = false + } +} + +struct EditKnowledgePage: View { + let item: KnowledgeItem + @State private var title: String; @State private var content: String + + init(item: KnowledgeItem) { + self.item = item + _title = State(initialValue: item.title) + _content = State(initialValue: item.content ?? "") + } + var body: some View { + ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) { + ScrollView { VStack(spacing: 16) { + VStack(alignment: .leading, spacing: 8) { Text("标题").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035); TextField("", text: $title).font(.system(size: 16)).tint(Color.zxPurple).padding(.horizontal, 16).frame(height: 52).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14)).overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1)) } + VStack(alignment: .leading, spacing: 8) { Text("内容").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035); TextEditor(text: $content).frame(minHeight: 200).scrollContentBackground(.hidden).padding(12).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14)).overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1)) } + Button { + Task { _ = try? await KnowledgeItemService.shared.update(id: item.id, title: title, content: content, summary: nil) } + } label: { Text("保存修改").font(.system(size: 14, weight: .bold)).foregroundColor(.white).frame(maxWidth: .infinity).frame(height: 52).background(ZXGradient.ctaPurple).clipShape(RoundedRectangle(cornerRadius: 16)) } + }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) } + }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) + } +} + +// MARK: - Helpers + +private func materialTypeFromMime(_ mime: String?) -> MaterialType { + guard let m = mime?.lowercased() else { return .markdown } + if m.contains("pdf") { return .pdf } + if m.contains("epub") { return .epub } + if m.contains("word") || m.contains("docx") || m.contains("doc") { return .word } + if m.contains("excel") || m.contains("xlsx") { return .excel } + if m.contains("powerpoint") || m.contains("pptx") { return .powerPoint } + if m.contains("image") { return .image } + if m.contains("text/plain") { return .text } + return .markdown +} + +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 +}