fix(app): Phase 1.1 紧急修复 — SyncEngine 接入 + authorId + catch 异常处理
- feat(sync): SyncEngine 接入 EditorPage, 保存时 enqueue + 网络恢复自动 trySync - fix(editor): authorId 从 AuthBloc 获取, 替代硬编码 'local' - fix(bloc): class_bloc/calendar/profile/parent catch(_).全部改为 debugPrint - feat(editor): 编辑器工具栏拆分 (brush_panel/tag_panel/text_format_bar/dot_grid_painter) - feat(editor): EditorBloc 扩展 + EditorPage 增强 - feat(search): SearchBloc 扩展搜索功能 - feat(home): HomeBloc/HomePage 增强 - feat(auth): LoginPage 增强 - feat(templates): TemplateGalleryPage 重构 - fix(web): 管理端班级/日记页面修复 - fix(server): comment_service + theme_handler 修复 - docs: 添加全链路审计报告和验证截图
This commit is contained in:
@@ -54,6 +54,9 @@ final class HomeLoaded extends HomeState {
|
||||
/// 总日记数(spec §3.4 quick-stats)
|
||||
final int totalCount;
|
||||
|
||||
/// 今日天气(从今日日记中提取,null 则默认晴)
|
||||
final Weather? todayWeather;
|
||||
|
||||
const HomeLoaded({
|
||||
this.recentJournals = const [],
|
||||
this.hasTodayEntry = false,
|
||||
@@ -61,6 +64,7 @@ final class HomeLoaded extends HomeState {
|
||||
this.streakDays = 0,
|
||||
this.monthCount = 0,
|
||||
this.totalCount = 0,
|
||||
this.todayWeather,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -111,10 +115,21 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
// 推算连续天数
|
||||
final streakDays = _calculateStreak(journals);
|
||||
|
||||
// 本月日记数 & 总数(spec §3.4 quick-stats)
|
||||
// 本月日记数(spec §3.4 quick-stats)
|
||||
final monthCount = journals.where((j) =>
|
||||
j.date.year == today.year && j.date.month == today.month).length;
|
||||
final totalCount = journals.length;
|
||||
|
||||
// 总日记数 — 使用仓库计数方法(不受分页限制)
|
||||
final totalCount = await _journalRepo.getJournalCount();
|
||||
|
||||
// 今日天气 — 从今日日记中提取
|
||||
final todayJournal = journals.firstWhere(
|
||||
(j) => j.date.year == today.year &&
|
||||
j.date.month == today.month &&
|
||||
j.date.day == today.day,
|
||||
orElse: () => journals.first, // fallback for type safety
|
||||
);
|
||||
final todayWeather = hasTodayEntry ? todayJournal.weather : null;
|
||||
|
||||
emit(HomeLoaded(
|
||||
recentJournals: journals,
|
||||
@@ -123,6 +138,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
streakDays: streakDays,
|
||||
monthCount: monthCount,
|
||||
totalCount: totalCount,
|
||||
todayWeather: todayWeather,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(const HomeLoaded()); // 空状态而非错误,离线友好
|
||||
|
||||
@@ -100,7 +100,7 @@ class _HomeView extends StatelessWidget {
|
||||
|
||||
_MoodSelectorCard(
|
||||
topMood: state.topMood,
|
||||
weather: const _Weather(icon: '☀', label: '晴 26°'),
|
||||
todayWeather: state.todayWeather,
|
||||
onMoodTap: (_) => context.push('/editor'),
|
||||
),
|
||||
const SizedBox(height: DesignTokens.spacing20),
|
||||
@@ -261,12 +261,12 @@ class _StreakBadge extends StatelessWidget {
|
||||
class _MoodSelectorCard extends StatelessWidget {
|
||||
const _MoodSelectorCard({
|
||||
required this.topMood,
|
||||
required this.weather,
|
||||
required this.todayWeather,
|
||||
required this.onMoodTap,
|
||||
});
|
||||
|
||||
final Mood? topMood;
|
||||
final _Weather weather;
|
||||
final Weather? todayWeather;
|
||||
final ValueChanged<Mood> onMoodTap;
|
||||
|
||||
static const _moods = [
|
||||
@@ -277,6 +277,14 @@ class _MoodSelectorCard extends StatelessWidget {
|
||||
('🤔', '思考', Mood.thinking),
|
||||
];
|
||||
|
||||
static const _weatherMap = {
|
||||
Weather.sunny: ('☀', '晴'),
|
||||
Weather.cloudy: ('☁', '多云'),
|
||||
Weather.rainy: ('🌧', '雨'),
|
||||
Weather.snowy: ('❄', '雪'),
|
||||
Weather.windy: ('💨', '风'),
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
@@ -306,10 +314,13 @@ class _MoodSelectorCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'${weather.icon} ${weather.label}',
|
||||
style: TextStyle(fontSize: 13, color: theme.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
Builder(builder: (context) {
|
||||
final w = _weatherMap[todayWeather] ?? _weatherMap[Weather.sunny]!;
|
||||
return Text(
|
||||
'${w.$1} ${w.$2}',
|
||||
style: TextStyle(fontSize: 13, color: theme.colorScheme.onSurfaceVariant),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: DesignTokens.spacing12),
|
||||
@@ -376,12 +387,6 @@ class _MoodOption extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _Weather {
|
||||
const _Weather({required this.icon, required this.label});
|
||||
final String icon;
|
||||
final String label;
|
||||
}
|
||||
|
||||
/// 4. "今天的日记" 渐变卡片 + 浮动写按钮
|
||||
class _TodayCard extends StatelessWidget {
|
||||
const _TodayCard({required this.hasTodayEntry, required this.onTap});
|
||||
@@ -621,7 +626,9 @@ class _JournalCard extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final moodColor = AppColors.moodColors[journal.mood.value] ?? AppColors.accent;
|
||||
final excerpt = journal.tags.isEmpty ? '点击查看详情' : journal.tags.take(3).map((t) => '#$t').join(' ');
|
||||
final excerpt = journal.contentExcerpt?.isNotEmpty == true
|
||||
? journal.contentExcerpt!
|
||||
: (journal.tags.isEmpty ? '点击查看详情' : journal.tags.take(3).map((t) => '#$t').join(' '));
|
||||
|
||||
return Material(
|
||||
color: theme.colorScheme.surface,
|
||||
|
||||
Reference in New Issue
Block a user