/// 时间: 2026-03-29 /// 功能: 填写投票凭证弹窗组件 /// 介绍: 提供投票功能的用户凭证填写功能 /// 最新变化: 支持动态主题色设置 import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../models/colors/app_colors.dart'; import '../../../services/get/theme_controller.dart'; import '../../../utils/http/vote_api.dart'; class LoginRegisterDialog extends StatefulWidget { final VoidCallback? onLoginSuccess; const LoginRegisterDialog({super.key, this.onLoginSuccess}); @override State createState() => _LoginRegisterDialogState(); } class _LoginRegisterDialogState extends State { final ThemeController _themeController = Get.find(); final _formKey = GlobalKey(); final _usernameController = TextEditingController(); bool _isLoading = false; @override void dispose() { _usernameController.dispose(); super.dispose(); } String? _validateUsername(String? value) { if (value == null || value.isEmpty) { return '请输入投票凭证'; } final phoneRegex = RegExp(r'^1[3456789]\d{9}$'); final emailRegex = RegExp( r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', ); final wechatRegex = RegExp(r'^[a-zA-Z0-9_-]{6,20}$'); if (!phoneRegex.hasMatch(value) && !emailRegex.hasMatch(value) && !wechatRegex.hasMatch(value)) { return '请输入正确的手机号、邮箱或微信号'; } return null; } Future _submit() async { if (!_formKey.currentState!.validate()) { return; } setState(() { _isLoading = true; }); try { final deviceType = await VoteApi.getDeviceType(); final username = _usernameController.text.trim(); const password = '123456'; try { await VoteApi.login(username: username, password: password); if (mounted) { Navigator.pop(context); widget.onLoginSuccess?.call(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('验证成功'), backgroundColor: AppColors.success, ), ); } } catch (loginError) { await VoteApi.register( username: username, password: password, userIdentifier: deviceType, ); await VoteApi.login(username: username, password: password); if (mounted) { Navigator.pop(context); widget.onLoginSuccess?.call(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('注册并验证成功'), backgroundColor: AppColors.success, ), ); } } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString().replaceAll('Exception: ', '')), backgroundColor: AppColors.error, ), ); } } finally { if (mounted) { setState(() { _isLoading = false; }); } } } @override Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; return Dialog( backgroundColor: AppColors.surface, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Container( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '填写 投票凭证', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: AppColors.primaryText, ), ), IconButton( icon: Icon(Icons.close, color: AppColors.tertiaryText), onPressed: () => Navigator.pop(context), ), ], ), Text( '微信号或手机号或邮箱作为投票凭证,\n任何人都可以填写,限时开放投票,\n投票凭证仅用于投票,不会泄露隐私.\n结束后删除会所有凭证,仅保留投票结果', style: TextStyle( fontSize: 14, color: AppColors.secondaryText, ), textAlign: TextAlign.center, ), const SizedBox(height: 2), Form( key: _formKey, child: Column( children: [ TextFormField( controller: _usernameController, style: TextStyle(color: AppColors.primaryText), decoration: InputDecoration( labelText: '点击填写', hintText: '手机号/邮箱/微信号', labelStyle: TextStyle(color: AppColors.secondaryText), hintStyle: TextStyle(color: AppColors.tertiaryText), border: OutlineInputBorder( borderSide: BorderSide(color: AppColors.divider), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: AppColors.divider), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: AppColors.primary), ), prefixIcon: Icon(Icons.person, color: AppColors.primary), ), validator: _validateUsername, ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _isLoading ? null : _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white, ), ), ) : const Text('验证', style: TextStyle(fontSize: 16)), ), ), ], ), ), ], ), ), ); }); } }