import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/constants/app_colors.dart'; import '../providers/user_providers.dart'; /// 支付密码验证弹窗 /// 返回 true 表示验证通过,false 或 null 表示取消或验证失败 class TradePasswordDialog extends ConsumerStatefulWidget { final String title; final String? subtitle; const TradePasswordDialog({ super.key, this.title = '请输入支付密码', this.subtitle, }); @override ConsumerState createState() => _TradePasswordDialogState(); /// 显示支付密码验证弹窗 /// 返回 true 表示验证通过,false 或 null 表示取消或验证失败 static Future show( BuildContext context, { String title = '请输入支付密码', String? subtitle, }) { return showDialog( context: context, barrierDismissible: false, builder: (context) => TradePasswordDialog( title: title, subtitle: subtitle, ), ); } } class _TradePasswordDialogState extends ConsumerState { final _passwordController = TextEditingController(); final _focusNode = FocusNode(); bool _obscurePassword = true; bool _isVerifying = false; String? _errorMessage; @override void initState() { super.initState(); // 自动聚焦密码输入框 WidgetsBinding.instance.addPostFrameCallback((_) { _focusNode.requestFocus(); }); } @override void dispose() { _passwordController.dispose(); _focusNode.dispose(); super.dispose(); } Future _verify() async { final password = _passwordController.text; if (password.isEmpty) { setState(() => _errorMessage = '请输入支付密码'); return; } if (password.length != 6) { setState(() => _errorMessage = '支付密码必须是6位数字'); return; } setState(() { _isVerifying = true; _errorMessage = null; }); try { final isValid = await ref.read(userNotifierProvider.notifier).verifyTradePassword(password); if (mounted) { if (isValid) { Navigator.of(context).pop(true); } else { setState(() { _isVerifying = false; _errorMessage = '支付密码错误'; _passwordController.clear(); }); } } } catch (e) { if (mounted) { setState(() { _isVerifying = false; _errorMessage = '验证失败,请重试'; }); } } } @override Widget build(BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), title: Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: AppColors.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20), ), child: Icon( Icons.lock_outline, color: AppColors.primary, size: 24, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.title, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), if (widget.subtitle != null) ...[ const SizedBox(height: 4), Text( widget.subtitle!, style: TextStyle( fontSize: 12, color: Colors.grey[600], fontWeight: FontWeight.normal, ), ), ], ], ), ), ], ), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: _passwordController, focusNode: _focusNode, obscureText: _obscurePassword, keyboardType: TextInputType.number, textAlign: TextAlign.center, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 8, ), inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(6), ], decoration: InputDecoration( hintText: '请输入6位数字', hintStyle: TextStyle( fontSize: 16, color: Colors.grey[400], letterSpacing: 0, ), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, color: Colors.grey[600], ), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: AppColors.primary, width: 2), ), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), ), onSubmitted: (_) => _verify(), ), if (_errorMessage != null) ...[ const SizedBox(height: 12), Row( children: [ Icon(Icons.error_outline, color: AppColors.error, size: 16), const SizedBox(width: 4), Text( _errorMessage!, style: TextStyle( color: AppColors.error, fontSize: 14, ), ), ], ), ], ], ), actions: [ TextButton( onPressed: _isVerifying ? null : () => Navigator.of(context).pop(false), child: const Text('取消'), ), ElevatedButton( onPressed: _isVerifying ? null : _verify, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: _isVerifying ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text( '确认', style: TextStyle(color: Colors.white), ), ), ], ); } }