229 lines
5.9 KiB
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),
|
|
),
|
|
);
|