import SwiftUI import CoreData import QRCode internal import SwiftImageReadWrite struct QRCodeDetailView: View { let historyItem: HistoryItem @StateObject private var coreDataManager = CoreDataManager.shared @State private var qrCodeImage: UIImage? @State private var showingShareSheet = false @State private var showingAlert = false @State private var alertMessage = "" var body: some View { ScrollView { VStack(spacing: 20) { // 二维码图片 qrCodeImageView // 二维码类型信息 qrCodeTypeSection // 解析后的详细信息 parsedInfoSection // 原始内容 originalContentSection // 操作按钮 actionButtonsSection } .padding() } .navigationTitle("二维码详情") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: { showingShareSheet = true }) { Image(systemName: "square.and.arrow.up") } } } .onAppear { generateQRCodeImage() } .sheet(isPresented: $showingShareSheet) { ShareSheet(activityItems: [historyItem.content ?? ""]) } .alert("提示", isPresented: $showingAlert) { Button("确定") { } } message: { Text(alertMessage) } } // MARK: - 二维码图片视图 private var qrCodeImageView: some View { VStack(spacing: 16) { if let qrCodeImage = qrCodeImage { Image(uiImage: qrCodeImage) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 200, height: 200) .cornerRadius(12) .shadow(radius: 8) } else { RoundedRectangle(cornerRadius: 12) .fill(Color.gray.opacity(0.3)) .frame(width: 200, height: 200) .overlay( ProgressView() .scaleEffect(1.5) ) } Text("扫描此二维码") .font(.caption) .foregroundColor(.secondary) } } // MARK: - 二维码类型信息 private var qrCodeTypeSection: some View { VStack(alignment: .leading, spacing: 12) { HStack { Image(systemName: "qrcode") .font(.title2) .foregroundColor(.blue) Text("二维码类型") .font(.headline) Spacer() } if let qrCodeTypeString = historyItem.qrCodeType, let qrCodeType = QRCodeType(rawValue: qrCodeTypeString) { HStack { Image(systemName: qrCodeType.icon) .font(.title3) .foregroundColor(.orange) Text(qrCodeType.displayName) .font(.title3) .fontWeight(.medium) Spacer() } .padding() .background(Color.orange.opacity(0.1)) .cornerRadius(8) } } .padding() .background(Color(.systemBackground)) .cornerRadius(12) .shadow(radius: 2) } // MARK: - 解析后的详细信息 private var parsedInfoSection: some View { VStack(alignment: .leading, spacing: 12) { HStack { Image(systemName: "info.circle") .font(.title2) .foregroundColor(.green) Text("解析信息") .font(.headline) Spacer() } if let content = historyItem.content { let parsedData = QRCodeParser.parseQRCode(content) VStack(alignment: .leading, spacing: 8) { HStack { Image(systemName: parsedData.icon) .font(.title3) .foregroundColor(.green) Text(parsedData.title) .font(.title3) .fontWeight(.medium) Spacer() } if let subtitle = parsedData.subtitle { Text(subtitle) .font(.body) .foregroundColor(.secondary) .multilineTextAlignment(.leading) } } .padding() .background(Color.green.opacity(0.1)) .cornerRadius(8) } } .padding() .background(Color(.systemBackground)) .cornerRadius(12) .shadow(radius: 2) } // MARK: - 原始内容 private var originalContentSection: some View { VStack(alignment: .leading, spacing: 12) { HStack { Image(systemName: "doc.text") .font(.title2) .foregroundColor(.purple) Text("原始内容") .font(.headline) Spacer() } if let content = historyItem.content { ScrollView { Text(content) .font(.system(.body, design: .monospaced)) .foregroundColor(.secondary) .multilineTextAlignment(.leading) .padding() .frame(maxWidth: .infinity, alignment: .leading) } .frame(maxHeight: 200) .background(Color.purple.opacity(0.1)) .cornerRadius(8) } } .padding() .background(Color(.systemBackground)) .cornerRadius(12) .shadow(radius: 2) } // MARK: - 操作按钮 private var actionButtonsSection: some View { VStack(spacing: 12) { // 收藏按钮 Button(action: toggleFavorite) { HStack { Image(systemName: historyItem.isFavorite ? "heart.fill" : "heart") .foregroundColor(historyItem.isFavorite ? .red : .gray) Text(historyItem.isFavorite ? "取消收藏" : "收藏") .fontWeight(.medium) } .frame(maxWidth: .infinity) .padding() .background(historyItem.isFavorite ? Color.red.opacity(0.1) : Color.gray.opacity(0.1)) .foregroundColor(historyItem.isFavorite ? .red : .gray) .cornerRadius(10) } // 复制内容按钮 Button(action: copyContent) { HStack { Image(systemName: "doc.on.doc") .foregroundColor(.blue) Text("复制内容") .fontWeight(.medium) } .frame(maxWidth: .infinity) .padding() .background(Color.blue.opacity(0.1)) .foregroundColor(.blue) .cornerRadius(10) } // 打开链接按钮(如果是URL类型) if let content = historyItem.content, canOpenURL(content) { Button(action: { openURL(content) }) { HStack { Image(systemName: "arrow.up.right.square") .foregroundColor(.green) Text("打开链接") .fontWeight(.medium) } .frame(maxWidth: .infinity) .padding() .background(Color.green.opacity(0.1)) .foregroundColor(.green) .cornerRadius(10) } } } .padding() .background(Color(.systemBackground)) .cornerRadius(12) .shadow(radius: 2) } // MARK: - 生成二维码图片 private func generateQRCodeImage() { guard let content = historyItem.content else { return } do { let imageData = try QRCode.build .text(content) .quietZonePixelCount(3) .foregroundColor(CGColor(srgbRed: 1, green: 0, blue: 0.6, alpha: 1)) .backgroundColor(CGColor(srgbRed: 0, green: 0, blue: 0.2, alpha: 1)) .background.cornerRadius(3) .onPixels.shape(QRCode.PixelShape.CurvePixel()) .eye.shape(QRCode.EyeShape.Teardrop()) .generate.image(dimension: 600, representation: .png()) self.qrCodeImage = UIImage(data: imageData) } catch { print("生成二维码失败: \(error)") } } // MARK: - 切换收藏状态 private func toggleFavorite() { historyItem.isFavorite.toggle() coreDataManager.save() let message = historyItem.isFavorite ? "已添加到收藏" : "已取消收藏" alertMessage = message showingAlert = true } // MARK: - 复制内容 private func copyContent() { if let content = historyItem.content { UIPasteboard.general.string = content alertMessage = "内容已复制到剪贴板" showingAlert = true } } // MARK: - 检查是否可以打开URL private func canOpenURL(_ string: String) -> Bool { guard let url = URL(string: string) else { return false } return UIApplication.shared.canOpenURL(url) } // MARK: - 打开URL private func openURL(_ string: String) { guard let url = URL(string: string) else { return } UIApplication.shared.open(url) } } // MARK: - 分享表单 struct ShareSheet: UIViewControllerRepresentable { let activityItems: [Any] func makeUIViewController(context: Context) -> UIActivityViewController { let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) return controller } func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {} } #Preview("Wi‑Fi") { let ctx = PreviewData.context let item = PreviewData.wifiSample(in: ctx) return NavigationView { QRCodeDetailView(historyItem: item) } } #Preview("URL") { let ctx = PreviewData.context let item = PreviewData.urlSample(in: ctx) return NavigationView { QRCodeDetailView(historyItem: item) } } #Preview("SMS") { let ctx = PreviewData.context let item = PreviewData.smsSample(in: ctx) return NavigationView { QRCodeDetailView(historyItem: item) } } #Preview("vCard") { let ctx = PreviewData.context let item = PreviewData.vcardSample(in: ctx) return NavigationView { QRCodeDetailView(historyItem: item) } } #Preview("Instagram") { let ctx = PreviewData.context let item = PreviewData.instagramSample(in: ctx) return NavigationView { QRCodeDetailView(historyItem: item) } } #Preview("Text") { let ctx = PreviewData.context let item = PreviewData.textSample(in: ctx) return NavigationView { QRCodeDetailView(historyItem: item) } } // MARK: - Preview Data private enum PreviewData { static let context: NSManagedObjectContext = { let container = NSPersistentContainer(name: "MyQrCode") let description = NSPersistentStoreDescription() description.type = NSInMemoryStoreType container.persistentStoreDescriptions = [description] container.loadPersistentStores { _, _ in } return container.viewContext }() private static func makeBaseItem(in context: NSManagedObjectContext, content: String, qrType: QRCodeType, favorite: Bool = false) -> HistoryItem { let item = HistoryItem(context: context) item.id = UUID() item.content = content item.dataType = DataType.qrcode.rawValue item.dataSource = DataSource.created.rawValue item.createdAt = Date() item.isFavorite = favorite item.qrCodeType = qrType.rawValue return item } static func wifiSample(in context: NSManagedObjectContext) -> HistoryItem { let content = "WIFI:T:WPA;S:MyNetwork;P:MyPassword;;" return makeBaseItem(in: context, content: content, qrType: .wifi, favorite: true) } static func urlSample(in context: NSManagedObjectContext) -> HistoryItem { let content = "https://www.example.com" return makeBaseItem(in: context, content: content, qrType: .url) } static func smsSample(in context: NSManagedObjectContext) -> HistoryItem { let content = "SMSTO:+8613800138000:Hello" return makeBaseItem(in: context, content: content, qrType: .sms) } static func vcardSample(in context: NSManagedObjectContext) -> HistoryItem { let content = """ BEGIN:VCARD VERSION:3.0 FN:John Doe TEL:+1234567890 EMAIL:example@example.com END:VCARD """.trimmingCharacters(in: .whitespacesAndNewlines) return makeBaseItem(in: context, content: content, qrType: .vcard) } static func instagramSample(in context: NSManagedObjectContext) -> HistoryItem { let content = "https://www.instagram.com/example_user/" return makeBaseItem(in: context, content: content, qrType: .instagram) } static func textSample(in context: NSManagedObjectContext) -> HistoryItem { let content = "Hello, this is a text message!" return makeBaseItem(in: context, content: content, qrType: .text) } }