Implement profile tab with Android-aligned flows and OSS upload.

Add personal info page, account switch, real-name auth, withdrawal settings, session cache extensions, AlibabaCloudOSS SPM, and unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-06 16:01:05 +08:00
parent 02a80764ea
commit 005cac3f78
36 changed files with 4077 additions and 57 deletions

View File

@ -55,7 +55,7 @@ enum LoginValidationError: Equatable {
///
enum LoginResolution {
case completed(V9AuthResponse)
case completed(V9AuthResponse, AccountSwitchAccount)
case needsAccountSelection(AccountSelectionPayload)
}
@ -201,6 +201,8 @@ struct V9ScenicUser: Decodable, Equatable {
let phone: String
let scenicId: Int
let scenicName: String
let appRoleCode: String
let appRoleName: String
let isCurrent: Bool
var businessUserId: Int {
@ -241,6 +243,8 @@ struct V9ScenicUser: Decodable, Equatable {
case phone
case scenicId = "scenic_id"
case scenicName = "scenic_name"
case appRoleCode = "app_role_code"
case appRoleName = "app_role_name"
case isCurrent = "is_current"
}
@ -257,6 +261,8 @@ struct V9ScenicUser: Decodable, Equatable {
phone = try container.decodeLossyString(forKey: .phone)
scenicId = try container.decodeLossyInt(forKey: .scenicId) ?? 0
scenicName = try container.decodeLossyString(forKey: .scenicName)
appRoleCode = try container.decodeLossyString(forKey: .appRoleCode)
appRoleName = try container.decodeLossyString(forKey: .appRoleName)
isCurrent = try container.decodeLossyBool(forKey: .isCurrent) ?? false
}
}
@ -278,6 +284,8 @@ struct V9StoreUser: Decodable, Equatable {
let scenicName: String
let storeId: Int
let storeName: String
let appRoleCode: String
let appRoleName: String
let isCurrent: Bool
var businessUserId: Int {
@ -320,6 +328,8 @@ struct V9StoreUser: Decodable, Equatable {
case scenicName = "scenic_name"
case storeId = "store_id"
case storeName = "store_name"
case appRoleCode = "app_role_code"
case appRoleName = "app_role_name"
case isCurrent = "is_current"
}
@ -338,6 +348,8 @@ struct V9StoreUser: Decodable, Equatable {
scenicName = try container.decodeLossyString(forKey: .scenicName)
storeId = try container.decodeLossyInt(forKey: .storeId) ?? 0
storeName = try container.decodeLossyString(forKey: .storeName)
appRoleCode = try container.decodeLossyString(forKey: .appRoleCode)
appRoleName = try container.decodeLossyString(forKey: .appRoleName)
isCurrent = try container.decodeLossyBool(forKey: .isCurrent) ?? false
}
}