135 lines
4.3 KiB
Swift
135 lines
4.3 KiB
Swift
//
|
|
// AccountDeletionModels.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// 注销核验资产,使用中性文案展示当前账号拥有的数据与权益。
|
|
struct AccountDeletionAssetSummary: Codable, Hashable, Sendable {
|
|
|
|
/// 注销核验覆盖的资产类型。
|
|
enum Kind: String, Codable, CaseIterable, Sendable {
|
|
case wallet
|
|
case works
|
|
case projects
|
|
case cloudFiles
|
|
}
|
|
|
|
let kind: Kind
|
|
let title: String
|
|
let valueText: String
|
|
}
|
|
|
|
/// 注销前置核验结果,包含资产快照和注销影响说明。
|
|
struct AccountDeletionPrecheck: Equatable, Sendable {
|
|
let assets: [AccountDeletionAssetSummary]
|
|
let consequences: [String]
|
|
}
|
|
|
|
/// 注销申请当前状态。
|
|
enum AccountDeletionRequestStatus: String, Codable, Sendable {
|
|
case pending
|
|
case canceled
|
|
case completed
|
|
}
|
|
|
|
/// 注销申请记录,保存7天冷静期及用户确认的资产范围。
|
|
struct AccountDeletionRequest: Codable, Equatable, Sendable {
|
|
let id: UUID
|
|
let clientRequestID: UUID
|
|
let username: String
|
|
let submittedAt: Date
|
|
let scheduledDeletionAt: Date
|
|
var status: AccountDeletionRequestStatus
|
|
let acknowledgedAssetKinds: [AccountDeletionAssetSummary.Kind]
|
|
}
|
|
|
|
/// 登录时需要处理的注销状态。
|
|
enum AccountDeletionLoginState: Equatable, Sendable {
|
|
case none
|
|
case pending(AccountDeletionRequest)
|
|
case completed(AccountDeletionRequest)
|
|
}
|
|
|
|
/// 注销短信验证页所需的稳定上下文。
|
|
struct AccountDeletionVerificationContext: Equatable, Sendable {
|
|
let username: String
|
|
let maskedPhone: String
|
|
let assets: [AccountDeletionAssetSummary]
|
|
}
|
|
|
|
/// 注销业务错误,统一提供可直接展示的中文提示。
|
|
enum AccountDeletionError: LocalizedError, Equatable {
|
|
case missingIdentity
|
|
case invalidVerificationCode
|
|
case incompleteAcknowledgement
|
|
case noPendingRequest
|
|
case cancellationExpired
|
|
case deletionCompleted
|
|
case persistenceFailed
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .missingIdentity:
|
|
"当前登录账号缺少手机号,暂时无法提交注销"
|
|
case .invalidVerificationCode:
|
|
"验证码错误,请输入演示验证码 123456"
|
|
case .incompleteAcknowledgement:
|
|
"请先确认已了解全部资产和注销后果"
|
|
case .noPendingRequest:
|
|
"当前账号没有待取消的注销申请"
|
|
case .cancellationExpired:
|
|
"7天取消期限已过,无法恢复账号"
|
|
case .deletionCompleted:
|
|
"账号已完成注销,无法继续登录"
|
|
case .persistenceFailed:
|
|
"注销状态保存失败,请稍后重试"
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 注销账号身份工具,统一手机号规范化、掩码和当前登录身份解析。
|
|
enum AccountDeletionIdentity {
|
|
|
|
/// 从当前会话读取登录手机号,优先使用登录页保存的原始账号。
|
|
static func currentUsername(session: AppSessionStore = AppStore.shared.session) -> String? {
|
|
let candidates = [session.lastLoginUsername, session.phone]
|
|
return candidates
|
|
.compactMap { $0 }
|
|
.map(normalizedUsername)
|
|
.first { !$0.isEmpty }
|
|
}
|
|
|
|
/// 将手机号账号规范化为纯数字,并兼容 +86 前缀。
|
|
static func normalizedUsername(_ value: String) -> String {
|
|
var digits = value.filter(\.isNumber)
|
|
if digits.hasPrefix("86"), digits.count == 13 {
|
|
digits.removeFirst(2)
|
|
}
|
|
return digits
|
|
}
|
|
|
|
/// 将手机号转换为用于页面展示的脱敏格式。
|
|
static func maskedPhone(_ value: String) -> String {
|
|
let username = normalizedUsername(value)
|
|
guard username.count == 11 else { return username }
|
|
let start = username.prefix(3)
|
|
let end = username.suffix(4)
|
|
return "\(start)****\(end)"
|
|
}
|
|
}
|
|
|
|
/// 注销时间格式化工具,统一成功页和登录恢复弹窗的中文时间。
|
|
enum AccountDeletionDateFormatter {
|
|
|
|
/// 将服务端计划删除时间格式化为中文日期时间。
|
|
static func displayText(_ date: Date) -> String {
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "zh_CN")
|
|
formatter.timeZone = TimeZone(identifier: "Asia/Shanghai")
|
|
formatter.dateFormat = "yyyy年M月d日 HH:mm"
|
|
return formatter.string(from: date)
|
|
}
|
|
}
|