- 新增 DiscoverBloc (LoadData/Refresh) + DiscoverModels 4 个数据类 - DiscoverPage 改为 BlocBuilder 驱动: loading/loaded/error/empty 四态 - 替换全部硬编码占位数据为 API 实时数据 - 添加 RefreshIndicator 下拉刷新 - 离线异常时保留已有数据,友好错误提示
79 lines
2.3 KiB
Dart
79 lines
2.3 KiB
Dart
// 发现页 BLoC — 管理发现页数据加载状态
|
||
//
|
||
// 职责:调用 /diary/discover API,解析响应,管理加载/成功/失败状态。
|
||
|
||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||
|
||
import '../../../data/remote/api_client.dart';
|
||
import '../models/discover_models.dart';
|
||
|
||
part 'discover_event.dart';
|
||
part 'discover_state.dart';
|
||
|
||
class DiscoverBloc extends Bloc<DiscoverEvent, DiscoverState> {
|
||
final ApiClient _api;
|
||
|
||
DiscoverBloc({required ApiClient api})
|
||
: _api = api,
|
||
super(const DiscoverInitial()) {
|
||
on<DiscoverLoadData>(_onLoadData);
|
||
on<DiscoverRefresh>(_onRefresh);
|
||
}
|
||
|
||
/// 首次加载 — 显示 loading 状态
|
||
Future<void> _onLoadData(
|
||
DiscoverLoadData event,
|
||
Emitter<DiscoverState> emit,
|
||
) async {
|
||
emit(const DiscoverLoading());
|
||
await _fetchData(emit);
|
||
}
|
||
|
||
/// 刷新 — 不显示 loading,静默更新
|
||
Future<void> _onRefresh(
|
||
DiscoverRefresh event,
|
||
Emitter<DiscoverState> emit,
|
||
) async {
|
||
await _fetchData(emit);
|
||
}
|
||
|
||
/// 通用数据获取逻辑
|
||
Future<void> _fetchData(Emitter<DiscoverState> emit) async {
|
||
try {
|
||
final response = await _api.get('/diary/discover');
|
||
final body = response.data as Map<String, dynamic>;
|
||
|
||
// 后端信封格式: { success, data: { ... }, message }
|
||
final dataJson = body['data'] as Map<String, dynamic>? ?? {};
|
||
final discoverData = DiscoverData.fromJson(dataJson);
|
||
|
||
emit(DiscoverLoaded(discoverData));
|
||
} on OfflineException {
|
||
// 离线时,如果有已加载的数据,保留它
|
||
if (state is DiscoverLoaded) return;
|
||
emit(const DiscoverError('网络不可用,请检查网络连接'));
|
||
} catch (e) {
|
||
if (state is DiscoverLoaded) return;
|
||
emit(DiscoverError('加载失败:${_friendlyError(e)}'));
|
||
}
|
||
}
|
||
|
||
/// 将异常转换为用户友好的错误消息
|
||
String _friendlyError(Object error) {
|
||
final msg = error.toString();
|
||
if (msg.contains('SocketException') || msg.contains('Connection refused')) {
|
||
return '无法连接服务器';
|
||
}
|
||
if (msg.contains('401')) {
|
||
return '登录已过期,请重新登录';
|
||
}
|
||
if (msg.contains('403')) {
|
||
return '没有访问权限';
|
||
}
|
||
if (msg.contains('500')) {
|
||
return '服务器错误,请稍后重试';
|
||
}
|
||
return '请稍后重试';
|
||
}
|
||
}
|