107 lines
2.8 KiB
Dart
107 lines
2.8 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../services/wallet_service.dart';
|
|
|
|
/// 钱包状态:钱包信息 + 积分明细(biz_type 筛选 + 触底分页)
|
|
class WalletState {
|
|
const WalletState({
|
|
this.wallet,
|
|
this.records = const [],
|
|
this.recordsTotal = 0,
|
|
this.bizType,
|
|
this.isLoading = false,
|
|
this.loadFailed = false,
|
|
this.loadingMore = false,
|
|
});
|
|
|
|
final WalletInfo? wallet;
|
|
final List<PointsRecord> records;
|
|
final int recordsTotal;
|
|
|
|
/// null = 全部
|
|
final int? bizType;
|
|
final bool isLoading;
|
|
final bool loadFailed;
|
|
final bool loadingMore;
|
|
|
|
bool get hasMore => records.length < recordsTotal;
|
|
|
|
WalletState copyWith({
|
|
WalletInfo? wallet,
|
|
List<PointsRecord>? records,
|
|
int? recordsTotal,
|
|
int? Function()? bizType,
|
|
bool? isLoading,
|
|
bool? loadFailed,
|
|
bool? loadingMore,
|
|
}) =>
|
|
WalletState(
|
|
wallet: wallet ?? this.wallet,
|
|
records: records ?? this.records,
|
|
recordsTotal: recordsTotal ?? this.recordsTotal,
|
|
bizType: bizType != null ? bizType() : this.bizType,
|
|
isLoading: isLoading ?? this.isLoading,
|
|
loadFailed: loadFailed ?? this.loadFailed,
|
|
loadingMore: loadingMore ?? this.loadingMore,
|
|
);
|
|
}
|
|
|
|
class WalletNotifier extends StateNotifier<WalletState> {
|
|
WalletNotifier() : super(const WalletState()) {
|
|
load();
|
|
}
|
|
|
|
static const _pageSize = 20;
|
|
|
|
Future<void> load() async {
|
|
state = state.copyWith(isLoading: true, loadFailed: false);
|
|
try {
|
|
final wallet = await WalletService.fetchWallet();
|
|
final page = await WalletService.fetchPointsRecords(
|
|
page: 1,
|
|
pageSize: _pageSize,
|
|
bizType: state.bizType,
|
|
);
|
|
state = state.copyWith(
|
|
wallet: wallet,
|
|
records: page.items,
|
|
recordsTotal: page.total,
|
|
isLoading: false,
|
|
);
|
|
} catch (_) {
|
|
state = state.copyWith(isLoading: false, loadFailed: true);
|
|
}
|
|
}
|
|
|
|
/// 切换 biz_type 筛选并重载明细
|
|
Future<void> setBizType(int? bizType) async {
|
|
if (bizType == state.bizType) return;
|
|
state = state.copyWith(bizType: () => bizType);
|
|
await load();
|
|
}
|
|
|
|
/// 触底加载下一页
|
|
Future<void> loadMore() async {
|
|
if (state.loadingMore || !state.hasMore || state.isLoading) return;
|
|
state = state.copyWith(loadingMore: true);
|
|
try {
|
|
final page = await WalletService.fetchPointsRecords(
|
|
page: state.records.length ~/ _pageSize + 1,
|
|
pageSize: _pageSize,
|
|
bizType: state.bizType,
|
|
);
|
|
state = state.copyWith(
|
|
records: [...state.records, ...page.items],
|
|
recordsTotal: page.total,
|
|
loadingMore: false,
|
|
);
|
|
} catch (_) {
|
|
state = state.copyWith(loadingMore: false);
|
|
}
|
|
}
|
|
}
|
|
|
|
final walletProvider = StateNotifierProvider<WalletNotifier, WalletState>(
|
|
(_) => WalletNotifier(),
|
|
);
|