Add role-based order/deposit lists, AVFoundation QR scanning, verify dialogs, and ViewModel tests so photographers, scenic admins, and store admins match Android behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
74 lines
2.9 KiB
Swift
74 lines
2.9 KiB
Swift
//
|
||
// QRCodeScanResult.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// 扫码 JSON 解析结果,对齐 Android QR 分流。
|
||
struct QRCodeScanResult: Equatable {
|
||
let rawJSON: String
|
||
let method: String
|
||
let orderNumber: String
|
||
let userId: Int
|
||
let time: String
|
||
let timeLong: Int64
|
||
let checkSum: String
|
||
|
||
static func parse(_ content: String) -> QRCodeScanResult? {
|
||
let trimmed = content.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
guard !trimmed.isEmpty, let data = trimmed.data(using: .utf8) else { return nil }
|
||
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return nil }
|
||
|
||
let method = (json["method"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||
let orderNumber = (json["order_number"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||
let userId = Self.parseInt(json["user_id"])
|
||
let timeLong = Self.parseTimeLong(json["time"])
|
||
let time = Self.parseTimeString(json["time"])
|
||
let checkSum = (json["check_sum"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||
|
||
return QRCodeScanResult(
|
||
rawJSON: trimmed,
|
||
method: method,
|
||
orderNumber: orderNumber,
|
||
userId: userId,
|
||
time: time,
|
||
timeLong: timeLong,
|
||
checkSum: checkSum
|
||
)
|
||
}
|
||
|
||
private static func parseInt(_ value: Any?) -> Int {
|
||
if let intValue = value as? Int { return intValue }
|
||
if let stringValue = value as? String, let intValue = Int(stringValue.trimmingCharacters(in: .whitespacesAndNewlines)) {
|
||
return intValue
|
||
}
|
||
if let doubleValue = value as? Double { return Int(doubleValue) }
|
||
return 0
|
||
}
|
||
|
||
private static func parseTimeLong(_ value: Any?) -> Int64 {
|
||
if let intValue = value as? Int64 { return intValue }
|
||
if let intValue = value as? Int { return Int64(intValue) }
|
||
if let doubleValue = value as? Double { return Int64(doubleValue) }
|
||
if let stringValue = value as? String, let intValue = Int64(stringValue.trimmingCharacters(in: .whitespacesAndNewlines)) {
|
||
return intValue
|
||
}
|
||
return 0
|
||
}
|
||
|
||
private static func parseTimeString(_ value: Any?) -> String {
|
||
if let stringValue = value as? String {
|
||
return stringValue.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
}
|
||
let longValue = parseTimeLong(value)
|
||
guard longValue > 0 else { return "" }
|
||
let seconds = longValue > 1_000_000_000_000 ? TimeInterval(longValue) / 1000 : TimeInterval(longValue)
|
||
let date = Date(timeIntervalSince1970: seconds)
|
||
let formatter = DateFormatter()
|
||
formatter.locale = Locale(identifier: "zh_CN")
|
||
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
||
return formatter.string(from: date)
|
||
}
|
||
}
|