137 lines
5.1 KiB
Swift
137 lines
5.1 KiB
Swift
import Combine
|
||
import CoreDomain
|
||
import CoreModel
|
||
import Foundation
|
||
|
||
/// Fake 计划仓库(骨架阶段返回假数据,可提交)。
|
||
public final class FakePlanRepository: PlanRepository, @unchecked Sendable {
|
||
private let plans: [PlanType: CurrentValueSubject<PlanRecord, Never>]
|
||
private var submits: [String: CurrentValueSubject<PlanSubmitData, Never>] = [:]
|
||
private let lock = NSLock()
|
||
|
||
public init() {
|
||
var dict: [PlanType: CurrentValueSubject<PlanRecord, Never>] = [:]
|
||
for type in PlanType.allCases {
|
||
dict[type] = CurrentValueSubject<PlanRecord, Never>(Self.seedPlan(type))
|
||
}
|
||
plans = dict
|
||
}
|
||
|
||
public func observePlan(type: PlanType) -> AsyncThrowingStream<PlanRecord, Error> {
|
||
Self.stream(plans[type]!)
|
||
}
|
||
|
||
public func observePlanSubmit(type: PlanType, periodKey: String) -> AsyncThrowingStream<PlanSubmitData, Error> {
|
||
Self.stream(submitSubject(type: type, periodKey: periodKey))
|
||
}
|
||
|
||
public func savePlan(type: PlanType, periodKey: String, content: String, attachments: [String]) async throws {
|
||
try await Task.sleep(for: .milliseconds(300))
|
||
|
||
let submit = submitSubject(type: type, periodKey: periodKey)
|
||
let currentSubmit = submit.value
|
||
submit.value = PlanSubmitData(
|
||
content: content,
|
||
attachments: attachments,
|
||
checked: true,
|
||
canSubmit: currentSubmit.canSubmit,
|
||
message: currentSubmit.message,
|
||
history: currentSubmit.history
|
||
)
|
||
|
||
let plan = plans[type]!
|
||
let currentPlan = plan.value
|
||
plan.value = PlanRecord(
|
||
type: currentPlan.type,
|
||
periodKey: currentPlan.periodKey,
|
||
canSubmit: currentPlan.canSubmit,
|
||
message: currentPlan.message,
|
||
myChecked: true,
|
||
myRecord: MyPlanRecord(status: "已完成", submittedTime: "现在", content: content, attachments: attachments),
|
||
groups: currentPlan.groups,
|
||
unassignedCount: currentPlan.unassignedCount
|
||
)
|
||
}
|
||
|
||
private func submitSubject(type: PlanType, periodKey: String) -> CurrentValueSubject<PlanSubmitData, Never> {
|
||
let key = "\(type.rawValue):\(periodKey)"
|
||
lock.lock()
|
||
defer { lock.unlock() }
|
||
if let existing = submits[key] {
|
||
return existing
|
||
}
|
||
let subject = CurrentValueSubject<PlanSubmitData, Never>(Self.seedSubmit(type: type))
|
||
submits[key] = subject
|
||
return subject
|
||
}
|
||
|
||
private static func stream<T>(_ subject: CurrentValueSubject<T, Never>) -> AsyncThrowingStream<T, Error> {
|
||
AsyncThrowingStream { continuation in
|
||
let cancellable = subject.sink { continuation.yield($0) }
|
||
continuation.onTermination = { _ in cancellable.cancel() }
|
||
}
|
||
}
|
||
|
||
private static func seedPlan(_ type: PlanType) -> PlanRecord {
|
||
PlanRecord(
|
||
type: type,
|
||
periodKey: periodKey(for: type),
|
||
canSubmit: true,
|
||
message: type == .weekly ? "本周计划提交截止:周日晚 23:59" : nil,
|
||
myChecked: type == .weekly,
|
||
myRecord: type == .weekly
|
||
? MyPlanRecord(status: "已完成", submittedTime: "今天 18:30", content: "本周完成两章学习,整理笔记并复习错题。", attachments: ["图1", "图2"])
|
||
: nil,
|
||
groups: seedGroups(),
|
||
unassignedCount: 2
|
||
)
|
||
}
|
||
|
||
private static func seedSubmit(type: PlanType) -> PlanSubmitData {
|
||
if type == .weekly {
|
||
return PlanSubmitData(
|
||
content: "本周完成两章学习,整理笔记并复习错题。",
|
||
attachments: ["图1", "图2"],
|
||
checked: true,
|
||
canSubmit: true,
|
||
message: nil,
|
||
history: []
|
||
)
|
||
}
|
||
return PlanSubmitData(
|
||
content: "",
|
||
attachments: [],
|
||
checked: false,
|
||
canSubmit: true,
|
||
message: nil,
|
||
history: [
|
||
MyPlanRecord(status: "已完成", submittedTime: "2026-08 完成", content: "上月计划内容……", attachments: []),
|
||
]
|
||
)
|
||
}
|
||
|
||
private static func periodKey(for type: PlanType) -> String {
|
||
switch type {
|
||
case .weekly: return "2026 第 37 周"
|
||
case .monthly: return "2026 年 9 月"
|
||
case .yearly: return "2026 年"
|
||
}
|
||
}
|
||
|
||
private static func seedGroups() -> [PlanGroup] {
|
||
[
|
||
PlanGroup(id: "g1", name: "进阶一组", checkedCount: 4, memberCount: 6, members: seedMembers()),
|
||
PlanGroup(id: "g2", name: "进阶二组", checkedCount: 5, memberCount: 5, members: seedMembers()),
|
||
PlanGroup(id: "g3", name: "进阶三组", checkedCount: 2, memberCount: 7, members: seedMembers()),
|
||
]
|
||
}
|
||
|
||
private static func seedMembers() -> [PlanMember] {
|
||
[
|
||
PlanMember(id: "p1", name: "张三", filled: true),
|
||
PlanMember(id: "p2", name: "李四", filled: true),
|
||
PlanMember(id: "p3", name: "王五", filled: false),
|
||
]
|
||
}
|
||
}
|