fix: all iOS compile errors - protocols, missing fields, colors, shadowed max
- Protocol conformance: list→listAll with extension defaults - ContinueLearningResponse has no lastPosition→use nil - LearningSession has no readingTargetType/materialId→use defaults - Color.zxBlue→Color.blue, Color.zxIndigo→Color.indigo - Shadowed max parameter→Swift.max - ForEach Identifiable→explicit id: \.id Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
d28dba29fc
commit
def8c4c93a
Binary file not shown.
@ -39,10 +39,10 @@ struct AnalysisHomeView: View {
|
||||
}
|
||||
if let ls = viewModel.learningSummary {
|
||||
HStack(spacing: 12) {
|
||||
ZXStatBadge(icon: "book.pages", label: "今日阅读", value: "\(ls.todaySeconds / 60) 分钟", trend: "", color: Color.zxBlue)
|
||||
ZXStatBadge(icon: "book.pages", label: "今日阅读", value: "\(ls.todaySeconds / 60) 分钟", trend: "", color: Color.blue)
|
||||
ZXStatBadge(icon: "calendar.badge.clock", label: "本周阅读", value: "\(ls.weekSeconds / 60) 分钟", trend: "", color: Color.zxTeal)
|
||||
ZXStatBadge(icon: "doc.text", label: "已读资料", value: "\(ls.markedReadCount) 本", trend: "", color: Color.zxGreen)
|
||||
ZXStatBadge(icon: "books.vertical", label: "阅读资料", value: "\(ls.materialsReadCount) 本", trend: "", color: Color.zxIndigo)
|
||||
ZXStatBadge(icon: "books.vertical", label: "阅读资料", value: "\(ls.materialsReadCount) 本", trend: "", color: Color.indigo)
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
@ -88,7 +88,7 @@ struct AnalysisHomeView: View {
|
||||
Spacer()
|
||||
Text("最近 \(viewModel.recentRecords.count) 条").font(.system(size: 12)).foregroundColor(Color.zxF04)
|
||||
}
|
||||
ForEach(viewModel.recentRecords.prefix(5)) { rec in
|
||||
ForEach(viewModel.recentRecords.prefix(5), id: \.id) { rec in
|
||||
HStack(spacing: 10) {
|
||||
Circle().fill(rec.recordType == "reading" ? Color.zxPurple : Color.zxGreen).frame(width: 8, height: 8)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
@ -275,5 +275,5 @@ private func formatDuration(_ seconds: Int) -> String {
|
||||
|
||||
private func barHeight(val: Int, max: Int) -> CGFloat {
|
||||
guard max > 0 else { return 8 }
|
||||
return max(8, CGFloat(val) / CGFloat(max) * 60)
|
||||
return Swift.max(8, CGFloat(val) / CGFloat(max) * 60)
|
||||
}
|
||||
|
||||
@ -9,14 +9,20 @@ protocol KnowledgeBaseServicing {
|
||||
extension KnowledgeBaseService: KnowledgeBaseServicing {}
|
||||
|
||||
protocol KnowledgeItemServicing {
|
||||
func list(knowledgeBaseId: String, sortBy: String?, order: String?) async throws -> [KnowledgeItem]
|
||||
func listAll(knowledgeBaseId: String) async throws -> [KnowledgeItem]
|
||||
}
|
||||
extension KnowledgeItemService: KnowledgeItemServicing {
|
||||
func listAll(knowledgeBaseId: String) async throws -> [KnowledgeItem] {
|
||||
try await list(knowledgeBaseId: knowledgeBaseId, sortBy: nil, order: nil)
|
||||
}
|
||||
}
|
||||
extension KnowledgeItemService: KnowledgeItemServicing {}
|
||||
|
||||
protocol QuizServicing {
|
||||
func list(knowledgeBaseId: String) async throws -> [Quiz]
|
||||
func listAll(knowledgeBaseId: String) async throws -> [Quiz]
|
||||
}
|
||||
extension QuizService: QuizServicing {
|
||||
func listAll(knowledgeBaseId: String) async throws -> [Quiz] { try await list(knowledgeBaseId: knowledgeBaseId) }
|
||||
}
|
||||
extension QuizService: QuizServicing {}
|
||||
|
||||
protocol ReadingProgressServicing {
|
||||
func getReadingProgress(materialId: String, targetType: String) async throws -> MaterialReadingProgressDTO
|
||||
@ -69,8 +75,8 @@ final class MaterialDetailViewModel: ObservableObject {
|
||||
isLoading = true
|
||||
|
||||
async let kbResult = try? kbService.detail(id: knowledgeBaseId)
|
||||
async let itemsResult = try? itemService.list(knowledgeBaseId: knowledgeBaseId)
|
||||
async let quizzesResult = try? quizService.list(knowledgeBaseId: knowledgeBaseId)
|
||||
async let itemsResult = try? itemService.listAll(knowledgeBaseId: knowledgeBaseId)
|
||||
async let quizzesResult = try? quizService.listAll(knowledgeBaseId: knowledgeBaseId)
|
||||
async let progressResult: MaterialReadingProgressDTO? = {
|
||||
if let mid = materialId {
|
||||
return try? await readingService.getReadingProgress(materialId: mid, targetType: "knowledge_source")
|
||||
|
||||
@ -4,9 +4,11 @@ import Foundation
|
||||
// MARK: - Service protocols (for testability)
|
||||
|
||||
protocol SessionServicing {
|
||||
func list() async throws -> [LearningSession]
|
||||
func listAll() async throws -> [LearningSession]
|
||||
}
|
||||
extension LearningSessionService: SessionServicing {
|
||||
func listAll() async throws -> [LearningSession] { try await list() }
|
||||
}
|
||||
extension LearningSessionService: SessionServicing {}
|
||||
|
||||
protocol ReviewServicing {
|
||||
func dueCards() async throws -> [ReviewCard]
|
||||
@ -14,9 +16,11 @@ protocol ReviewServicing {
|
||||
extension ReviewService: ReviewServicing {}
|
||||
|
||||
protocol KBListServicing {
|
||||
func list() async throws -> [KnowledgeBase]
|
||||
func listAll() async throws -> [KnowledgeBase]
|
||||
}
|
||||
extension KnowledgeBaseService: KBListServicing {
|
||||
func listAll() async throws -> [KnowledgeBase] { try await list() }
|
||||
}
|
||||
extension KnowledgeBaseService: KBListServicing {}
|
||||
|
||||
protocol QuizListServicing {
|
||||
func listAll() async throws -> [Quiz]
|
||||
@ -98,10 +102,10 @@ final class StudyHomeViewModel: ObservableObject {
|
||||
loadingState = .loading
|
||||
banner = nil
|
||||
|
||||
async let sessions = try? sessionService.list()
|
||||
async let sessions = try? sessionService.listAll()
|
||||
async let dueCards = try? reviewService.dueCards()
|
||||
async let quizzes = try? quizService.listAll()
|
||||
async let knowledgeBases = try? kbService.list()
|
||||
async let knowledgeBases = try? kbService.listAll()
|
||||
async let summary = try? activityService.summary()
|
||||
async let streak = try? activityService.streak()
|
||||
|
||||
@ -135,10 +139,10 @@ final class StudyHomeViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
func refresh() async {
|
||||
async let sessions = try? sessionService.list()
|
||||
async let sessions = try? sessionService.listAll()
|
||||
async let dueCards = try? reviewService.dueCards()
|
||||
async let quizzes = try? quizService.listAll()
|
||||
async let knowledgeBases = try? kbService.list()
|
||||
async let knowledgeBases = try? kbService.listAll()
|
||||
async let summary = try? activityService.summary()
|
||||
async let streak = try? activityService.streak()
|
||||
|
||||
@ -176,8 +180,7 @@ final class StudyHomeViewModel: ObservableObject {
|
||||
let resolved = MaterialPathResolver.resolve(materialId: materialId, apiType: cl.type, title: cl.title) {
|
||||
let kbTitle = cl.title ?? knowledgeBases.first?.title ?? "学习"
|
||||
let elapsed = formatElapsedSince(cl.lastReadAt)
|
||||
let pos = cl.lastPosition.flatMap { ReadingPositionAdapter.fromValue($0) }
|
||||
return .continueSession(materialId: materialId, filePath: resolved.filePath, materialType: resolved.materialType, kbTitle: kbTitle, elapsed: elapsed, resumePosition: pos)
|
||||
return .continueSession(materialId: materialId, filePath: resolved.filePath, materialType: resolved.materialType, kbTitle: kbTitle, elapsed: elapsed, resumePosition: nil)
|
||||
}
|
||||
|
||||
if let unfinished = sessions
|
||||
@ -186,8 +189,7 @@ final class StudyHomeViewModel: ObservableObject {
|
||||
.first {
|
||||
let kbTitle = knowledgeBases.first(where: { $0.id == unfinished.knowledgeBaseId })?.title ?? "学习"
|
||||
let elapsed = formatElapsedSince(unfinished.startedAt)
|
||||
let mt: MaterialType = unfinished.readingTargetType == "knowledge_source" ? .unknown : .unknown
|
||||
return .continueSession(materialId: unfinished.materialId ?? "", filePath: "", materialType: mt, kbTitle: kbTitle, elapsed: elapsed, resumePosition: nil)
|
||||
return .continueSession(materialId: "", filePath: "", materialType: .unknown, kbTitle: kbTitle, elapsed: elapsed, resumePosition: nil)
|
||||
}
|
||||
|
||||
if !dueCards.isEmpty {
|
||||
|
||||
@ -10,7 +10,7 @@ private final class MockKnowledgeBaseService: KnowledgeBaseServicing {
|
||||
|
||||
private final class MockKnowledgeItemService: KnowledgeItemServicing {
|
||||
var items: [KnowledgeItem] = []
|
||||
func list(knowledgeBaseId: String, sortBy: String?, order: String?) async throws -> [KnowledgeItem] { items }
|
||||
func listAll(knowledgeBaseId: String) async throws -> [KnowledgeItem] { items }
|
||||
}
|
||||
|
||||
private final class MockQuizService: QuizServicing {
|
||||
|
||||
@ -5,7 +5,7 @@ import XCTest
|
||||
|
||||
private final class MockSessionService: SessionServicing {
|
||||
var sessions: [LearningSession] = []
|
||||
func list() async throws -> [LearningSession] { sessions }
|
||||
func listAll() async throws -> [LearningSession] { sessions }
|
||||
}
|
||||
|
||||
private final class MockReviewService: ReviewServicing {
|
||||
@ -20,7 +20,7 @@ private final class MockQuizListService: QuizListServicing {
|
||||
|
||||
private final class MockKBListService: KBListServicing {
|
||||
var kbs: [KnowledgeBase] = []
|
||||
func list() async throws -> [KnowledgeBase] { kbs }
|
||||
func listAll() async throws -> [KnowledgeBase] { kbs }
|
||||
}
|
||||
|
||||
private final class MockActivityHomeService: ActivityHomeServicing {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user