迁移合作订单完整能力,并统一 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

@ -15,20 +15,94 @@ final class PermissionContext: ObservableObject {
@Published private(set) var permissionURIs: Set<String> = []
@Published var currentRole: RoleInfo?
/// ID
func replaceRolePermissions(_ rolePermissions: [RolePermissionResponse], currentRoleId: Int? = nil) {
/// App role_code legacy id
var currentAppRole: AppRoleCode? {
if let code = AppRoleCode.fromCode(currentRole?.roleCode) { return code }
if let roleId = currentRole?.id, let code = AppRoleCode.fromLegacyRoleId(roleId) { return code }
return AppRoleCode.fromRoleName(currentRole?.name)
}
/// role_code
func replaceRolePermissions(
_ rolePermissions: [RolePermissionResponse],
currentRoleCode: String? = nil,
cachedLegacyRoleId: Int? = nil,
roleName: String? = nil
) {
self.rolePermissions = rolePermissions
currentRole = currentRoleId.flatMap { id in
rolePermissions.first { $0.role.id == id }?.role
} ?? currentRole.flatMap { role in
rolePermissions.first { $0.role.id == role.id }?.role
} ?? rolePermissions.first?.role
let resolvedCode = RolePermissionMatching.resolveRoleCode(
roleCode: currentRoleCode,
roleId: cachedLegacyRoleId,
roleName: roleName,
permissions: rolePermissions
)?.rawValue ?? currentRoleCode
if let matched = RolePermissionMatching.match(
in: rolePermissions,
roleCode: resolvedCode,
roleId: cachedLegacyRoleId,
roleName: roleName ?? currentRole?.name
) {
currentRole = matched.role
} else if let currentRole,
let matched = rolePermissions.first(where: { $0.role.id == currentRole.id }) {
self.currentRole = matched.role
} else {
currentRole = rolePermissions.first?.role
}
permissionURIs = Set(Self.flattenPermissions(currentRole?.permission ?? []))
}
///
func selectRole(code: AppRoleCode, accountContext: AccountContext) {
guard let rolePermission = rolePermissions.first(where: {
AppRoleCode.fromCode($0.role.roleCode) == code
}) else { return }
applyRoleSelection(rolePermission, accountContext: accountContext)
}
/// legacy id使 API role id
func selectRole(id roleId: Int, accountContext: AccountContext) {
guard let rolePermission = rolePermissions.first(where: { $0.role.id == roleId }) else { return }
applyRoleSelection(rolePermission, accountContext: accountContext)
}
/// URI
func canAccess(_ uri: String) -> Bool {
permissionURIs.contains(uri.trimmingCharacters(in: .whitespacesAndNewlines))
}
/// URI API
func topLevelPermissionURIs(for roleCode: String?) -> [String] {
guard let roleCode,
let rolePermission = matchedRolePermission(roleCode: roleCode) else {
return []
}
return rolePermission.role.permission.compactMap { item in
let uri = item.uri.trimmingCharacters(in: .whitespacesAndNewlines)
return uri.isEmpty ? nil : uri
}
}
///
func currentRoleScenicScopes() -> [BusinessScope] {
guard let currentRole else { return [] }
guard let rolePermission = matchedRolePermission(roleCode: currentRole.roleCode)
?? rolePermissions.first(where: { $0.role.id == currentRole.id }) else {
return []
}
return Self.uniqueScenicScopes(from: rolePermission.scenic)
}
/// 退
func reset() {
rolePermissions = []
permissionURIs = []
currentRole = nil
}
///
private func applyRoleSelection(_ rolePermission: RolePermissionResponse, accountContext: AccountContext) {
currentRole = rolePermission.role
permissionURIs = Set(Self.flattenPermissions(rolePermission.role.permission))
@ -41,25 +115,14 @@ final class PermissionContext: ObservableObject {
)
}
/// URI
func canAccess(_ uri: String) -> Bool {
permissionURIs.contains(uri.trimmingCharacters(in: .whitespacesAndNewlines))
}
///
func currentRoleScenicScopes() -> [BusinessScope] {
guard let currentRole else { return [] }
guard let rolePermission = rolePermissions.first(where: { $0.role.id == currentRole.id }) else {
return []
}
return Self.uniqueScenicScopes(from: rolePermission.scenic)
}
/// 退
func reset() {
rolePermissions = []
permissionURIs = []
currentRole = nil
/// role_code
private func matchedRolePermission(roleCode: String) -> RolePermissionResponse? {
RolePermissionMatching.match(
in: rolePermissions,
roleCode: roleCode,
roleId: nil,
roleName: nil
)
}
/// URI