389 lines
14 KiB
Dart
389 lines
14 KiB
Dart
import 'package:flutter/cupertino.dart';
|
||
import 'package:get/get.dart';
|
||
|
||
class RegisterPage extends StatefulWidget {
|
||
const RegisterPage({super.key});
|
||
|
||
@override
|
||
State<RegisterPage> createState() => _RegisterPageState();
|
||
}
|
||
|
||
class _RegisterPageState extends State<RegisterPage> {
|
||
final _formKey = GlobalKey<FormState>();
|
||
final _phoneController = TextEditingController();
|
||
final _smsCodeController = TextEditingController();
|
||
final _passwordController = TextEditingController();
|
||
final _confirmPasswordController = TextEditingController();
|
||
bool _isLoading = false;
|
||
bool _isCountdownRunning = false;
|
||
int _countdownSeconds = 0;
|
||
bool _obscurePassword = true;
|
||
bool _obscureConfirmPassword = true;
|
||
|
||
@override
|
||
void dispose() {
|
||
_phoneController.dispose();
|
||
_smsCodeController.dispose();
|
||
_passwordController.dispose();
|
||
_confirmPasswordController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
Future<void> _sendSmsCode() async {
|
||
if (_phoneController.text.isEmpty) {
|
||
showCupertinoDialog(
|
||
context: context,
|
||
builder: (context) => CupertinoAlertDialog(
|
||
title: const Text('提示'),
|
||
content: const Text('请先输入手机号'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
child: const Text('确定'),
|
||
onPressed: () => Navigator.pop(context),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
return;
|
||
}
|
||
|
||
setState(() {
|
||
_isCountdownRunning = true;
|
||
_countdownSeconds = 60;
|
||
});
|
||
|
||
await Future.delayed(const Duration(seconds: 1));
|
||
|
||
while (_countdownSeconds > 0 && mounted) {
|
||
await Future.delayed(const Duration(seconds: 1));
|
||
setState(() {
|
||
_countdownSeconds--;
|
||
});
|
||
}
|
||
|
||
if (mounted) {
|
||
setState(() {
|
||
_isCountdownRunning = false;
|
||
});
|
||
}
|
||
|
||
if (mounted) {
|
||
showCupertinoDialog(
|
||
context: context,
|
||
builder: (context) => CupertinoAlertDialog(
|
||
title: const Text('验证码已发送'),
|
||
content: const Text('请输入收到的6位验证码'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
child: const Text('确定'),
|
||
onPressed: () => Navigator.pop(context),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
Future<void> _handleRegister() async {
|
||
if (!_formKey.currentState!.validate()) {
|
||
return;
|
||
}
|
||
|
||
setState(() {
|
||
_isLoading = true;
|
||
});
|
||
|
||
await Future.delayed(const Duration(seconds: 1));
|
||
|
||
setState(() {
|
||
_isLoading = false;
|
||
});
|
||
|
||
if (mounted) {
|
||
showCupertinoDialog(
|
||
context: context,
|
||
builder: (context) => CupertinoAlertDialog(
|
||
title: const Text('注册成功'),
|
||
content: const Text('欢迎加入!'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
isDefaultAction: true,
|
||
child: const Text('确定'),
|
||
onPressed: () {
|
||
Navigator.pop(context);
|
||
Navigator.pop(context);
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return CupertinoPageScaffold(
|
||
navigationBar: CupertinoNavigationBar(
|
||
middle: const Text('注册'),
|
||
trailing: CupertinoButton(
|
||
padding: EdgeInsets.zero,
|
||
onPressed: () {
|
||
Get.offAndToNamed('/login');
|
||
},
|
||
child: const Text('取消'),
|
||
),
|
||
),
|
||
child: SafeArea(
|
||
child: SingleChildScrollView(
|
||
padding: const EdgeInsets.all(24.0),
|
||
child: Form(
|
||
key: _formKey,
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||
children: [
|
||
const SizedBox(height: 32),
|
||
const Icon(
|
||
CupertinoIcons.person_2_fill,
|
||
size: 80,
|
||
color: CupertinoColors.activeGreen,
|
||
),
|
||
const SizedBox(height: 24),
|
||
const Text(
|
||
'创建新账户',
|
||
style: TextStyle(
|
||
fontSize: 28,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
'使用手机号快速注册',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
color: CupertinoColors.inactiveGray,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: 40),
|
||
CupertinoFormSection.insetGrouped(
|
||
header: const Text('手机号'),
|
||
children: [
|
||
CupertinoTextFormFieldRow(
|
||
controller: _phoneController,
|
||
keyboardType: TextInputType.phone,
|
||
prefix: const Padding(
|
||
padding: EdgeInsets.only(left: 8),
|
||
child: Icon(CupertinoIcons.phone, size: 20),
|
||
),
|
||
placeholder: '请输入11位手机号',
|
||
validator: (value) {
|
||
if (value == null || value.isEmpty) {
|
||
return '请输入手机号';
|
||
}
|
||
if (value.length != 11) {
|
||
return '请输入有效的手机号';
|
||
}
|
||
return null;
|
||
},
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: CupertinoFormSection.insetGrouped(
|
||
header: const Text('验证码'),
|
||
children: [
|
||
CupertinoTextFormFieldRow(
|
||
controller: _smsCodeController,
|
||
keyboardType: TextInputType.number,
|
||
prefix: const Padding(
|
||
padding: EdgeInsets.only(left: 8),
|
||
child: Icon(CupertinoIcons.shield, size: 20),
|
||
),
|
||
placeholder: '6位验证码',
|
||
validator: (value) {
|
||
if (value == null || value.isEmpty) {
|
||
return '请输入验证码';
|
||
}
|
||
if (value.length != 6) {
|
||
return '验证码为6位';
|
||
}
|
||
return null;
|
||
},
|
||
),
|
||
],
|
||
),
|
||
),
|
||
const SizedBox(width: 12),
|
||
Padding(
|
||
padding: const EdgeInsets.only(top: 30),
|
||
child: SizedBox(
|
||
width: 120,
|
||
height: 50,
|
||
child: CupertinoButton.filled(
|
||
onPressed: _isCountdownRunning ? null : _sendSmsCode,
|
||
borderRadius: BorderRadius.circular(12),
|
||
padding: EdgeInsets.zero,
|
||
child: Text(
|
||
_isCountdownRunning ? '${_countdownSeconds}s' : '获取验证码',
|
||
style: const TextStyle(fontSize: 14),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
CupertinoFormSection.insetGrouped(
|
||
header: const Text('设置密码'),
|
||
children: [
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
child: CupertinoTextFormFieldRow(
|
||
controller: _passwordController,
|
||
obscureText: _obscurePassword,
|
||
prefix: const Padding(
|
||
padding: EdgeInsets.only(left: 8),
|
||
child: Icon(CupertinoIcons.lock, size: 20),
|
||
),
|
||
placeholder: '请设置密码(至少6位)',
|
||
validator: (value) {
|
||
if (value == null || value.isEmpty) {
|
||
return '请输入密码';
|
||
}
|
||
if (value.length < 6) {
|
||
return '密码至少6位';
|
||
}
|
||
return null;
|
||
},
|
||
),
|
||
),
|
||
CupertinoButton(
|
||
padding: const EdgeInsets.only(left: 8),
|
||
onPressed: () {
|
||
setState(() {
|
||
_obscurePassword = !_obscurePassword;
|
||
});
|
||
},
|
||
child: Icon(
|
||
_obscurePassword
|
||
? CupertinoIcons.eye_slash
|
||
: CupertinoIcons.eye,
|
||
size: 20,
|
||
color: CupertinoColors.inactiveGray,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
CupertinoFormSection.insetGrouped(
|
||
header: const Text('确认密码'),
|
||
children: [
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
child: CupertinoTextFormFieldRow(
|
||
controller: _confirmPasswordController,
|
||
obscureText: _obscureConfirmPassword,
|
||
prefix: const Padding(
|
||
padding: EdgeInsets.only(left: 8),
|
||
child: Icon(CupertinoIcons.lock_shield, size: 20),
|
||
),
|
||
placeholder: '请再次输入密码',
|
||
validator: (value) {
|
||
if (value == null || value.isEmpty) {
|
||
return '请确认密码';
|
||
}
|
||
if (value != _passwordController.text) {
|
||
return '两次输入的密码不一致';
|
||
}
|
||
return null;
|
||
},
|
||
),
|
||
),
|
||
CupertinoButton(
|
||
padding: const EdgeInsets.only(left: 8),
|
||
onPressed: () {
|
||
setState(() {
|
||
_obscureConfirmPassword = !_obscureConfirmPassword;
|
||
});
|
||
},
|
||
child: Icon(
|
||
_obscureConfirmPassword
|
||
? CupertinoIcons.eye_slash
|
||
: CupertinoIcons.eye,
|
||
size: 20,
|
||
color: CupertinoColors.inactiveGray,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 32),
|
||
CupertinoButton.filled(
|
||
onPressed: _isLoading ? null : _handleRegister,
|
||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||
borderRadius: BorderRadius.circular(12),
|
||
child: _isLoading
|
||
? const SizedBox(
|
||
height: 20,
|
||
width: 20,
|
||
child: CupertinoActivityIndicator(
|
||
radius: 10,
|
||
),
|
||
)
|
||
: const Text(
|
||
'立即注册',
|
||
style: TextStyle(fontSize: 17),
|
||
),
|
||
),
|
||
const SizedBox(height: 24),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Text(
|
||
'已有账户?',
|
||
style: TextStyle(
|
||
color: CupertinoColors.inactiveGray,
|
||
),
|
||
),
|
||
CupertinoButton(
|
||
padding: EdgeInsets.zero,
|
||
onPressed: () {
|
||
Get.offAndToNamed('/login');
|
||
},
|
||
child: const Text('立即登录'),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
Text(
|
||
'注册即表示您同意我们的服务条款和隐私政策',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: CupertinoColors.inactiveGray,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|