95 lines
2.7 KiB
Dart
95 lines
2.7 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../core/network/api_exception.dart';
|
|
import '../models/membership_models.dart';
|
|
import '../services/membership_service.dart';
|
|
import '../services/user_service.dart';
|
|
import 'auth_provider.dart';
|
|
|
|
/// 会员中心状态
|
|
class MemberState {
|
|
const MemberState({
|
|
this.plans = const [],
|
|
this.benefits = const [],
|
|
this.me,
|
|
this.isLoading = false,
|
|
this.loadFailed = false,
|
|
this.redeeming = false,
|
|
});
|
|
|
|
final List<MembershipPlan> plans;
|
|
final List<String> benefits;
|
|
final MyMemberState? me;
|
|
final bool isLoading;
|
|
final bool loadFailed;
|
|
final bool redeeming;
|
|
|
|
MemberState copyWith({
|
|
List<MembershipPlan>? plans,
|
|
List<String>? benefits,
|
|
MyMemberState? me,
|
|
bool? isLoading,
|
|
bool? loadFailed,
|
|
bool? redeeming,
|
|
}) =>
|
|
MemberState(
|
|
plans: plans ?? this.plans,
|
|
benefits: benefits ?? this.benefits,
|
|
me: me ?? this.me,
|
|
isLoading: isLoading ?? this.isLoading,
|
|
loadFailed: loadFailed ?? this.loadFailed,
|
|
redeeming: redeeming ?? this.redeeming,
|
|
);
|
|
}
|
|
|
|
/// 会员中心 Notifier:套餐列表 + 我的会员状态 + 积分开通
|
|
class MemberNotifier extends StateNotifier<MemberState> {
|
|
MemberNotifier(this._ref) : super(const MemberState()) {
|
|
load();
|
|
}
|
|
|
|
final Ref _ref;
|
|
|
|
Future<void> load() async {
|
|
state = state.copyWith(isLoading: true, loadFailed: false);
|
|
try {
|
|
final plans = await MembershipService.fetchPlans();
|
|
MyMemberState? me;
|
|
// 游客无会员状态接口权限,未登录时跳过
|
|
if (_ref.read(authProvider).isLoggedIn) {
|
|
me = await MembershipService.fetchMe();
|
|
}
|
|
state = state.copyWith(
|
|
plans: plans.plans,
|
|
benefits: plans.benefits,
|
|
me: me,
|
|
isLoading: false,
|
|
);
|
|
} catch (_) {
|
|
state = state.copyWith(isLoading: false, loadFailed: true);
|
|
}
|
|
}
|
|
|
|
/// 积分开通会员。
|
|
/// 成功返回结果文案;失败抛 [ApiException] 由 UI 提示(2001 积分不足 / 2004 终身卡重复开通)。
|
|
Future<RedeemResult> redeem(String planCode) async {
|
|
state = state.copyWith(redeeming: true);
|
|
try {
|
|
final result = await MembershipService.redeem(planCode);
|
|
// 刷新我的会员状态 + 全局用户信息(积分/会员标识已变化)
|
|
final me = await MembershipService.fetchMe();
|
|
final user = await UserService.fetchMe();
|
|
state = state.copyWith(me: me, redeeming: false);
|
|
await _ref.read(authProvider.notifier).onLoginSuccess(user);
|
|
return result;
|
|
} catch (_) {
|
|
state = state.copyWith(redeeming: false);
|
|
rethrow;
|
|
}
|
|
}
|
|
}
|
|
|
|
final memberProvider = StateNotifierProvider<MemberNotifier, MemberState>(
|
|
MemberNotifier.new,
|
|
);
|