Files
nj/app/lib/features/templates/bloc/template_bloc.dart
iven e57c3427a4 fix(app): 18 处 catch(e) 添加 debugPrint 异常日志
- parent_bloc: 6 处 (LoadChildren/BindChild/ViewJournals/ExportData/DeleteData/UnbindChild)
- search_bloc: 3 处 (SearchByMood/SearchByTag/SearchByKeyword)
- achievement_bloc: 1 处 (_fetchAchievements)
- sticker_bloc: 2 处 (_fetchPacks/fetchStickersInPack)
- template_bloc: 1 处 (_fetchTemplates)
- mood_bloc: 1 处 (_loadStats)
- home_bloc: 1 处 (_onLoadData)
- calendar_bloc: 1 处 (_onMonthChanged)
- sync_engine: 1 处 (trySync)
- weekly_page: 已有 debugPrint,无需修改
2026-06-02 23:21:16 +08:00

138 lines
3.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 模板 BLoC — 通过 API 加载模板列表
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:nuanji_app/data/remote/api_client.dart';
// ===== 模型 =====
/// 日记模板
class Template {
final String id;
final String name;
final String? description;
final String? previewUrl;
final Map<String, dynamic>? templateData;
final String? category;
final bool isFree;
/// 用于 UI 显示的 emoji基于 category 推导)
String get emoji => switch (category) {
'日常' => '☀️',
'旅行' => '🗺️',
'校园' => '📚',
'节日' => '🎄',
'创意' => '',
_ => '📝',
};
const Template({
required this.id,
required this.name,
this.description,
this.previewUrl,
this.templateData,
this.category,
this.isFree = true,
});
}
// ===== State =====
/// 模板页面状态
class TemplateState {
final List<Template> templates;
final String selectedCategory;
final bool isLoading;
final String? errorMessage;
const TemplateState({
this.templates = const [],
this.selectedCategory = '全部',
this.isLoading = false,
this.errorMessage,
});
/// 按分类过滤模板
List<Template> get filteredTemplates => selectedCategory == '全部'
? templates
: templates.where((t) => t.category == selectedCategory).toList();
/// 所有分类(去重 + 加"全部"
List<String> get categories {
final cats = templates
.map((t) => t.category)
.whereType<String>()
.toSet()
.toList();
return ['全部', ...cats];
}
TemplateState copyWith({
List<Template>? templates,
String? selectedCategory,
bool? isLoading,
String? errorMessage,
}) =>
TemplateState(
templates: templates ?? this.templates,
selectedCategory: selectedCategory ?? this.selectedCategory,
isLoading: isLoading ?? this.isLoading,
errorMessage: errorMessage,
);
}
// ===== BLoC =====
/// 模板 BLoC — ChangeNotifier 模式
class TemplateBloc extends ChangeNotifier {
final ApiClient _api;
TemplateState _state = const TemplateState();
TemplateState get state => _state;
TemplateBloc({required ApiClient api}) : _api = api;
/// 加载模板列表
void load() {
_state = _state.copyWith(isLoading: true);
notifyListeners();
_fetchTemplates();
}
/// 选择分类
void selectCategory(String category) {
_state = _state.copyWith(selectedCategory: category);
notifyListeners();
}
Future<void> _fetchTemplates() async {
try {
final response = await _api.get('/diary/templates');
final body = response.data as Map<String, dynamic>;
final list = body['data'] as List? ?? [];
final templates = list.map((item) {
final m = item as Map<String, dynamic>;
return Template(
id: m['id'] as String,
name: m['name'] as String,
description: m['description'] as String?,
previewUrl: m['preview_url'] as String?,
templateData: m['template_data'] as Map<String, dynamic>?,
category: m['category'] as String?,
isFree: m['is_free'] as bool? ?? true,
);
}).toList();
_state = _state.copyWith(isLoading: false, templates: templates);
} catch (e) {
debugPrint('TemplateBloc._fetchTemplates 失败: $e');
_state = _state.copyWith(
isLoading: false,
errorMessage: '加载模板列表失败',
);
}
notifyListeners();
}
}