rwadurian/frontend/mining-app/lib/presentation/providers/trading_providers.dart

229 lines
5.9 KiB
Dart

import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../domain/entities/price_info.dart';
import '../../domain/entities/market_overview.dart';
import '../../domain/entities/trading_account.dart';
import '../../domain/entities/trade_order.dart';
import '../../domain/repositories/trading_repository.dart';
import '../../data/models/trade_order_model.dart';
import '../../core/di/injection.dart';
// Repository Provider
final tradingRepositoryProvider = Provider<TradingRepository>((ref) {
return getIt<TradingRepository>();
});
// K线周期选择
final selectedKlinePeriodProvider = StateProvider<String>((ref) => '1h');
// 当前价格 Provider (5分钟缓存)
final currentPriceProvider = FutureProvider<PriceInfo?>((ref) async {
final repository = ref.watch(tradingRepositoryProvider);
final result = await repository.getCurrentPrice();
ref.keepAlive();
final timer = Timer(const Duration(minutes: 5), () {
ref.invalidateSelf();
});
ref.onDispose(() => timer.cancel());
return result.fold(
(failure) => throw Exception(failure.message),
(priceInfo) => priceInfo,
);
});
// 市场概览 Provider (5分钟缓存)
final marketOverviewProvider = FutureProvider<MarketOverview?>((ref) async {
final repository = ref.watch(tradingRepositoryProvider);
final result = await repository.getMarketOverview();
ref.keepAlive();
final timer = Timer(const Duration(minutes: 5), () {
ref.invalidateSelf();
});
ref.onDispose(() => timer.cancel());
return result.fold(
(failure) => throw Exception(failure.message),
(overview) => overview,
);
});
// 交易账户 Provider (带参数)
final tradingAccountProvider = FutureProvider.family<TradingAccount?, String>(
(ref, accountSequence) async {
if (accountSequence.isEmpty) return null;
final repository = ref.watch(tradingRepositoryProvider);
final result = await repository.getTradingAccount(accountSequence);
ref.keepAlive();
final timer = Timer(const Duration(minutes: 2), () {
ref.invalidateSelf();
});
ref.onDispose(() => timer.cancel());
return result.fold(
(failure) => throw Exception(failure.message),
(account) => account,
);
},
);
// 订单列表 Provider
final ordersProvider = FutureProvider<OrdersPageModel?>((ref) async {
final repository = ref.watch(tradingRepositoryProvider);
final result = await repository.getOrders(page: 1, pageSize: 10);
ref.keepAlive();
final timer = Timer(const Duration(minutes: 2), () {
ref.invalidateSelf();
});
ref.onDispose(() => timer.cancel());
return result.fold(
(failure) => throw Exception(failure.message),
(orders) => orders,
);
});
// 交易状态
class TradingState {
final bool isLoading;
final String? error;
final Map<String, dynamic>? lastOrderResult;
TradingState({
this.isLoading = false,
this.error,
this.lastOrderResult,
});
TradingState copyWith({
bool? isLoading,
String? error,
Map<String, dynamic>? lastOrderResult,
}) {
return TradingState(
isLoading: isLoading ?? this.isLoading,
error: error,
lastOrderResult: lastOrderResult ?? this.lastOrderResult,
);
}
}
class TradingNotifier extends StateNotifier<TradingState> {
final TradingRepository repository;
TradingNotifier({required this.repository}) : super(TradingState());
/// 创建买入订单
Future<bool> buyShares(String price, String quantity) async {
state = state.copyWith(isLoading: true, error: null);
final result = await repository.createOrder(
type: 'BUY',
price: price,
quantity: quantity,
);
return result.fold(
(failure) {
state = state.copyWith(isLoading: false, error: failure.message);
return false;
},
(orderResult) {
state = state.copyWith(isLoading: false, lastOrderResult: orderResult);
return true;
},
);
}
/// 创建卖出订单
Future<bool> sellShares(String price, String quantity) async {
state = state.copyWith(isLoading: true, error: null);
final result = await repository.createOrder(
type: 'SELL',
price: price,
quantity: quantity,
);
return result.fold(
(failure) {
state = state.copyWith(isLoading: false, error: failure.message);
return false;
},
(orderResult) {
state = state.copyWith(isLoading: false, lastOrderResult: orderResult);
return true;
},
);
}
/// 取消订单
Future<bool> cancelOrder(String orderNo) async {
state = state.copyWith(isLoading: true, error: null);
final result = await repository.cancelOrder(orderNo);
return result.fold(
(failure) {
state = state.copyWith(isLoading: false, error: failure.message);
return false;
},
(_) {
state = state.copyWith(isLoading: false);
return true;
},
);
}
/// 划入积分股
Future<bool> transferIn(String amount) async {
state = state.copyWith(isLoading: true, error: null);
final result = await repository.transferIn(amount);
return result.fold(
(failure) {
state = state.copyWith(isLoading: false, error: failure.message);
return false;
},
(_) {
state = state.copyWith(isLoading: false);
return true;
},
);
}
/// 划出积分股
Future<bool> transferOut(String amount) async {
state = state.copyWith(isLoading: true, error: null);
final result = await repository.transferOut(amount);
return result.fold(
(failure) {
state = state.copyWith(isLoading: false, error: failure.message);
return false;
},
(_) {
state = state.copyWith(isLoading: false);
return true;
},
);
}
void clearError() {
state = state.copyWith(error: null);
}
}
final tradingNotifierProvider = StateNotifierProvider<TradingNotifier, TradingState>(
(ref) => TradingNotifier(
repository: ref.watch(tradingRepositoryProvider),
),
);