You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.5 KiB
225 lines
6.5 KiB
import Foundation
|
|
import SwiftUI
|
|
|
|
// MARK: - 条形码类型枚举
|
|
public enum BarcodeType: String, CaseIterable {
|
|
case ean13 = "EAN-13"
|
|
case ean8 = "EAN-8"
|
|
case upce = "UPC-E"
|
|
case code39 = "Code 39"
|
|
case code128 = "Code 128"
|
|
case itf14 = "ITF-14"
|
|
case pdf417 = "PDF417"
|
|
|
|
var displayName: String {
|
|
return self.rawValue
|
|
}
|
|
|
|
var icon: String {
|
|
switch self {
|
|
case .ean13, .ean8, .upce, .itf14:
|
|
return "barcode"
|
|
case .code39, .code128:
|
|
return "barcode.viewfinder"
|
|
case .pdf417:
|
|
return "qrcode.viewfinder"
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 二维码类型枚举
|
|
public enum QRCodeType: String, CaseIterable {
|
|
case wifi = "WiFi"
|
|
case mail = "Email"
|
|
case url = "URL"
|
|
case phone = "Phone"
|
|
case sms = "SMS"
|
|
case vcard = "vCard"
|
|
case mecard = "MeCard"
|
|
case text = "Text"
|
|
case location = "Location"
|
|
case calendar = "Calendar"
|
|
case instagram = "Instagram"
|
|
case facebook = "Facebook"
|
|
case spotify = "Spotify"
|
|
case twitter = "X"
|
|
case whatsapp = "WhatsApp"
|
|
case viber = "Viber"
|
|
case snapchat = "Snapchat"
|
|
case tiktok = "TikTok"
|
|
|
|
var displayName: String {
|
|
return self.rawValue
|
|
}
|
|
|
|
var icon: String {
|
|
switch self {
|
|
case .wifi:
|
|
return "wifi"
|
|
case .mail:
|
|
return "envelope"
|
|
case .url:
|
|
return "link"
|
|
case .phone:
|
|
return "phone"
|
|
case .sms:
|
|
return "message"
|
|
case .vcard, .mecard:
|
|
return "person.crop.rectangle"
|
|
case .text:
|
|
return "text.quote"
|
|
case .location:
|
|
return "location"
|
|
case .calendar:
|
|
return "calendar"
|
|
case .instagram:
|
|
return "camera"
|
|
case .facebook:
|
|
return "person.2"
|
|
case .spotify:
|
|
return "music.note"
|
|
case .twitter:
|
|
return "bird"
|
|
case .whatsapp:
|
|
return "message.circle"
|
|
case .viber:
|
|
return "bubble.left.and.bubble.right"
|
|
case .snapchat:
|
|
return "camera.viewfinder"
|
|
case .tiktok:
|
|
return "music.mic"
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 数据来源枚举
|
|
public enum DataSource: String, CaseIterable {
|
|
case scanned = "scanned"
|
|
case created = "created"
|
|
|
|
var displayName: String {
|
|
switch self {
|
|
case .scanned:
|
|
return NSLocalizedString("scanned", comment: "Scanned")
|
|
case .created:
|
|
return NSLocalizedString("manually_created", comment: "Manually created")
|
|
}
|
|
}
|
|
|
|
var icon: String {
|
|
switch self {
|
|
case .scanned:
|
|
return "camera.viewfinder"
|
|
case .created:
|
|
return "plus.circle"
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 数据类型枚举
|
|
public enum DataType: String, CaseIterable {
|
|
case barcode = "barcode"
|
|
case qrcode = "qrcode"
|
|
|
|
var displayName: String {
|
|
switch self {
|
|
case .barcode:
|
|
return "barcode".localized
|
|
case .qrcode:
|
|
return "qr_code".localized
|
|
}
|
|
}
|
|
|
|
var icon: String {
|
|
switch self {
|
|
case .barcode:
|
|
return "barcode"
|
|
case .qrcode:
|
|
return "qrcode"
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 二维码解析数据
|
|
@objc(ParsedQRData)
|
|
public class ParsedQRData: NSObject, NSSecureCoding {
|
|
public static var supportsSecureCoding: Bool = true
|
|
|
|
public let type: QRCodeType
|
|
public let title: String
|
|
public let subtitle: String?
|
|
public let icon: String
|
|
|
|
public init(type: QRCodeType, title: String, subtitle: String? = nil, icon: String? = nil) {
|
|
self.type = type
|
|
self.title = title
|
|
self.subtitle = subtitle
|
|
self.icon = icon ?? type.icon
|
|
}
|
|
|
|
public required init?(coder: NSCoder) {
|
|
let typeString = coder.decodeObject(of: NSString.self, forKey: "type") as String? ?? ""
|
|
self.type = QRCodeType(rawValue: typeString) ?? .text
|
|
self.title = coder.decodeObject(of: NSString.self, forKey: "title") as String? ?? ""
|
|
self.subtitle = coder.decodeObject(of: NSString.self, forKey: "subtitle") as String?
|
|
self.icon = coder.decodeObject(of: NSString.self, forKey: "icon") as String? ?? self.type.icon
|
|
}
|
|
|
|
public func encode(with coder: NSCoder) {
|
|
coder.encode(type.rawValue, forKey: "type")
|
|
coder.encode(title, forKey: "title")
|
|
coder.encode(subtitle, forKey: "subtitle")
|
|
coder.encode(icon, forKey: "icon")
|
|
}
|
|
}
|
|
|
|
// MARK: - 二维码样式数据
|
|
public struct QRCodeStyleData: Codable {
|
|
public let foregroundColor: String
|
|
public let backgroundColor: String
|
|
public let dotType: String
|
|
public let eyeType: String
|
|
public let logo: String?
|
|
public let hasCustomLogo: Bool
|
|
public let customLogoFileName: String?
|
|
|
|
public init(foregroundColor: String, backgroundColor: String, dotType: String, eyeType: String, logo: String? = nil, hasCustomLogo: Bool = false, customLogoFileName: String? = nil) {
|
|
self.foregroundColor = foregroundColor
|
|
self.backgroundColor = backgroundColor
|
|
self.dotType = dotType
|
|
self.eyeType = eyeType
|
|
self.logo = logo
|
|
self.hasCustomLogo = hasCustomLogo
|
|
self.customLogoFileName = customLogoFileName
|
|
}
|
|
|
|
// 获取样式的描述信息
|
|
public var styleDescription: String {
|
|
var description = String(format: NSLocalizedString("style_description_format", comment: "Style description format"), foregroundColor, backgroundColor, dotType, eyeType)
|
|
if let logo = logo {
|
|
description += String(format: NSLocalizedString("style_logo_format", comment: "Style logo format"), logo)
|
|
}
|
|
if hasCustomLogo {
|
|
description += NSLocalizedString("custom_logo", comment: "Custom logo")
|
|
}
|
|
return description
|
|
}
|
|
|
|
// 从文件名加载自定义Logo图片
|
|
public var customLogoImage: UIImage? {
|
|
guard let fileName = customLogoFileName else {
|
|
return nil
|
|
}
|
|
|
|
// 获取文档目录
|
|
guard let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
|
return nil
|
|
}
|
|
|
|
let customLogosPath = documentsPath.appendingPathComponent("CustomLogos")
|
|
let imagePath = customLogosPath.appendingPathComponent(fileName)
|
|
|
|
return UIImage(contentsOfFile: imagePath.path)
|
|
}
|
|
}
|