迁移合作订单完整能力,并统一 AppRoleCode 角色权限与首页菜单展示。

新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-29 13:33:00 +08:00
parent d310d26293
commit 1970572edd
66 changed files with 4247 additions and 201 deletions

View File

@ -0,0 +1,107 @@
//
// SaleUserQrParser.swift
// suixinkan
//
// Created by Codex on 2026/6/29.
//
import Foundation
/// sale_user_id
enum SaleUserQrParser {
/// method
static let methodSaleUserBind = "sale_user_bind"
/// sale_user_id
/// `{"method":"sale_user_bind","sale_user_id":2}`
/// URL query method JSON
static func parseSaleUserId(_ content: String) -> Int? {
let trimmed = content.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty { return nil }
if trimmed.hasPrefix("{") {
if let value = parseFromJSON(trimmed) {
return value
}
}
if let value = Int(trimmed), value > 0 {
return value
}
if trimmed.contains("://") || trimmed.contains("?") {
return parseFromURL(trimmed)
}
return nil
}
///
static func isSaleUserBindQR(_ content: String) -> Bool {
guard let object = jsonObject(from: content) else { return false }
let method = (object["method"] as? String)?
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
return method == methodSaleUserBind
}
private static func parseFromJSON(_ json: String) -> Int? {
guard let object = jsonObject(from: json) else { return nil }
return parseFromJSONObject(object)
}
private static func jsonObject(from json: String) -> [String: Any]? {
guard let data = json.data(using: .utf8),
let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
else { return nil }
return object
}
private static func parseFromJSONObject(_ object: [String: Any]) -> Int? {
let method = (object["method"] as? String)?
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if method == methodSaleUserBind {
return readIntValue(object["sale_user_id"])
}
return readSaleUserId(object)
}
private static func readSaleUserId(_ object: [String: Any]) -> Int? {
let keys = ["sale_user_id", "saleUserId", "user_id", "id"]
for key in keys {
if let value = readIntValue(object[key]) {
return value
}
}
return nil
}
private static func readIntValue(_ value: Any?) -> Int? {
switch value {
case let intValue as Int where intValue > 0:
return intValue
case let number as NSNumber where number.intValue > 0:
return number.intValue
case let stringValue as String:
let trimmed = stringValue.trimmingCharacters(in: .whitespacesAndNewlines)
if let intValue = Int(trimmed), intValue > 0 {
return intValue
}
return nil
default:
return nil
}
}
private static func parseFromURL(_ urlString: String) -> Int? {
guard let components = URLComponents(string: urlString) else { return nil }
let keys = ["sale_user_id", "saleUserId", "user_id", "id"]
for key in keys {
if let value = components.queryItems?.first(where: { $0.name == key })?.value,
let intValue = Int(value.trimmingCharacters(in: .whitespacesAndNewlines)),
intValue > 0 {
return intValue
}
}
return nil
}
}