From ec1eed8f04c6e23b3d05700320c6c8776af52957 Mon Sep 17 00:00:00 2001 From: AndyChen1024 Date: Tue, 15 Sep 2026 14:35:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9A=E4=B9=89=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E4=B8=8E=E7=94=A8=E4=BE=8B=EF=BC=88=E5=90=AB?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreDomain/CheckinRepository.swift | 9 ++++++ .../Sources/CoreDomain/CheckinUseCase.swift | 18 ++++++++++++ .../Sources/CoreDomain/HomeRepository.swift | 5 ++-- .../Sources/CoreDomain/HomeUseCase.swift | 8 ++++-- .../Sources/CoreDomain/PlanRepository.swift | 8 ++++++ .../Sources/CoreDomain/PlanUseCase.swift | 22 +++++++++++++++ .../CoreDomain/ProfileRepository.swift | 7 +++++ .../Sources/CoreDomain/ProfileUseCase.swift | 14 ++++++++++ .../CoreDomain/SessionRepository.swift | 28 +++++++++++++++++++ .../Sources/CoreDomain/SessionUseCase.swift | 24 ++++++++++++++++ 10 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 IosClientKit/Sources/CoreDomain/CheckinRepository.swift create mode 100644 IosClientKit/Sources/CoreDomain/CheckinUseCase.swift create mode 100644 IosClientKit/Sources/CoreDomain/PlanRepository.swift create mode 100644 IosClientKit/Sources/CoreDomain/PlanUseCase.swift create mode 100644 IosClientKit/Sources/CoreDomain/ProfileRepository.swift create mode 100644 IosClientKit/Sources/CoreDomain/ProfileUseCase.swift create mode 100644 IosClientKit/Sources/CoreDomain/SessionRepository.swift create mode 100644 IosClientKit/Sources/CoreDomain/SessionUseCase.swift diff --git a/IosClientKit/Sources/CoreDomain/CheckinRepository.swift b/IosClientKit/Sources/CoreDomain/CheckinRepository.swift new file mode 100644 index 0000000..9bf2dfd --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/CheckinRepository.swift @@ -0,0 +1,9 @@ +import CoreModel + +/// 打卡数据仓库协议(定义在 domain 层,实现放 CoreRepository)。 +public protocol CheckinRepository: Sendable { + /// 观察打卡数据。 + func observeCheckin() -> AsyncThrowingStream + /// 提交打卡状态。 + func submitCheckin(status: CheckinStatus) async throws +} diff --git a/IosClientKit/Sources/CoreDomain/CheckinUseCase.swift b/IosClientKit/Sources/CoreDomain/CheckinUseCase.swift new file mode 100644 index 0000000..9f7e57a --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/CheckinUseCase.swift @@ -0,0 +1,18 @@ +import CoreModel + +/// 获取/提交打卡数据的用例。 +public struct CheckinUseCase: Sendable { + private let repository: CheckinRepository + + public init(repository: CheckinRepository) { + self.repository = repository + } + + public func observeCheckin() -> AsyncThrowingStream { + repository.observeCheckin() + } + + public func submitCheckin(status: CheckinStatus) async throws { + try await repository.submitCheckin(status: status) + } +} diff --git a/IosClientKit/Sources/CoreDomain/HomeRepository.swift b/IosClientKit/Sources/CoreDomain/HomeRepository.swift index 8644765..cf72216 100644 --- a/IosClientKit/Sources/CoreDomain/HomeRepository.swift +++ b/IosClientKit/Sources/CoreDomain/HomeRepository.swift @@ -1,8 +1,9 @@ import CoreModel /// Home 数据仓库协议(定义在 domain 层,实现放 CoreRepository)。 -/// Kotlin: interface HomeRepository { fun observeHome(): Flow } public protocol HomeRepository: Sendable { - /// Kotlin: Flow → Swift: AsyncThrowingStream + /// 已登录首页。 func observeHome() -> AsyncThrowingStream + /// 游客首页。 + func observeGuestHome() -> AsyncThrowingStream } diff --git a/IosClientKit/Sources/CoreDomain/HomeUseCase.swift b/IosClientKit/Sources/CoreDomain/HomeUseCase.swift index 5b190cd..34712a6 100644 --- a/IosClientKit/Sources/CoreDomain/HomeUseCase.swift +++ b/IosClientKit/Sources/CoreDomain/HomeUseCase.swift @@ -1,7 +1,6 @@ import CoreModel /// 获取 Home 数据的用例。 -/// Kotlin: class HomeUseCase(...) { suspend operator fun invoke(): HomeData } public struct HomeUseCase: Sendable { private let repository: HomeRepository @@ -9,8 +8,13 @@ public struct HomeUseCase: Sendable { self.repository = repository } - /// Kotlin: Flow → Swift: AsyncThrowingStream + /// 已登录首页。 public func observeHome() -> AsyncThrowingStream { repository.observeHome() } + + /// 游客首页。 + public func observeGuestHome() -> AsyncThrowingStream { + repository.observeGuestHome() + } } diff --git a/IosClientKit/Sources/CoreDomain/PlanRepository.swift b/IosClientKit/Sources/CoreDomain/PlanRepository.swift new file mode 100644 index 0000000..4b997eb --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/PlanRepository.swift @@ -0,0 +1,8 @@ +import CoreModel + +/// 计划数据仓库协议(定义在 domain 层,实现放 CoreRepository)。 +public protocol PlanRepository: Sendable { + func observePlan(type: PlanType) -> AsyncThrowingStream + func observePlanSubmit(type: PlanType, periodKey: String) -> AsyncThrowingStream + func savePlan(type: PlanType, periodKey: String, content: String, attachments: [String]) async throws +} diff --git a/IosClientKit/Sources/CoreDomain/PlanUseCase.swift b/IosClientKit/Sources/CoreDomain/PlanUseCase.swift new file mode 100644 index 0000000..1519b08 --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/PlanUseCase.swift @@ -0,0 +1,22 @@ +import CoreModel + +/// 获取/提交计划数据的用例。 +public struct PlanUseCase: Sendable { + private let repository: PlanRepository + + public init(repository: PlanRepository) { + self.repository = repository + } + + public func observePlan(type: PlanType) -> AsyncThrowingStream { + repository.observePlan(type: type) + } + + public func observePlanSubmit(type: PlanType, periodKey: String) -> AsyncThrowingStream { + repository.observePlanSubmit(type: type, periodKey: periodKey) + } + + public func savePlan(type: PlanType, periodKey: String, content: String, attachments: [String]) async throws { + try await repository.savePlan(type: type, periodKey: periodKey, content: content, attachments: attachments) + } +} diff --git a/IosClientKit/Sources/CoreDomain/ProfileRepository.swift b/IosClientKit/Sources/CoreDomain/ProfileRepository.swift new file mode 100644 index 0000000..ae5ceda --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/ProfileRepository.swift @@ -0,0 +1,7 @@ +import CoreModel + +/// 个人资料仓库协议(定义在 domain 层,实现放 CoreRepository)。 +public protocol ProfileRepository: Sendable { + /// Kotlin: Flow → Swift: AsyncThrowingStream + func observeProfile() -> AsyncThrowingStream +} diff --git a/IosClientKit/Sources/CoreDomain/ProfileUseCase.swift b/IosClientKit/Sources/CoreDomain/ProfileUseCase.swift new file mode 100644 index 0000000..55ceaad --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/ProfileUseCase.swift @@ -0,0 +1,14 @@ +import CoreModel + +/// 获取个人资料的用例。 +public struct ProfileUseCase: Sendable { + private let repository: ProfileRepository + + public init(repository: ProfileRepository) { + self.repository = repository + } + + public func observeProfile() -> AsyncThrowingStream { + repository.observeProfile() + } +} diff --git a/IosClientKit/Sources/CoreDomain/SessionRepository.swift b/IosClientKit/Sources/CoreDomain/SessionRepository.swift new file mode 100644 index 0000000..4aed400 --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/SessionRepository.swift @@ -0,0 +1,28 @@ +import Foundation + +/// 会话相关错误。 +public enum SessionError: Error, Sendable, LocalizedError { + case invalidPhone + case wrongCode + case phoneNotMatched + + public var errorDescription: String? { + switch self { + case .invalidPhone: return "请输入正确的手机号" + case .wrongCode: return "验证码错误" + case .phoneNotMatched: return "手机号未匹配,无法登录" + } + } +} + +/// 会话仓库协议(登录态 / 手机号登录)。 +public protocol SessionRepository: Sendable { + /// 观察登录态。 + func observeIsLoggedIn() -> AsyncThrowingStream + /// 请求短信验证码。 + func requestSmsCode(phone: String) async throws + /// 手机号 + 验证码登录。 + func login(phone: String, code: String) async throws + /// 退出登录。 + func logout() async throws +} diff --git a/IosClientKit/Sources/CoreDomain/SessionUseCase.swift b/IosClientKit/Sources/CoreDomain/SessionUseCase.swift new file mode 100644 index 0000000..0857f5e --- /dev/null +++ b/IosClientKit/Sources/CoreDomain/SessionUseCase.swift @@ -0,0 +1,24 @@ +/// 会话用例。 +public struct SessionUseCase: Sendable { + private let repository: SessionRepository + + public init(repository: SessionRepository) { + self.repository = repository + } + + public func observeIsLoggedIn() -> AsyncThrowingStream { + repository.observeIsLoggedIn() + } + + public func requestSmsCode(phone: String) async throws { + try await repository.requestSmsCode(phone: phone) + } + + public func login(phone: String, code: String) async throws { + try await repository.login(phone: phone, code: code) + } + + public func logout() async throws { + try await repository.logout() + } +}