import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../data/providers.dart'; import '../../data/state/app_interaction_state.dart'; import '../../routing/app_routes.dart'; import '../../theme/app_icons.dart'; import '../../theme/yanting_text.dart'; import '../../theme/yanting_tokens.dart'; import '../../widgets/app_buttons.dart'; import '../../widgets/app_card.dart'; import '../../widgets/page_header.dart'; import '../../widgets/states.dart'; class LoginPage extends HookConsumerWidget { const LoginPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final phoneController = useTextEditingController(); final codeController = useTextEditingController(); final agreed = useState(false); final loading = useState(false); final theme = ShadTheme.of(context); final auth = ref.watch(authControllerProvider); Future submit() async { final phone = phoneController.text.trim(); final code = codeController.text.trim(); if (phone.length < 8) { showAppToast(context, '请输入手机号'); return; } if (code.length < 4) { showAppToast(context, '请输入验证码'); return; } if (!agreed.value) { showAppToast(context, '请先同意用户协议和隐私政策'); return; } loading.value = true; try { await ref .read(authControllerProvider.notifier) .login(LoginMethod.phone, phone: phone); await ref.read(profileControllerProvider.notifier).refresh(); if (!context.mounted) return; showAppToast(context, '已登录 ${maskPhone(phone)}'); if (context.canPop()) { context.pop(); } else { context.go(AppRoutes.profile); } } finally { loading.value = false; } } return Scaffold( backgroundColor: theme.colorScheme.background, appBar: AppBar( leading: IconButton( icon: const Icon(AppIcons.arrowLeft), onPressed: () { if (context.canPop()) { context.pop(); } else { context.go(AppRoutes.profile); } }, ), title: const Text('登录 · Login'), ), body: ListView( padding: const EdgeInsets.fromLTRB( YantingSpacing.screenX, 4, YantingSpacing.screenX, 20, ), children: [ const PageHeader(title: '登录研听', subtitle: '先把登录逻辑接通,弹窗入口保持不变'), if (auth.loggedIn) ...[ AppCard( color: theme.colorScheme.secondary, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('当前已登录', style: YantingText.cardTitle), const SizedBox(height: 6), Text( auth.phone == null ? '本地登录态已生效' : '手机号 ${maskPhone(auth.phone!)}', style: YantingText.body.copyWith( color: theme.colorScheme.mutedForeground, ), ), ], ), ), const SizedBox(height: YantingSpacing.x3), ], AppCard( padding: const EdgeInsets.all(18), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('手机号登录', style: YantingText.sectionTitle), const SizedBox(height: 12), ShadInput( controller: phoneController, placeholder: const Text('请输入手机号'), keyboardType: TextInputType.phone, inputFormatters: [FilteringTextInputFormatter.digitsOnly], ), const SizedBox(height: 12), ShadInput( controller: codeController, placeholder: const Text('验证码'), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], trailing: Padding( padding: const EdgeInsets.only(right: 4), child: AppButton( label: '发送验证码', kind: AppButtonKind.ghost, compact: true, onPressed: () => showAppToast(context, '验证码功能待接入'), ), ), ), const SizedBox(height: 14), ShadCheckbox( value: agreed.value, onChanged: (value) => agreed.value = value, label: const Text('我已阅读并同意'), sublabel: const Text('《用户协议》和《隐私政策》'), ), const SizedBox(height: 18), AppButton( label: loading.value ? '登录中...' : '登录', expand: true, onPressed: loading.value ? null : submit, ), ], ), ), const SizedBox(height: YantingSpacing.x3), AppCard( color: theme.colorScheme.secondary, child: Text( '当前版本先做本地登录态和页面流转,后端接口接入后再替换为真实校验。', style: YantingText.meta.copyWith( color: theme.colorScheme.mutedForeground, ), ), ), ], ), ); } } String maskPhone(String phone) { if (phone.length < 7) return phone; return '${phone.substring(0, 3)}****${phone.substring(phone.length - 4)}'; }