Implement orders tab aligned with Android, including scan verify flows.

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>
This commit is contained in:
2026-07-06 16:59:53 +08:00
parent 6492f80ef0
commit 31d2b6094b
27 changed files with 4226 additions and 17 deletions

View File

@ -0,0 +1,55 @@
//
// SaleUserQrParser.swift
// suixinkan
//
import Foundation
/// Android `SaleUserQrParser`
enum SaleUserQrParser {
static let methodSaleUserBind = "sale_user_bind"
static func parseSaleUserId(_ content: String) -> Int? {
let trimmed = content.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return nil }
if trimmed.hasPrefix("{"), let data = trimmed.data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
if let fromMethod = parseFromJSON(json) { return fromMethod }
}
if let intValue = Int(trimmed), intValue > 0 { return intValue }
if trimmed.contains("://") || trimmed.contains("?"),
let components = URLComponents(string: trimmed) {
for key in ["sale_user_id", "saleUserId", "user_id", "id"] {
if let value = components.queryItems?.first(where: { $0.name == key })?.value,
let intValue = Int(value), intValue > 0 {
return intValue
}
}
}
return nil
}
private static func parseFromJSON(_ json: [String: Any]) -> Int? {
if let method = json["method"] as? String, method == methodSaleUserBind,
let id = readInt(json["sale_user_id"]), id > 0 {
return id
}
for key in ["sale_user_id", "saleUserId", "user_id", "id"] {
if let id = readInt(json[key]), id > 0 { return id }
}
return nil
}
private static func readInt(_ 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 nil
}
}