import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../l10n/app_localizations.dart'; import '../theme/app_colors.dart'; import '../utils/dialog_utils.dart'; import '../utils/top_toast.dart'; import '../../data/repositories/broker_repository.dart'; import '../../providers/profile_provider.dart'; /// 等待用户资料加载完成 Future waitForProfileLoad(WidgetRef ref) async { if (!ref.read(profileProvider).isLoadingProfile) { return; } for (int i = 0; i < 30; i++) { await Future.delayed(const Duration(milliseconds: 100)); if (!ref.read(profileProvider).isLoadingProfile) { break; } } } /// 判断申请是否处于待审核 bool isBrokerApplyPending(dynamic status) { return status == 0 || status == '0' || status == 'AUDIT_ING'; } /// 经纪商入口:已是经纪商进主页,有待审申请进记录页,否则弹申请窗 Future openBrokerEntry(BuildContext context, WidgetRef ref) async { await waitForProfileLoad(ref); if (!context.mounted) { return; } if (ref.read(profileProvider).user.isBroker) { context.push('/broker'); return; } try { final list = await ref.read(brokerRepositoryProvider).getMyApplyList(); if (!context.mounted) { return; } final hasPending = list.any( (item) => isBrokerApplyPending(item['auditStatus']), ); if (hasPending) { context.push('/broker/apply'); return; } } catch (_) { // 列表拉取失败时仍允许用户发起申请 } if (!context.mounted) { return; } await showBrokerApplyDialog(context, ref); } /// 展示经纪商申请弹窗(对齐 Web 非经纪商提示) Future showBrokerApplyDialog( BuildContext context, WidgetRef ref, ) async { final l10n = AppLocalizations.of(context)!; final cs = Theme.of(context).colorScheme; // 保留页面 context,dialog 关闭后其内部 context 不在 GoRouter 子树中 final hostContext = context; await showDialog( context: context, barrierDismissible: false, builder: (dialogContext) { var submitting = false; return StatefulBuilder( builder: (dialogContext, setState) { return AlertDialog( backgroundColor: cs.surface, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('🏦', style: TextStyle(fontSize: 36)), const SizedBox(height: 12), Text( l10n.brokerApplyTitle, textAlign: TextAlign.center, style: TextStyle( color: cs.onSurface, fontSize: 18, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 12), Text( l10n.brokerApplyDesc, textAlign: TextAlign.center, style: TextStyle( color: cs.onSurface.withAlpha(180), fontSize: 14, height: 1.5, ), ), ], ), actions: [ Row( children: [ Expanded( child: OutlinedButton( onPressed: submitting ? null : () { Navigator.of(dialogContext).pop(); }, style: OutlinedButton.styleFrom( side: BorderSide(color: cs.outline.withAlpha(80)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.symmetric(vertical: 14), ), child: Text( l10n.cancel, style: TextStyle( color: cs.onSurface.withAlpha(180), fontSize: 15, ), ), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: submitting ? null : () async { setState(() { submitting = true; }); Navigator.of(dialogContext).pop(); await submitBrokerApply(hostContext, ref); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.brand, foregroundColor: Colors.black, disabledBackgroundColor: AppColors.brand.withAlpha(100), disabledForegroundColor: Colors.black.withAlpha(100), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.symmetric(vertical: 14), ), child: submitting ? SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.black.withAlpha(180), ), ) : Text( l10n.applyNow, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, ), ), ), ), ], ), ], ); }, ); }, ); } /// 提交经纪商申请并展示后端返回的 message Future submitBrokerApply(BuildContext context, WidgetRef ref) async { final l10n = AppLocalizations.of(context)!; try { final err = await ref.read(brokerRepositoryProvider).submitApply(); if (!context.mounted) { return; } if (err != null && err.isNotEmpty) { showTopToast(context, message: err); if (isAlreadyBrokerError(err)) { context.push('/broker'); } else if (isApplyPendingError(err)) { context.push('/broker/apply'); } return; } if (err != null && err.isEmpty) { showTopToast(context, message: l10n.operationFailed); return; } showTopToast( context, message: l10n.applySubmitted, backgroundColor: AppColors.rise, ); context.push('/broker/apply'); } catch (e) { if (!context.mounted) { return; } final message = extractErrorMessage(e); showTopToast( context, message: message.isNotEmpty ? message : l10n.operationFailed, ); if (isApplyPendingError(message)) { context.push('/broker/apply'); } } }