feat: study home with daily plan card and quick actions

This commit is contained in:
pluv committed 2026-10-24 01:30:35 +08:00
1 parent 277ead9fe7
commit 0423027e97
4 files changed
+452 -6

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
/// 「学习」首页需要的一份排程摘要。
///
/// 目前由 [StudyPlan.sample] 提供示例数据;接上新内核后,这里应改为由排程
/// 返回的真实数据(到期条目数、新识记额度、历史平均速度等),UI 不需要改。
class StudyPlan {
const StudyPlan({
required this.deckName,
required this.algorithm,
required this.totalItems,
required this.activatedItems,
required this.dueItems,
required this.newItems,
required this.secondsPerItem,
});
/// 当前单元集名称。
final String deckName;
/// 该单元集使用的调度算法标识,如 `NSP-0`、`SM-2`。
final String algorithm;
/// 单元集条目总数。
final int totalItems;
/// 已激活(学过至少一次)的条目数。
final int activatedItems;
/// 今天到期、需要复习的条目数。
final int dueItems;
/// 今天还可以引入的新识记条目数。
final int newItems;
/// 单个条目完成一轮多谜题测验的平均耗时(秒)。
///
/// 用于把「今天要学多少」翻译成用户能感知的时间承诺。实测速度应当来自
/// 内核,这里先用经验值。
final int secondsPerItem;
/// 今天总共要处理的条目数。
int get itemCount => dueItems + newItems;
/// 今天是否无事可做。
bool get isEmpty => itemCount == 0;
/// 单元集整体完成度,0..1。
double get progress => totalItems == 0 ? 0 : activatedItems / totalItems;
/// 完成度百分比,保留一位小数。
String get progressPercent => '${(progress * 100).toStringAsFixed(1)}%';
/// 预计用时(分钟,向上取整)。条目数为 0 时返回 0。
int get estimatedMinutes => _minutes(itemCount, secondsPerItem);
/// 预计用时的展示文案。
String get estimatedLabel => isEmpty
? '今天没有到期的内容'
: '预计用时 $estimatedMinutes 分钟';
/// 示例数据:高考必背古诗文,NSP-0 调度。
static const StudyPlan sample = StudyPlan(
deckName: '高考必背古诗文',
algorithm: 'NSP-0',
totalItems: 950,
activatedItems: 295,
dueItems: 18,
newItems: 35,
secondsPerItem: 13,
);
static int _minutes(int itemCount, int secondsPerItem) {
if (itemCount <= 0 || secondsPerItem <= 0) {
return 0;
}
final int totalSeconds = itemCount * secondsPerItem;
return (totalSeconds + 59) ~/ 60;
}
}