diff --git a/frontend/mining-app/lib/presentation/pages/asset/receive_shares_page.dart b/frontend/mining-app/lib/presentation/pages/asset/receive_shares_page.dart index 23678415..5eabab89 100644 --- a/frontend/mining-app/lib/presentation/pages/asset/receive_shares_page.dart +++ b/frontend/mining-app/lib/presentation/pages/asset/receive_shares_page.dart @@ -5,6 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:qr_flutter/qr_flutter.dart'; import '../../../core/router/routes.dart'; import '../../providers/user_providers.dart'; +import '../../../data/models/capability_model.dart'; class ReceiveSharesPage extends ConsumerWidget { const ReceiveSharesPage({super.key}); @@ -20,6 +21,8 @@ class ReceiveSharesPage extends ConsumerWidget { final user = ref.watch(userNotifierProvider); final phone = user.phone ?? ''; final nickname = user.nickname ?? user.realName ?? '股行用户'; + final capabilities = ref.watch(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + final p2pReceiveEnabled = capabilities.p2pReceiveEnabled; return Scaffold( backgroundColor: _bgGray, @@ -57,6 +60,27 @@ class ReceiveSharesPage extends ConsumerWidget { body: SingleChildScrollView( child: Column( children: [ + if (!p2pReceiveEnabled) + Container( + margin: const EdgeInsets.fromLTRB(16, 16, 16, 0), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xFFEF4444).withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: const Row( + children: [ + Icon(Icons.block, color: Color(0xFFEF4444), size: 20), + SizedBox(width: 8), + Expanded( + child: Text( + '您的P2P收款功能已被限制,当前无法接收转账', + style: TextStyle(fontSize: 13, color: Color(0xFFEF4444)), + ), + ), + ], + ), + ), const SizedBox(height: 32), // 二维码卡片 diff --git a/frontend/mining-app/lib/presentation/pages/asset/send_shares_page.dart b/frontend/mining-app/lib/presentation/pages/asset/send_shares_page.dart index 518329f0..d453a7eb 100644 --- a/frontend/mining-app/lib/presentation/pages/asset/send_shares_page.dart +++ b/frontend/mining-app/lib/presentation/pages/asset/send_shares_page.dart @@ -8,6 +8,7 @@ import '../../providers/user_providers.dart'; import '../../providers/asset_providers.dart'; import '../../providers/transfer_providers.dart'; import '../../widgets/qr_scanner_sheet.dart'; +import '../../../data/models/capability_model.dart'; class SendSharesPage extends ConsumerStatefulWidget { const SendSharesPage({super.key}); @@ -482,7 +483,10 @@ class _SendSharesPageState extends ConsumerState { final amount = double.tryParse(_amountController.text) ?? 0; final available = double.tryParse(availableCash) ?? 0; final totalRequired = amount + feeAmount; - final isValid = _isRecipientVerified && + final capabilities = ref.watch(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + final p2pSendEnabled = capabilities.p2pSendEnabled; + final isValid = p2pSendEnabled && + _isRecipientVerified && amount >= minTransferAmount && totalRequired <= available; @@ -494,7 +498,11 @@ class _SendSharesPageState extends ConsumerState { child: ElevatedButton( onPressed: isValid && !transferState.isLoading ? () => _handleTransfer(feeAmount) - : null, + : !p2pSendEnabled + ? () => ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('您的P2P转出功能已被限制'), backgroundColor: _red), + ) + : null, style: ElevatedButton.styleFrom( backgroundColor: _orange, foregroundColor: Colors.white, diff --git a/frontend/mining-app/lib/presentation/pages/c2c/c2c_market_page.dart b/frontend/mining-app/lib/presentation/pages/c2c/c2c_market_page.dart index 45284853..379bd524 100644 --- a/frontend/mining-app/lib/presentation/pages/c2c/c2c_market_page.dart +++ b/frontend/mining-app/lib/presentation/pages/c2c/c2c_market_page.dart @@ -8,6 +8,7 @@ import '../../../data/models/c2c_order_model.dart'; import '../../providers/c2c_providers.dart'; import '../../providers/user_providers.dart'; import '../../providers/asset_providers.dart'; +import '../../../data/models/capability_model.dart'; class C2cMarketPage extends ConsumerStatefulWidget { const C2cMarketPage({super.key}); @@ -73,7 +74,16 @@ class _C2cMarketPageState extends ConsumerState actions: [ IconButton( icon: const Icon(Icons.add_circle_outline, color: _orange), - onPressed: () => context.push(Routes.c2cPublish), + onPressed: () { + final caps = ref.read(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + if (!caps.c2cEnabled) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('您的C2C交易功能已被限制'), backgroundColor: _red), + ); + return; + } + context.push(Routes.c2cPublish); + }, ), ], bottom: TabBar( @@ -614,6 +624,13 @@ class _C2cMarketPageState extends ConsumerState // #13 + #15: 接单对话框(支持部分成交数量输入 + BUY单收款信息输入) void _showTakeOrderDialog(C2cOrderModel order, bool isBuyAction) { + final caps = ref.read(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + if (!caps.c2cEnabled) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('您的C2C交易功能已被限制'), backgroundColor: _red), + ); + return; + } final quantityController = TextEditingController(text: order.quantity); final paymentAccountController = TextEditingController(); final paymentRealNameController = TextEditingController(); diff --git a/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart b/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart index 4753af7f..deeff72d 100644 --- a/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart +++ b/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart @@ -7,6 +7,7 @@ import '../../providers/c2c_providers.dart'; import '../../providers/user_providers.dart'; import '../../providers/asset_providers.dart'; import '../../providers/trading_providers.dart'; +import '../../../data/models/capability_model.dart'; class C2cPublishPage extends ConsumerStatefulWidget { const C2cPublishPage({super.key}); @@ -708,9 +709,11 @@ class _C2cPublishPageState extends ConsumerState { Widget _buildPublishButton(C2cTradingState c2cState) { final quantity = double.tryParse(_quantityController.text) ?? 0; final isSell = _selectedType == 1; + final capabilities = ref.watch(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + final c2cEnabled = capabilities.c2cEnabled; // #11: 价格固定为1,数量最小为1 - bool isValid = quantity >= 1; + bool isValid = c2cEnabled && quantity >= 1; if (isSell) { // 如果选择了其他支付方式,还需要填写收款账号和姓名 if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) { @@ -726,7 +729,13 @@ class _C2cPublishPageState extends ConsumerState { width: double.infinity, height: 50, child: ElevatedButton( - onPressed: isValid && !c2cState.isLoading ? _handlePublish : null, + onPressed: isValid && !c2cState.isLoading + ? _handlePublish + : !c2cEnabled + ? () => ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('您的C2C交易功能已被限制'), backgroundColor: _red), + ) + : null, style: ElevatedButton.styleFrom( backgroundColor: _selectedType == 0 ? _green : _red, foregroundColor: Colors.white, diff --git a/frontend/mining-app/lib/presentation/pages/profile/edit_profile_page.dart b/frontend/mining-app/lib/presentation/pages/profile/edit_profile_page.dart index 374f5e48..a110a912 100644 --- a/frontend/mining-app/lib/presentation/pages/profile/edit_profile_page.dart +++ b/frontend/mining-app/lib/presentation/pages/profile/edit_profile_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../providers/user_providers.dart'; +import '../../../data/models/capability_model.dart'; class EditProfilePage extends ConsumerStatefulWidget { const EditProfilePage({super.key}); @@ -336,6 +337,17 @@ class _EditProfilePageState extends ConsumerState { } Future _saveProfile() async { + final capabilities = ref.read(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + if (!capabilities.profileEditEnabled) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('您的编辑资料功能已被限制'), + backgroundColor: Color(0xFFEF4444), + ), + ); + return; + } + setState(() { _isLoading = true; }); diff --git a/frontend/mining-app/lib/presentation/pages/profile/team_page.dart b/frontend/mining-app/lib/presentation/pages/profile/team_page.dart index 1c3556b2..1ecddb55 100644 --- a/frontend/mining-app/lib/presentation/pages/profile/team_page.dart +++ b/frontend/mining-app/lib/presentation/pages/profile/team_page.dart @@ -5,6 +5,7 @@ import '../../../data/datasources/remote/referral_remote_datasource.dart'; import '../../widgets/team_tree_widget.dart'; import '../../providers/user_providers.dart'; import '../../providers/profile_providers.dart'; +import '../../../data/models/capability_model.dart'; class TeamPage extends ConsumerStatefulWidget { const TeamPage({super.key}); @@ -31,6 +32,15 @@ class _TeamPageState extends ConsumerState { } Future _loadRootNode() async { + final capabilities = ref.read(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + if (!capabilities.viewTeamEnabled) { + setState(() { + _isLoading = false; + _error = '您的查看团队功能已被限制'; + }); + return; + } + final user = ref.read(userNotifierProvider); final stats = ref.read(userStatsProvider).valueOrNull; diff --git a/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart b/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart index 8020b760..29e88f57 100644 --- a/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart +++ b/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart @@ -17,6 +17,7 @@ import '../../providers/asset_providers.dart'; import '../../widgets/shimmer_loading.dart'; import '../../widgets/kline_chart/kline_chart_widget.dart'; import '../../widgets/trade_password_dialog.dart'; +import '../../../data/models/capability_model.dart'; class TradingPage extends ConsumerStatefulWidget { const TradingPage({super.key}); @@ -805,15 +806,23 @@ class _TradingPageState extends ConsumerState { ), ), const SizedBox(height: 24), - // 提交按钮(卖出时校验积分股余额) + // 提交按钮(卖出时校验积分股余额 + 能力检查) Builder(builder: (context) { final sellError = _selectedTab == 1 ? _getSellValidationError(tradingShareBalance) : null; - final isDisabled = sellError != null; + final capabilities = ref.watch(capabilitiesProvider).valueOrNull ?? CapabilityMap.defaultAll(); + final tradingEnabled = capabilities.tradingEnabled; + final isDisabled = sellError != null || !tradingEnabled; return SizedBox( width: double.infinity, height: 48, child: ElevatedButton( - onPressed: isDisabled ? null : _handleTrade, + onPressed: isDisabled + ? !tradingEnabled + ? () => ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('您的交易功能已被限制'), backgroundColor: AppColors.down), + ) + : null + : _handleTrade, style: ElevatedButton.styleFrom( backgroundColor: isDisabled ? Colors.grey : _orange, shape: RoundedRectangleBorder(