|
|
import SwiftUI
|
|
|
import CoreImage
|
|
|
import CoreImage.CIFilterBuiltins
|
|
|
|
|
|
// MARK: - 条形码预览组件
|
|
|
struct BarcodePreviewView: View {
|
|
|
let content: String
|
|
|
let barcodeType: BarcodeType
|
|
|
|
|
|
var body: some View {
|
|
|
Group {
|
|
|
if let barcodeImage = generateBarcodeImage() {
|
|
|
Image(uiImage: barcodeImage)
|
|
|
.resizable()
|
|
|
.aspectRatio(contentMode: .fit)
|
|
|
.frame(maxWidth: .infinity)
|
|
|
.background(Color.white)
|
|
|
.cornerRadius(8)
|
|
|
.shadow(color: .black.opacity(0.1), radius: 2, x: 0, y: 1)
|
|
|
} else {
|
|
|
// 生成失败时的占位符
|
|
|
VStack(spacing: 8) {
|
|
|
Image(systemName: "barcode.viewfinder")
|
|
|
.font(.system(size: 32))
|
|
|
.foregroundColor(.gray)
|
|
|
|
|
|
Text(NSLocalizedString("cannot_generate_barcode", comment: "Cannot generate barcode"))
|
|
|
.font(.caption)
|
|
|
.foregroundColor(.gray)
|
|
|
|
|
|
Text(NSLocalizedString("check_input_format", comment: "Please check input content format"))
|
|
|
.font(.caption2)
|
|
|
.foregroundColor(.gray)
|
|
|
}
|
|
|
.frame(maxWidth: .infinity)
|
|
|
.frame(height: 120)
|
|
|
.background(Color(.systemGray5))
|
|
|
.cornerRadius(8)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// MARK: - 生成条形码图片
|
|
|
private func generateBarcodeImage() -> UIImage? {
|
|
|
guard !content.isEmpty else { return nil }
|
|
|
|
|
|
let context = CIContext()
|
|
|
let filter: CIFilter?
|
|
|
|
|
|
// 根据条形码类型选择相应的滤镜
|
|
|
switch barcodeType {
|
|
|
case .ean13, .ean8, .upce, .itf14:
|
|
|
filter = CIFilter.code128BarcodeGenerator()
|
|
|
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
|
|
|
|
|
|
case .code39:
|
|
|
// Code 39 使用 Code 128 滤镜,因为 Core Image 不直接支持 Code 39
|
|
|
filter = CIFilter.code128BarcodeGenerator()
|
|
|
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
|
|
|
|
|
|
case .code128:
|
|
|
filter = CIFilter.code128BarcodeGenerator()
|
|
|
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
|
|
|
|
|
|
case .pdf417:
|
|
|
filter = CIFilter.pdf417BarcodeGenerator()
|
|
|
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
|
|
|
}
|
|
|
|
|
|
guard let filter = filter,
|
|
|
let outputImage = filter.outputImage else { return nil }
|
|
|
|
|
|
// 设置条形码的尺寸和缩放
|
|
|
let scale = CGAffineTransform(scaleX: 3, y: 3)
|
|
|
let scaledImage = outputImage.transformed(by: scale)
|
|
|
|
|
|
// 转换为UIImage
|
|
|
guard let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) else {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
return UIImage(cgImage: cgImage)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#Preview {
|
|
|
VStack(spacing: 20) {
|
|
|
BarcodePreviewView(content: "1234567890123", barcodeType: .ean13)
|
|
|
BarcodePreviewView(content: "12345678", barcodeType: .ean8)
|
|
|
BarcodePreviewView(content: "CODE39", barcodeType: .code39)
|
|
|
BarcodePreviewView(content: "123456789012345678901234567890", barcodeType: .pdf417)
|
|
|
}
|
|
|
.padding()
|
|
|
} |