-
Notifications
You must be signed in to change notification settings - Fork 603
在 在看 页面 添加了周数分栏显示 #1650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
The head ref may contain hidden characters: "\u5728-\u518D\u770B\u9875\u9762-\u6DFB\u52A0\u4E86\u5468\u6570\u663E\u793A"
在 在看 页面 添加了周数分栏显示 #1650
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ import 'package:kazumi/modules/bangumi/bangumi_item.dart'; | |||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/modules/collect/collect_module.dart'; | ||||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/modules/collect/collect_change_module.dart'; | ||||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/modules/collect/collect_type.dart'; | ||||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/request/bangumi.dart'; | ||||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/utils/storage.dart'; | ||||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/utils/webdav.dart'; | ||||||||||||||||||||||||||||||||||||||||||
| import 'package:kazumi/repositories/collect_crud_repository.dart'; | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -20,6 +21,21 @@ abstract class _CollectController with Store { | |||||||||||||||||||||||||||||||||||||||||
| final _collectCrudRepository = Modular.get<ICollectCrudRepository>(); | ||||||||||||||||||||||||||||||||||||||||||
| final _collectRepository = Modular.get<ICollectRepository>(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // 时间表缓存:key=番剧ID, value=星期(0-6) | ||||||||||||||||||||||||||||||||||||||||||
| @observable | ||||||||||||||||||||||||||||||||||||||||||
| ObservableMap<int, int> _watchingCalendarWeekdayById = ObservableMap<int, int>(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // 构造函数:初始化时从缓存加载时间表数据 | ||||||||||||||||||||||||||||||||||||||||||
| _CollectController() { | ||||||||||||||||||||||||||||||||||||||||||
| _loadCachedCalendar(); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| @observable | ||||||||||||||||||||||||||||||||||||||||||
| bool isWatchingCalendarLoading = false; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| @observable | ||||||||||||||||||||||||||||||||||||||||||
| bool isWatchingCalendarReady = false; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Box setting = GStorage.setting; | ||||||||||||||||||||||||||||||||||||||||||
| List<BangumiItem> get favorites => _collectCrudRepository.getFavorites(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,6 +48,86 @@ abstract class _CollectController with Store { | |||||||||||||||||||||||||||||||||||||||||
| collectibles.addAll(_collectCrudRepository.getAllCollectibles()); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /// 从缓存加载时间表数据 | ||||||||||||||||||||||||||||||||||||||||||
| void _loadCachedCalendar() { | ||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||
| final cachedData = setting.get(SettingBoxKey.cachedWatchingCalendar); | ||||||||||||||||||||||||||||||||||||||||||
| if (cachedData != null && cachedData is Map) { | ||||||||||||||||||||||||||||||||||||||||||
| _watchingCalendarWeekdayById = ObservableMap<int, int>.of( | ||||||||||||||||||||||||||||||||||||||||||
| Map<int, int>.from(cachedData), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| if (_watchingCalendarWeekdayById.isNotEmpty) { | ||||||||||||||||||||||||||||||||||||||||||
| isWatchingCalendarReady = true; | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().d('Loaded cached watching calendar with ${_watchingCalendarWeekdayById.length} items'); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().e('Failed to load cached calendar', error: e); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /// 缓存时间表数据到本地 | ||||||||||||||||||||||||||||||||||||||||||
| Future<void> _saveCachedCalendar() async { | ||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||
| await setting.put( | ||||||||||||||||||||||||||||||||||||||||||
| SettingBoxKey.cachedWatchingCalendar, | ||||||||||||||||||||||||||||||||||||||||||
| Map<int, int>.from(_watchingCalendarWeekdayById), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().d('Saved watching calendar cache with ${_watchingCalendarWeekdayById.length} items'); | ||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().e('Failed to save calendar cache', error: e); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| @action | ||||||||||||||||||||||||||||||||||||||||||
| Future<void> loadWatchingCalendar() async { | ||||||||||||||||||||||||||||||||||||||||||
| if (isWatchingCalendarLoading) { | ||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| isWatchingCalendarLoading = true; | ||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||
| final calendar = await BangumiHTTP.getCalendar(); | ||||||||||||||||||||||||||||||||||||||||||
| if (calendar.isEmpty) { | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().w('Resolve watching calendar failed: empty calendar'); | ||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| final map = <int, int>{}; | ||||||||||||||||||||||||||||||||||||||||||
| for (int weekdayIndex = 0; | ||||||||||||||||||||||||||||||||||||||||||
| weekdayIndex < calendar.length && weekdayIndex < 7; | ||||||||||||||||||||||||||||||||||||||||||
| weekdayIndex++) { | ||||||||||||||||||||||||||||||||||||||||||
| for (final item in calendar[weekdayIndex]) { | ||||||||||||||||||||||||||||||||||||||||||
| map[item.id] = weekdayIndex; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if (map.isEmpty) { | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().w('Resolve watching calendar failed: empty map'); | ||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| _watchingCalendarWeekdayById = ObservableMap<int, int>.of(map); | ||||||||||||||||||||||||||||||||||||||||||
| isWatchingCalendarReady = true; | ||||||||||||||||||||||||||||||||||||||||||
| // 加载成功后缓存到本地 | ||||||||||||||||||||||||||||||||||||||||||
| await _saveCachedCalendar(); | ||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||
| KazumiLogger().e('Resolve watching calendar failed', error: e); | ||||||||||||||||||||||||||||||||||||||||||
| // 失败时不阻塞 UI:继续使用 airWeekday 的降级分组 | ||||||||||||||||||||||||||||||||||||||||||
| isWatchingCalendarReady = false; | ||||||||||||||||||||||||||||||||||||||||||
| _watchingCalendarWeekdayById = ObservableMap<int, int>(); | ||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||
| isWatchingCalendarLoading = false; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /// 确保时间表已加载(用于刷新缓存) | ||||||||||||||||||||||||||||||||||||||||||
| Future<void> ensureWatchingCalendarLoaded() async { | ||||||||||||||||||||||||||||||||||||||||||
| if (isWatchingCalendarLoading) { | ||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if (isWatchingCalendarReady && _watchingCalendarWeekdayById.isNotEmpty) { | ||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| await loadWatchingCalendar(); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+120
to
+129
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| int getCollectType(BangumiItem bangumiItem) { | ||||||||||||||||||||||||||||||||||||||||||
| return _collectCrudRepository.getCollectType(bangumiItem.id); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -130,4 +226,54 @@ abstract class _CollectController with Store { | |||||||||||||||||||||||||||||||||||||||||
| .where((item) => !excludeIds.contains(item.id)) | ||||||||||||||||||||||||||||||||||||||||||
| .toList(); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /// 将"在看"番剧按周数分组 | ||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||
| /// 返回 Map<int, List<CollectedBangumi>> | ||||||||||||||||||||||||||||||||||||||||||
| /// key: 0-6 代表周一到周日, 7 代表老番(不在时间表中) | ||||||||||||||||||||||||||||||||||||||||||
| Map<int, List<CollectedBangumi>> getWatchingBangumiByWeekday() { | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+230
to
+234
|
||||||||||||||||||||||||||||||||||||||||||
| // 初始化 8 个分组 (周一到周日 + 老番) | ||||||||||||||||||||||||||||||||||||||||||
| Map<int, List<CollectedBangumi>> weekdayGroups = { | ||||||||||||||||||||||||||||||||||||||||||
| 0: [], // 周一 | ||||||||||||||||||||||||||||||||||||||||||
| 1: [], // 周二 | ||||||||||||||||||||||||||||||||||||||||||
| 2: [], // 周三 | ||||||||||||||||||||||||||||||||||||||||||
| 3: [], // 周四 | ||||||||||||||||||||||||||||||||||||||||||
| 4: [], // 周五 | ||||||||||||||||||||||||||||||||||||||||||
| 5: [], // 周六 | ||||||||||||||||||||||||||||||||||||||||||
| 6: [], // 周日 | ||||||||||||||||||||||||||||||||||||||||||
| 7: [], // 老番 | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // 过滤出"在看"类型的番剧 | ||||||||||||||||||||||||||||||||||||||||||
| final watchingList = collectibles.where((item) => item.type == 1).toList(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+247
to
+249
|
||||||||||||||||||||||||||||||||||||||||||
| // 按周数分组:优先使用时间表匹配;不在时间表的统一归为老番 | ||||||||||||||||||||||||||||||||||||||||||
| for (var collected in watchingList) { | ||||||||||||||||||||||||||||||||||||||||||
| final id = collected.bangumiItem.id; | ||||||||||||||||||||||||||||||||||||||||||
| final calendarWeekdayIndex = _watchingCalendarWeekdayById[id]; | ||||||||||||||||||||||||||||||||||||||||||
| if (calendarWeekdayIndex != null && calendarWeekdayIndex >= 0 && calendarWeekdayIndex <= 6) { | ||||||||||||||||||||||||||||||||||||||||||
| weekdayGroups[calendarWeekdayIndex]!.add(collected); | ||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
| // 降级:时间表未就绪时,先按 airWeekday 分组;否则视为老番 | ||||||||||||||||||||||||||||||||||||||||||
| if (!isWatchingCalendarReady && _watchingCalendarWeekdayById.isEmpty) { | ||||||||||||||||||||||||||||||||||||||||||
| final weekday = collected.bangumiItem.airWeekday; | ||||||||||||||||||||||||||||||||||||||||||
| if (weekday >= 1 && weekday <= 7) { | ||||||||||||||||||||||||||||||||||||||||||
| weekdayGroups[weekday - 1]!.add(collected); | ||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
| weekdayGroups[7]!.add(collected); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+255
to
+265
|
||||||||||||||||||||||||||||||||||||||||||
| weekdayGroups[calendarWeekdayIndex]!.add(collected); | |
| } else { | |
| // 降级:时间表未就绪时,先按 airWeekday 分组;否则视为老番 | |
| if (!isWatchingCalendarReady && _watchingCalendarWeekdayById.isEmpty) { | |
| final weekday = collected.bangumiItem.airWeekday; | |
| if (weekday >= 1 && weekday <= 7) { | |
| weekdayGroups[weekday - 1]!.add(collected); | |
| } else { | |
| weekdayGroups[7]!.add(collected); | |
| } | |
| } else { | |
| // 首选:使用时间表中的星期分组 | |
| weekdayGroups[calendarWeekdayIndex]!.add(collected); | |
| } else { | |
| // 降级:当某个在看条目不在日历映射中时,尝试使用 airWeekday 分组(无效再视为老番) | |
| final weekday = collected.bangumiItem.airWeekday; | |
| if (weekday >= 1 && weekday <= 7) { | |
| weekdayGroups[weekday - 1]!.add(collected); | |
| } else { | |
| // airWeekday 无效时才视为老番 |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getWatchingBangumiByWeekday() 每次调用都会对 8 个分组执行 sort。该方法在页面 build 期间会被调用,重复排序会带来不必要的开销。建议把分组结果做成 @computed/缓存(当 collectibles 或时间表映射变化时再重算),或至少只对非空分组排序。
| // 对每个分组按时间排序 | |
| for (var group in weekdayGroups.values) { | |
| group.sort((a, b) => b.time.millisecondsSinceEpoch | |
| .compareTo(a.time.millisecondsSinceEpoch)); | |
| // 对每个分组按时间排序(仅对非空分组执行排序) | |
| for (var group in weekdayGroups.values) { | |
| if (group.isNotEmpty) { | |
| group.sort((a, b) => b.time.millisecondsSinceEpoch | |
| .compareTo(a.time.millisecondsSinceEpoch)); | |
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
loadWatchingCalendar()is introduced but not called anywhere in the codebase (no references outside this controller). As a result,cachedWatchingCalendarwill never be populated/updated and the “在看” weekday grouping will only use theairWeekdayfallback. Consider triggering this refresh fromCollectPage.initState()(or when entering the “在看” tab) so the calendar mapping and cache are actually used.