- 架构层:ViewModel/ObservableObject、Service/Repository、网络层 APIClient/APIEndpoint/APIError - 设计系统:Color(light:dark:) 自适应 28 色 Token、ColorSchemeManager 深浅色切换 - 全页面:AI 对话/反馈/回忆/薄弱点、知识库 CRUD、学习工作台、复习计划、学习分析、个人中心/设置 - 登录与引导:Sign in with Apple、AppSession 状态管理、引导流程、演示模式 - 本地持久化:FileCache + PersistenceController(学习任务/复习任务/学习记录) - 本地化:zh-Hans Localizable.strings ~120 条、ZXStrings 程序化引用、LanguageManager - 组件库:ZXTabBar/ZXBackHeader/ZXSTaskRow/ZXChartView/ZXTypingIndicator 等 22 个共享组件 - 等待名单:WaitlistView 邮箱收集表单 - 动效:ZXTypingIndicator AI 打字动画、ZXShimmerModifier 骨架屏 - 测试:StudyHomeViewModel/AIChatViewModel/ReviewPlanViewModel/FileCache 共 28 条 - Dynamic Type 支持 + 范围限制 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
48 lines
2.3 KiB
Swift
48 lines
2.3 KiB
Swift
import SwiftUI
|
||
|
||
struct ZXSTaskRow: View {
|
||
let task: StudyTaskEntity; var action: () -> Void
|
||
var body: some View {
|
||
Button(action: { withAnimation(.spring(response: 0.35, dampingFraction: 0.7)) { action() } }) {
|
||
HStack(spacing: 12) {
|
||
Image(systemName: task.isDone ? "checkmark.circle.fill" : "circle")
|
||
.font(.system(size: 20))
|
||
.foregroundColor(task.isDone ? Color.zxGreen : Color.zxF02)
|
||
VStack(alignment: .leading, spacing: 4) {
|
||
Text(task.title)
|
||
.font(.system(size: 13, weight: .semibold))
|
||
.foregroundColor(task.isDone ? Color.zxF04 : Color.zxF0)
|
||
.strikethrough(task.isDone)
|
||
HStack(spacing: 8) {
|
||
Text(task.taskType)
|
||
.font(.system(size: 10, weight: .semibold))
|
||
.foregroundColor(task.color)
|
||
.padding(.horizontal, 6).padding(.vertical, 1)
|
||
.background(task.color.opacity(0.12)).clipShape(Capsule())
|
||
Text("约 \(task.minutes) 分钟")
|
||
.font(.system(size: 10))
|
||
.foregroundColor(Color.zxF035)
|
||
}
|
||
}
|
||
Spacer()
|
||
if !task.isDone {
|
||
Image(systemName: "play.fill")
|
||
.font(.system(size: 14)).foregroundColor(.white)
|
||
.frame(width: 32, height: 32)
|
||
.background(ZXGradient.brand).clipShape(RoundedRectangle(cornerRadius: 10))
|
||
}
|
||
}
|
||
.padding(.horizontal, 16).padding(.vertical, 12)
|
||
.background(task.isDone ? Color.zxFill003 : Color.zxFill005)
|
||
.overlay(RoundedRectangle(cornerRadius: 14).stroke(
|
||
task.isDone ? Color.zxFill005 : Color.zxBorder008, lineWidth: 1
|
||
))
|
||
.clipShape(RoundedRectangle(cornerRadius: 14))
|
||
.opacity(task.isDone ? 0.6 : 1)
|
||
}
|
||
.foregroundColor(.primary)
|
||
.accessibilityLabel("\(task.title),\(task.isDone ? "已完成" : "未完成")")
|
||
.accessibilityHint(task.isDone ? "双击取消完成" : "双击标记完成")
|
||
}
|
||
}
|