import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:miaoji_zhang/shared/api/api_client.dart'; import 'package:miaoji_zhang/shared/api/auth_api.dart'; import 'package:miaoji_zhang/shared/theme/app_theme.dart'; class RegisterPage extends StatefulWidget { const RegisterPage({super.key}); @override State createState() => _RegisterPageState(); } class _RegisterPageState extends State { final _user = TextEditingController(); final _pass = TextEditingController(); bool _loading = false; bool _agreed = false; @override void dispose() { _user.dispose(); _pass.dispose(); super.dispose(); } Future _register() async { final username = _user.text.trim(); if (username.length < 3 || username.length > 32) { _message('用户名长度需在 3-32 之间'); return; } if (_pass.text.length < 6) { _message('密码至少 6 位'); return; } if (!_agreed) { _message('请先单独勾选同意用户协议与隐私政策'); return; } setState(() => _loading = true); try { await AuthApi.register(username, _pass.text, agreedToTerms: _agreed); if (!mounted) return; context.go('/onboarding'); } catch (error) { if (!mounted) return; _message(apiErrorMessage(error)); } finally { if (mounted) setState(() => _loading = false); } } void _message(String message) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(message))); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('注册')), body: SafeArea( child: ListView( padding: const EdgeInsets.symmetric(horizontal: 28), children: [ SizedBox(height: 32), TextField( controller: _user, decoration: InputDecoration(hintText: '用户名(3-32 位)'), ), SizedBox(height: 12), TextField( controller: _pass, obscureText: true, decoration: InputDecoration(hintText: '密码(至少 6 位)'), ), SizedBox(height: 18), Semantics( checked: _agreed, button: true, label: '同意用户协议与隐私政策', child: InkWell( onTap: () => setState(() => _agreed = !_agreed), borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric(vertical: 7), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ AnimatedContainer( duration: const Duration(milliseconds: 160), width: 21, height: 21, decoration: BoxDecoration( color: _agreed ? AppTheme.primary : Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all( color: _agreed ? AppTheme.primary : context.jz.text3, ), ), child: _agreed ? Icon( Icons.check_rounded, size: 15, color: Colors.white, ) : null, ), SizedBox(width: 10), Expanded( child: Text( '我已阅读并单独同意以下用户协议与隐私政策', style: TextStyle( fontSize: 12.5, height: 1.5, color: context.jz.text2, ), ), ), ], ), ), ), ), Wrap( spacing: 2, runSpacing: 0, children: [ _legalLink('《用户协议》', 'terms'), _legalLink('《隐私政策》', 'privacy'), _legalLink('权限用途', 'permissions'), _legalLink('第三方 SDK 清单', 'sdk'), ], ), SizedBox(height: 18), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _loading ? null : _register, child: _loading ? SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : Text('注册'), ), ), SizedBox(height: 14), TextButton( onPressed: () => context.go('/login'), child: Text( '已有账号?去登录', style: TextStyle(color: context.jz.text2), ), ), ], ), ), ); } Widget _legalLink(String label, String kind) => TextButton( onPressed: () => context.push('/legal/' + kind), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), minimumSize: const Size(0, 34), ), child: Text(label, style: TextStyle(fontSize: 11.5)), ); }