| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import 'package:flutter/material.dart';
- import 'package:go_router/go_router.dart';
- import '../../../core/l10n/app_localizations.dart';
- import '../../../core/theme/app_colors.dart';
- class TwoFactorScreen extends StatefulWidget {
- const TwoFactorScreen({super.key});
- @override
- State<TwoFactorScreen> createState() => _TwoFactorScreenState();
- }
- class _TwoFactorScreenState extends State<TwoFactorScreen> {
- final List<TextEditingController> _controllers =
- List.generate(6, (_) => TextEditingController());
- final List<FocusNode> _focusNodes = List.generate(6, (_) => FocusNode());
- @override
- void dispose() {
- for (final c in _controllers) { c.dispose(); }
- for (final f in _focusNodes) { f.dispose(); }
- super.dispose();
- }
- void _onDigitChanged(int index, String value) {
- if (value.isNotEmpty && index < 5) {
- _focusNodes[index + 1].requestFocus();
- }
- if (value.isEmpty && index > 0) {
- _focusNodes[index - 1].requestFocus();
- }
- setState(() {});
- }
- bool get _allFilled => _controllers.every((c) => c.text.isNotEmpty);
- @override
- Widget build(BuildContext context) {
- final cs = Theme.of(context).colorScheme;
- return Scaffold(
- appBar: AppBar(
- elevation: 0,
- leading: IconButton(
- icon: const Icon(Icons.chevron_left, size: 28),
- onPressed: () => context.pop(),
- ),
- title: Text(
- AppLocalizations.of(context)!.twoFactorVerification,
- style: const TextStyle(
- fontSize: 18,
- fontWeight: FontWeight.w600,
- ),
- ),
- centerTitle: true,
- ),
- body: Padding(
- padding: const EdgeInsets.fromLTRB(24, 32, 24, 32),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // ── 说明 ──────────────────────────────────────
- Text(
- AppLocalizations.of(context)!.googleCode,
- style: TextStyle(
- color: cs.onSurface,
- fontSize: 22,
- fontWeight: FontWeight.w700,
- ),
- ),
- const SizedBox(height: 8),
- Text(
- AppLocalizations.of(context)!.googleAuthCodeHint,
- style: TextStyle(
- color: cs.onSurface.withAlpha(153),
- fontSize: 14,
- height: 1.5,
- ),
- ),
- const SizedBox(height: 36),
- // ── 6 位数字输入格 ─────────────────────────────
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: List.generate(6, (i) {
- return SizedBox(
- width: 48,
- height: 56,
- child: TextField(
- controller: _controllers[i],
- focusNode: _focusNodes[i],
- textAlign: TextAlign.center,
- keyboardType: TextInputType.number,
- maxLength: 1,
- onChanged: (v) => _onDigitChanged(i, v),
- style: TextStyle(
- color: cs.onSurface,
- fontSize: 22,
- fontWeight: FontWeight.w600,
- ),
- decoration: InputDecoration(
- counterText: '',
- filled: true,
- fillColor: cs.surface,
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: BorderSide.none,
- ),
- focusedBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: const BorderSide(color: AppColors.brand, width: 1.5),
- ),
- ),
- ),
- );
- }),
- ),
- const SizedBox(height: 36),
- // ── 确认按钮 ──────────────────────────────────
- SizedBox(
- width: double.infinity,
- height: 50,
- child: ElevatedButton(
- onPressed: _allFilled
- ? () {
- // Mock: verify and go home
- context.go('/');
- }
- : null,
- style: ElevatedButton.styleFrom(
- backgroundColor: AppColors.brand,
- disabledBackgroundColor: AppColors.brand.withAlpha(80),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(10),
- ),
- ),
- child: Text(
- AppLocalizations.of(context)!.confirm,
- style: TextStyle(
- color: _allFilled ? cs.surface : cs.surface.withAlpha(153),
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- ),
- ),
- const SizedBox(height: 20),
- // ── 找不到验证码 ──────────────────────────────
- Center(
- child: GestureDetector(
- onTap: () {},
- child: Text(
- AppLocalizations.of(context)!.cantUseGoogleAuth,
- style: const TextStyle(
- color: AppColors.brand,
- fontSize: 14,
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- );
- }
- }
|