| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- 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<void> 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<void> 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<void> 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<void>(
- 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<void> 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');
- }
- }
- }
|