Files
plan_flutter/lib/page/system/code/login_code_page.dart
zhutao ca376d9393 1.列表,筛选完成和未完成
2.详情,增加checkout
2025-09-24 10:22:35 +08:00

229 lines
6.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:go_router/go_router.dart';
import 'package:plan/api/endpoints/user_api.dart';
import 'package:plan/api/network/safe.dart';
import 'package:provider/provider.dart';
import '../../../providers/app_store.dart';
import '../../../router/config/route_paths.dart';
class LoginCodePage extends StatefulWidget {
final String email;
final String password;
const LoginCodePage({super.key, required this.email, required this.password});
@override
State<LoginCodePage> createState() => _LoginCodePageState();
}
class _LoginCodePageState extends State<LoginCodePage> {
final List<FocusNode> _focusNodes = List.generate(4, (_) => FocusNode());
final List<TextEditingController> _controllers = List.generate(
4,
(_) => TextEditingController(),
);
//倒计时
int _count = 60;
Timer? _timer;
@override
void initState() {
super.initState();
_handSendCode();
_handClear();
}
@override
void dispose() {
_timer?.cancel();
_handClear();
super.dispose();
}
///小输入框改变时
void _onChanged(String value, int index) async {
//一键复制
if (value.length == 4) {
_handlePaste(value);
}
//提交
if (value.isNotEmpty && index == 3) {
_handSubmit();
return;
}
// 自动跳到下一格
if (value.length == 1 && index < 3) {
_focusNodes[index + 1].requestFocus();
}
}
void _handlePaste(String pastedText) {
// 只取前4位数字
final digits = pastedText.replaceAll(RegExp(r'[^0-9]'), '');
for (int i = 0; i < 4; i++) {
_controllers[i].text = i < digits.length ? digits[i] : '';
}
if (digits.length >= 4) {
_focusNodes[3].requestFocus();
_handSubmit();
} else if (digits.isNotEmpty) {
_focusNodes[digits.length].requestFocus();
}
}
///删除键
void _onDelete(KeyEvent event, int index) {
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.backspace) {
final currentController = _controllers[index];
if (currentController.text.isEmpty && index > 0) {
_focusNodes[index - 1].requestFocus();
_controllers[index - 1].clear();
}
}
}
///发送验证码
void _handSendCode() {
if (_count != 60) {
return;
}
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_count--;
});
if (_count == 0) {
setState(() {
_count = 60;
});
timer.cancel();
}
});
sendEmailCodeApi(widget.email);
EasyLoading.showToast("Send success");
}
///提交
void _handSubmit() async {
String code = _controllers.map((controller) => controller.text).join();
if (code.length == 4) {
EasyLoading.show();
var res = await safeRequest(
registerApi(
widget.email,
widget.password,
code,
),
onError: (error) {
_handClear();
EasyLoading.showToast("Login Error");
},
);
var appStore = context.read<AppStore>();
await appStore.setInfo(res);
context.go(RoutePaths.layout);
}
}
///清空
void _handClear() {
for (var controller in _controllers) {
controller.clear();
}
_focusNodes.first.requestFocus();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(),
body: ListView(
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(20),
children: [
Container(
margin: EdgeInsets.only(bottom: 20),
child: Text(
"Check your inbox",
style: Theme.of(context).textTheme.titleLarge,
),
),
Container(
margin: EdgeInsets.only(bottom: 60),
child: Text(
"Verification code has been sent to ${widget.email}",
style: Theme.of(context).textTheme.labelLarge,
),
),
Row(
spacing: 20,
children: List.generate(4, (index) {
return Expanded(
child: AspectRatio(
aspectRatio: 1,
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(10),
),
child: KeyboardListener(
focusNode: FocusNode(),
onKeyEvent: (event) {
_onDelete(event, index);
},
child: TextField(
controller: _controllers[index],
focusNode: _focusNodes[index],
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 4,
style: TextStyle(fontSize: 32),
decoration: InputDecoration(
counterText: "",
border: InputBorder.none,
isCollapsed: true,
),
onChanged: (value) {
_onChanged(value, index);
},
),
),
),
),
);
}),
),
Container(
margin: EdgeInsets.only(top: 30),
child: Row(
children: [
GestureDetector(
onTap: _handSendCode,
child: Visibility(
visible: _count != 60,
replacement: Text(
"Resend Code",
style: Theme.of(context).textTheme.bodySmall,
),
child: Text(
"Resend Code${_count}s",
style: Theme.of(context).textTheme.labelMedium,
),
),
),
],
),
),
],
),
);
}
}