登录页面Obx修改
This commit is contained in:
parent
680afe5b41
commit
cd260e1044
@ -1,17 +1,26 @@
|
||||
import 'package:cpnav/appbar.dart';
|
||||
import 'package:cpnav/pages/login/loginprefs.dart';
|
||||
import 'package:cpnav/pages/pass_track/controller.dart';
|
||||
import 'package:cpnav/pages/pass_track/bottomIcon/iconController.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:scence_map/controller.dart';
|
||||
import 'pages/login/login_page.dart';
|
||||
import 'pages/login/my_routes.dart';
|
||||
import 'pages/pass_track/view.dart';
|
||||
import 'service/pile_cm.dart';
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); //设置全屏
|
||||
Get.put(PassTrackController('WXLMB', 'cp_road'));
|
||||
Get.put(IconController());
|
||||
Get.put(LoginPageController());
|
||||
Get.put(AccountLoginController());
|
||||
Get.put(PhoneLoginController());
|
||||
LoginPrefs loginPrefs = LoginPrefs();
|
||||
loginPrefs.removeToken();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
@ -24,25 +33,12 @@ class MyApp extends StatelessWidget {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
// This is the theme of your application.
|
||||
//
|
||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
||||
// the application has a purple toolbar. Then, without quitting the app,
|
||||
// try changing the seedColor in the colorScheme below to Colors.green
|
||||
// and then invoke "hot reload" (save your changes or press the "hot
|
||||
// reload" button in a Flutter-supported IDE, or press "r" if you used
|
||||
// the command line to start the app).
|
||||
//
|
||||
// Notice that the counter didn't reset back to zero; the application
|
||||
// state is not lost during the reload. To reset the state, use hot
|
||||
// restart instead.
|
||||
//
|
||||
// This works for code too, not just values: Most code changes can be
|
||||
// tested with just a hot reload.
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
||||
initialRoute: "home",
|
||||
onGenerateRoute: onGenerateRoute,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'package:cpnav/models/user.dart';
|
||||
|
||||
class LoginPrefs extends GetxController {
|
||||
static const String expireStr = "expire"; //用户名
|
||||
static const String tokenStr = "token"; //token
|
||||
static const String phoneStr = "phone";
|
||||
final box = GetStorage(); // 实例化 GetStorage
|
||||
|
||||
Future<String> init() async {
|
||||
await GetStorage.init(); // 初始化 GetStorage
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
void saveExpire(int expire) {
|
||||
box.write(expireStr, expire);
|
||||
update();
|
||||
}
|
||||
|
||||
int getExpire() {
|
||||
return box.read(expireStr) ?? 0;
|
||||
}
|
||||
|
||||
void saveToken(String token) {
|
||||
box.write(tokenStr, token);
|
||||
update();
|
||||
}
|
||||
|
||||
String getToken() {
|
||||
return box.read(tokenStr) ?? "";
|
||||
}
|
||||
|
||||
void removeExpire() {
|
||||
box.remove(expireStr);
|
||||
update();
|
||||
}
|
||||
|
||||
void removeToken() {
|
||||
box.remove(tokenStr);
|
||||
update();
|
||||
}
|
||||
|
||||
void savePhone(String phone) {
|
||||
box.write(phoneStr, phone);
|
||||
update();
|
||||
}
|
||||
|
||||
String getPhone() {
|
||||
return box.read(phoneStr) ?? "";
|
||||
}
|
||||
|
||||
void clearLogin() {
|
||||
box.erase(); // 清除所有数据
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
class UserController extends GetxController {
|
||||
final box = GetStorage(); // 实例化 GetStorage
|
||||
|
||||
UserModel? getUser() {
|
||||
final userMap = box.read('user');
|
||||
if (userMap != null) {
|
||||
return UserModel.fromJson(userMap);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void setUser(Map user) {
|
||||
box.write('user', user);
|
||||
update();
|
||||
}
|
||||
}
|
@ -5,29 +5,86 @@ import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:cpnav/pages/login/loginprefs.dart';
|
||||
import 'package:cpnav/service/base.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class Login extends StatefulWidget {
|
||||
const Login({super.key});
|
||||
// class Login extends StatefulWidget {
|
||||
// const Login({super.key});
|
||||
|
||||
// @override
|
||||
// State<Login> createState() => _LoginState();
|
||||
// }
|
||||
|
||||
// class _LoginState extends State<Login> with SingleTickerProviderStateMixin {
|
||||
// //with SingleTickerProviderStateMixin 使this 不报错
|
||||
// late TabController _tabController;
|
||||
// //初始化实例
|
||||
// @override
|
||||
// void initState() {
|
||||
// _tabController = TabController(length: 2, vsync: this);
|
||||
// super.initState();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void dispose() {
|
||||
// _tabController.dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// appBar: AppBar(
|
||||
// title: const Text('欢迎登录'),
|
||||
// ),
|
||||
// body: Column(
|
||||
// children: <Widget>[
|
||||
// TabBar(
|
||||
// labelColor: Colors.black, // 设置选中标签的字体颜色为黑色
|
||||
// unselectedLabelColor: Colors.grey, // 设置未选中标签的字体颜色为灰色
|
||||
// labelStyle: const TextStyle(color: Colors.black), // 设置选中标签的字体颜色为黑色
|
||||
// unselectedLabelStyle:
|
||||
// const TextStyle(color: Colors.grey), // 设置未选中标签的字体颜色为灰色
|
||||
// controller: _tabController,
|
||||
// tabs: const [
|
||||
// Tab(text: '手机号登录', icon: Icon(Icons.phone_android)),
|
||||
// Tab(text: '账号登录', icon: Icon(Icons.account_box_outlined)),
|
||||
// ],
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: TabBarView(
|
||||
// controller: _tabController,
|
||||
// children: const [
|
||||
// PhoneLoginPage(),
|
||||
// AccountLoginPage(),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
class LoginPageController extends GetxController
|
||||
with SingleGetTickerProviderMixin {
|
||||
late TabController _tabController;
|
||||
|
||||
@override
|
||||
State<Login> createState() => _LoginState();
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
_tabController = TabController(length: 2, vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_tabController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
TabController get tabController => _tabController;
|
||||
}
|
||||
|
||||
class _LoginState extends State<Login> with SingleTickerProviderStateMixin {
|
||||
//with SingleTickerProviderStateMixin 使this 不报错
|
||||
late TabController _tabController;
|
||||
//初始化实例
|
||||
@override
|
||||
void initState() {
|
||||
_tabController = TabController(length: 2, vsync: this);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
class Login extends GetView<LoginPageController> {
|
||||
const Login({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -43,7 +100,7 @@ class _LoginState extends State<Login> with SingleTickerProviderStateMixin {
|
||||
labelStyle: const TextStyle(color: Colors.black), // 设置选中标签的字体颜色为黑色
|
||||
unselectedLabelStyle:
|
||||
const TextStyle(color: Colors.grey), // 设置未选中标签的字体颜色为灰色
|
||||
controller: _tabController,
|
||||
controller: controller.tabController,
|
||||
tabs: const [
|
||||
Tab(text: '手机号登录', icon: Icon(Icons.phone_android)),
|
||||
Tab(text: '账号登录', icon: Icon(Icons.account_box_outlined)),
|
||||
@ -51,7 +108,7 @@ class _LoginState extends State<Login> with SingleTickerProviderStateMixin {
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
controller: controller.tabController,
|
||||
children: const [
|
||||
PhoneLoginPage(),
|
||||
AccountLoginPage(),
|
||||
@ -64,48 +121,211 @@ class _LoginState extends State<Login> with SingleTickerProviderStateMixin {
|
||||
}
|
||||
}
|
||||
|
||||
class AccountLoginPage extends StatefulWidget {
|
||||
const AccountLoginPage({super.key});
|
||||
// class AccountLoginPage extends StatefulWidget {
|
||||
// const AccountLoginPage({super.key});
|
||||
|
||||
// @override
|
||||
// State<AccountLoginPage> createState() => _AccountLoginPageState();
|
||||
// }
|
||||
|
||||
// class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
// //初始化FormState
|
||||
// final _formKey = GlobalKey<FormState>();
|
||||
// String username = "";
|
||||
// String password = "";
|
||||
// String verifyCode = "";
|
||||
// String svgString = "";
|
||||
// String captchaId = "";
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
// SchedulerBinding.instance.addPostFrameCallback((_) async {
|
||||
// await changeCaptcha();
|
||||
// });
|
||||
// }
|
||||
|
||||
// changeCaptcha() async {
|
||||
// var captcha = await GetServices().getCaptcha();
|
||||
// setState(() {
|
||||
// svgString = captcha['data'];
|
||||
// captchaId = captcha['captchaId'];
|
||||
// });
|
||||
// }
|
||||
|
||||
// showErrorSnackbar(BuildContext context, String text) {
|
||||
// final snackBar = SnackBar(
|
||||
// content: Text(text),
|
||||
// backgroundColor: Colors.red,
|
||||
// );
|
||||
|
||||
// ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
// }
|
||||
|
||||
// LoginPrefs loginPrefs = LoginPrefs();
|
||||
// bool _obscureText = false;
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return SingleChildScrollView(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(16.0),
|
||||
// child: Column(
|
||||
// children: [
|
||||
// Form(
|
||||
// key: _formKey,
|
||||
// child: Column(
|
||||
// children: [
|
||||
// // 账号输入框
|
||||
// TextFormField(
|
||||
// decoration: const InputDecoration(
|
||||
// labelText: '用户名:',
|
||||
// ),
|
||||
// onSaved: (String? value) => username = value!,
|
||||
// validator: (String? value) {
|
||||
// String str = "";
|
||||
|
||||
// RegExp regex = RegExp(r'^[a-zA-Z0-9]+$');
|
||||
// if (value!.isEmpty) {
|
||||
// str = '用户名不能为空';
|
||||
// } else if (!regex.hasMatch(value)) {
|
||||
// str = '请输入有效的账号';
|
||||
// }
|
||||
|
||||
// return str == "" ? null : str;
|
||||
// },
|
||||
// ),
|
||||
// const SizedBox(height: 16.0),
|
||||
|
||||
// // 密码输入框
|
||||
// TextFormField(
|
||||
// decoration: InputDecoration(
|
||||
// labelText: '密码:',
|
||||
// suffixIcon: IconButton(
|
||||
// icon: Icon(
|
||||
// _obscureText
|
||||
// ? Icons.visibility
|
||||
// : Icons.visibility_off,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _obscureText = !_obscureText; // 切换密码可见状态
|
||||
// });
|
||||
// }),
|
||||
// ),
|
||||
// obscureText: _obscureText,
|
||||
// onSaved: (String? value) => password = value!,
|
||||
// validator: (String? value) {
|
||||
// String str = "";
|
||||
// RegExp regex = RegExp(r'^[a-zA-Z0-9@#$]+$');
|
||||
|
||||
// if (value!.isEmpty) {
|
||||
// str = '密码不能为空';
|
||||
// } else if (!regex.hasMatch(value)) {
|
||||
// str = '请输入有效的密码';
|
||||
// }
|
||||
|
||||
// return str == "" ? null : str;
|
||||
// },
|
||||
// ),
|
||||
// const SizedBox(height: 24.0),
|
||||
// Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: TextFormField(
|
||||
// decoration: const InputDecoration(
|
||||
// labelText: '验证码:',
|
||||
// ),
|
||||
// keyboardType: TextInputType.phone,
|
||||
// validator: (String? value) {
|
||||
// String str = "";
|
||||
|
||||
// if (value!.isEmpty) {
|
||||
// str = '验证码不能为空';
|
||||
// }
|
||||
|
||||
// return str == "" ? null : str;
|
||||
// },
|
||||
// onSaved: (String? value) => verifyCode = value!,
|
||||
// ),
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// changeCaptcha();
|
||||
// },
|
||||
// child: svgString.isNotEmpty
|
||||
// ? SvgPicture.string(
|
||||
// svgString,
|
||||
// width: 70, // 设置宽度
|
||||
// height: 40, // 设置高度
|
||||
// color: Colors.black,
|
||||
// )
|
||||
// : const Text(""))
|
||||
// ],
|
||||
// ),
|
||||
// // 登录按钮
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// _formKey.currentState!.save(); //必须
|
||||
// var res = await GetServices().getAccountLogin(
|
||||
// captchaId, password, username, verifyCode);
|
||||
// setState(() {
|
||||
// if (res['code'] != 1000) {
|
||||
// changeCaptcha();
|
||||
// showErrorSnackbar(context, res["message"]);
|
||||
// } else {
|
||||
// loginPrefs.saveExpire((res["data"]["expire"]));
|
||||
// loginPrefs.saveToken((res["data"]["token"]));
|
||||
// Navigator.pushNamed(context, 'home'); //跳转至首页
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// child: const Text('登录'),
|
||||
// ),
|
||||
// ],
|
||||
// ))
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
class AccountLoginController extends GetxController {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final username = ''.obs;
|
||||
final password = ''.obs;
|
||||
final verifyCode = ''.obs;
|
||||
final svgString = ''.obs;
|
||||
final captchaId = ''.obs;
|
||||
final obscureText = false.obs;
|
||||
|
||||
@override
|
||||
State<AccountLoginPage> createState() => _AccountLoginPageState();
|
||||
}
|
||||
|
||||
class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
//初始化FormState
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
String username = "";
|
||||
String password = "";
|
||||
String verifyCode = "";
|
||||
String svgString = "";
|
||||
String captchaId = "";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) async {
|
||||
await changeCaptcha();
|
||||
});
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
changeCaptcha();
|
||||
}
|
||||
|
||||
changeCaptcha() async {
|
||||
Future<void> changeCaptcha() async {
|
||||
var captcha = await GetServices().getCaptcha();
|
||||
setState(() {
|
||||
svgString = captcha['data'];
|
||||
captchaId = captcha['captchaId'];
|
||||
});
|
||||
svgString.value = captcha['data'];
|
||||
captchaId.value = captcha['captchaId'];
|
||||
}
|
||||
|
||||
showErrorSnackbar(BuildContext context, String text) {
|
||||
void showErrorSnackbar(String text) {
|
||||
final snackBar = SnackBar(
|
||||
content: Text(text),
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
ScaffoldMessenger.of(Get.context!).showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
LoginPrefs loginPrefs = LoginPrefs();
|
||||
bool _obscureText = false;
|
||||
|
||||
}
|
||||
|
||||
class AccountLoginPage extends GetView<AccountLoginController> {
|
||||
const AccountLoginPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
@ -114,7 +334,7 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
child: Column(
|
||||
children: [
|
||||
Form(
|
||||
key: _formKey,
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
// 账号输入框
|
||||
@ -122,7 +342,8 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
decoration: const InputDecoration(
|
||||
labelText: '用户名:',
|
||||
),
|
||||
onSaved: (String? value) => username = value!,
|
||||
onSaved: (String? value) =>
|
||||
controller.username.value = value!,
|
||||
validator: (String? value) {
|
||||
String str = "";
|
||||
|
||||
@ -139,23 +360,22 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
const SizedBox(height: 16.0),
|
||||
|
||||
// 密码输入框
|
||||
TextFormField(
|
||||
Obx(() => TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: '密码:',
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
_obscureText
|
||||
controller.obscureText.value
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_obscureText = !_obscureText; // 切换密码可见状态
|
||||
});
|
||||
controller.obscureText.toggle(); // 切换密码可见状态
|
||||
}),
|
||||
),
|
||||
obscureText: _obscureText,
|
||||
onSaved: (String? value) => password = value!,
|
||||
obscureText: controller.obscureText.value,
|
||||
onSaved: (String? value) =>
|
||||
controller.password.value = value!,
|
||||
validator: (String? value) {
|
||||
String str = "";
|
||||
RegExp regex = RegExp(r'^[a-zA-Z0-9@#$]+$');
|
||||
@ -168,7 +388,7 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
|
||||
return str == "" ? null : str;
|
||||
},
|
||||
),
|
||||
)),
|
||||
const SizedBox(height: 24.0),
|
||||
Row(
|
||||
children: [
|
||||
@ -187,46 +407,51 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
|
||||
return str == "" ? null : str;
|
||||
},
|
||||
onSaved: (String? value) => verifyCode = value!,
|
||||
onSaved: (String? value) =>
|
||||
controller.verifyCode.value = value!,
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
changeCaptcha();
|
||||
controller.changeCaptcha();
|
||||
},
|
||||
child: svgString.isNotEmpty
|
||||
child: Obx(() => controller.svgString.isNotEmpty
|
||||
? SvgPicture.string(
|
||||
svgString,
|
||||
controller.svgString.value,
|
||||
width: 70, // 设置宽度
|
||||
height: 40, // 设置高度
|
||||
color: Colors.black,
|
||||
)
|
||||
: const Text(""))
|
||||
: const Text("")))
|
||||
],
|
||||
),
|
||||
// 登录按钮
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save(); //必须
|
||||
if (controller.formKey.currentState!.validate()) {
|
||||
controller.formKey.currentState!.save(); //必须
|
||||
var res = await GetServices().getAccountLogin(
|
||||
captchaId, password, username, verifyCode);
|
||||
setState(() {
|
||||
controller.captchaId.value,
|
||||
controller.password.value,
|
||||
controller.username.value,
|
||||
controller.verifyCode.value);
|
||||
|
||||
if (res['code'] != 1000) {
|
||||
changeCaptcha();
|
||||
showErrorSnackbar(context, res["message"]);
|
||||
controller.changeCaptcha();
|
||||
controller.showErrorSnackbar(res["message"]);
|
||||
} else {
|
||||
loginPrefs.saveExpire((res["data"]["expire"]));
|
||||
loginPrefs.saveToken((res["data"]["token"]));
|
||||
Navigator.pushNamed(context, 'home'); //跳转至首页
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
child: const Text('登录'),
|
||||
),
|
||||
)
|
||||
],
|
||||
))
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -234,69 +459,248 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
}
|
||||
}
|
||||
|
||||
class PhoneLoginPage extends StatefulWidget {
|
||||
const PhoneLoginPage({super.key});
|
||||
// class PhoneLoginPage extends StatefulWidget {
|
||||
// const PhoneLoginPage({super.key});
|
||||
|
||||
@override
|
||||
State<PhoneLoginPage> createState() => _PhoneLoginPageState();
|
||||
}
|
||||
// @override
|
||||
// State<PhoneLoginPage> createState() => _PhoneLoginPageState();
|
||||
// }
|
||||
|
||||
class _PhoneLoginPageState extends State<PhoneLoginPage> {
|
||||
String phoneNumber = "";
|
||||
String smsCode = "";
|
||||
bool issmsCode = false;
|
||||
String smsText = "获取验证码";
|
||||
int _seconds = 60;
|
||||
late Timer _timer;
|
||||
//初始化FormState
|
||||
// class _PhoneLoginPageState extends State<PhoneLoginPage> {
|
||||
// String phoneNumber = "";
|
||||
// String smsCode = "";
|
||||
// bool issmsCode = false;
|
||||
// String smsText = "获取验证码";
|
||||
// int _seconds = 60;
|
||||
// late Timer _timer;
|
||||
// //初始化FormState
|
||||
// final _formKey = GlobalKey<FormState>();
|
||||
// LoginPrefs loginPrefs = LoginPrefs();
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
|
||||
// phoneNumber = loginPrefs.getPhone();
|
||||
// }
|
||||
|
||||
// void startTimer() {
|
||||
// _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
// if (_seconds > 0) {
|
||||
// _seconds -= 1;
|
||||
// smsText = "重新获取(${_seconds}s)";
|
||||
// } else {
|
||||
// _timer.cancel(); // 到0时关闭定时器
|
||||
// smsText = "获取验证码";
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// showErrorSnackbar(BuildContext context, String text) {
|
||||
// final snackBar = SnackBar(
|
||||
// content: Text(text),
|
||||
// backgroundColor: Colors.red,
|
||||
// );
|
||||
|
||||
// ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
// }
|
||||
|
||||
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Container(
|
||||
// key: _scaffoldKey,
|
||||
// padding: const EdgeInsets.all(16.0),
|
||||
// child: SingleChildScrollView(
|
||||
// child: Column(
|
||||
// children: <Widget>[
|
||||
// Form(
|
||||
// key: _formKey,
|
||||
// child:
|
||||
// // 手机号输入框
|
||||
// Column(
|
||||
// children: [
|
||||
// TextFormField(
|
||||
// maxLength: 11,
|
||||
// initialValue: phoneNumber,
|
||||
// decoration: const InputDecoration(
|
||||
// labelText: '手机号',
|
||||
// ),
|
||||
// keyboardType: TextInputType.phone,
|
||||
// validator: (String? value) {
|
||||
// String str = "";
|
||||
// final RegExp phoneRegex = RegExp(r'^[1-9]\d{10}$');
|
||||
// if (value!.isEmpty) {
|
||||
// str = '手机号不能为空';
|
||||
// } else if (!phoneRegex.hasMatch(value)) {
|
||||
// str = '请输入有效的手机号';
|
||||
// }
|
||||
|
||||
// return str == "" ? null : str;
|
||||
// },
|
||||
// onSaved: (String? value) => phoneNumber = value!,
|
||||
// ),
|
||||
// Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: TextFormField(
|
||||
// maxLength: 6,
|
||||
// decoration: const InputDecoration(
|
||||
// labelText: '验证码',
|
||||
// ),
|
||||
// keyboardType: TextInputType.phone,
|
||||
// validator: (String? value) {
|
||||
// String str = "";
|
||||
// if (value!.isEmpty) {
|
||||
// str = '验证码不能为空';
|
||||
// }
|
||||
|
||||
// if (issmsCode) {
|
||||
// return null;
|
||||
// }
|
||||
// return str == "" ? null : str;
|
||||
// },
|
||||
// onSaved: (val) => smsCode = val!,
|
||||
// ),
|
||||
// ),
|
||||
// // 获取验证码按钮
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// issmsCode = true;
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// _formKey.currentState!.save();
|
||||
// // 收回键盘
|
||||
// FocusScope.of(context).unfocus();
|
||||
// await GetServices().getsmsCode(phoneNumber);
|
||||
// startTimer(); // 开始定时器
|
||||
// }
|
||||
// },
|
||||
// child: Text(smsText),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(height: 16.0),
|
||||
|
||||
// // 登录按钮
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// issmsCode = false;
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// _formKey.currentState!.save();
|
||||
// // 表单校验通过,执行提交逻辑...
|
||||
// // 收回键盘
|
||||
// FocusScope.of(context).unfocus();
|
||||
// var res = await GetServices()
|
||||
// .phoneLogin(phoneNumber, smsCode);
|
||||
// setState(() {
|
||||
// if (res['code'] != 1000) {
|
||||
// showErrorSnackbar(
|
||||
// _scaffoldKey.currentContext!, res["message"]);
|
||||
// } else {
|
||||
// loginPrefs.savePhone(phoneNumber);
|
||||
// loginPrefs.saveExpire(res["data"]["expire"]);
|
||||
// loginPrefs.saveToken(res["data"]["token"]);
|
||||
// Navigator.pushNamed(
|
||||
// _scaffoldKey.currentContext!, 'home'); //跳转至首页
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// child: const Text('登录'),
|
||||
// ),
|
||||
// ],
|
||||
// )),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
class PhoneLoginController extends GetxController {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
LoginPrefs loginPrefs = LoginPrefs();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final phoneNumber = ''.obs;
|
||||
final smsCode = ''.obs;
|
||||
final issmsCode = false.obs;
|
||||
final smsText = '获取验证码'.obs;
|
||||
final _seconds = 60.obs;
|
||||
late Timer _timer;
|
||||
|
||||
phoneNumber = loginPrefs.getPhone();
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
phoneNumber.value = LoginPrefs().getPhone();
|
||||
}
|
||||
|
||||
void startTimer() {
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (_seconds > 0) {
|
||||
_seconds -= 1;
|
||||
smsText = "重新获取(${_seconds}s)";
|
||||
if (_seconds.value > 0) {
|
||||
_seconds.value -= 1;
|
||||
smsText.value = "重新获取(${_seconds.value}s)";
|
||||
} else {
|
||||
_timer.cancel(); // 到0时关闭定时器
|
||||
smsText = "获取验证码";
|
||||
smsText.value = "获取验证码";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showErrorSnackbar(BuildContext context, String text) {
|
||||
void showErrorSnackbar(String text) {
|
||||
final snackBar = SnackBar(
|
||||
content: Text(text),
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
ScaffoldMessenger.of(Get.context!).showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
Future<void> getSmsCode() async {
|
||||
issmsCode.value = true;
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
// 收回键盘
|
||||
FocusScope.of(Get.context!).unfocus();
|
||||
await GetServices().getsmsCode(phoneNumber.value);
|
||||
startTimer(); // 开始定时器
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> login() async {
|
||||
issmsCode.value = false;
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
// 表单校验通过,执行提交逻辑...
|
||||
// 收回键盘
|
||||
FocusScope.of(Get.context!).unfocus();
|
||||
var res =
|
||||
await GetServices().phoneLogin(phoneNumber.value, smsCode.value);
|
||||
if (res['code'] != 1000) {
|
||||
showErrorSnackbar(res["message"]);
|
||||
} else {
|
||||
LoginPrefs().savePhone(phoneNumber.value);
|
||||
LoginPrefs().saveExpire(res["data"]["expire"]);
|
||||
LoginPrefs().saveToken(res["data"]["token"]);
|
||||
Get.offNamed('home'); // 跳转至首页
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PhoneLoginPage extends GetView<PhoneLoginController> {
|
||||
const PhoneLoginPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
key: _scaffoldKey,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Form(
|
||||
key: _formKey,
|
||||
child:
|
||||
// 手机号输入框
|
||||
Column(
|
||||
key: controller._formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
// 手机号输入框
|
||||
TextFormField(
|
||||
maxLength: 11,
|
||||
initialValue: phoneNumber,
|
||||
initialValue: controller.phoneNumber.value,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '手机号',
|
||||
),
|
||||
@ -312,7 +716,8 @@ class _PhoneLoginPageState extends State<PhoneLoginPage> {
|
||||
|
||||
return str == "" ? null : str;
|
||||
},
|
||||
onSaved: (String? value) => phoneNumber = value!,
|
||||
onSaved: (String? value) =>
|
||||
controller.phoneNumber.value = value!,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
@ -329,27 +734,21 @@ class _PhoneLoginPageState extends State<PhoneLoginPage> {
|
||||
str = '验证码不能为空';
|
||||
}
|
||||
|
||||
if (issmsCode) {
|
||||
if (controller.issmsCode.value) {
|
||||
return null;
|
||||
}
|
||||
return str == "" ? null : str;
|
||||
},
|
||||
onSaved: (val) => smsCode = val!,
|
||||
onSaved: (String? value) =>
|
||||
controller.smsCode.value = value!,
|
||||
),
|
||||
),
|
||||
// 获取验证码按钮
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
issmsCode = true;
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
// 收回键盘
|
||||
FocusScope.of(context).unfocus();
|
||||
await GetServices().getsmsCode(phoneNumber);
|
||||
startTimer(); // 开始定时器
|
||||
}
|
||||
controller.getSmsCode();
|
||||
},
|
||||
child: Text(smsText),
|
||||
child: Obx(() => Text(controller.smsText.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -358,32 +757,13 @@ class _PhoneLoginPageState extends State<PhoneLoginPage> {
|
||||
// 登录按钮
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
issmsCode = false;
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
// 表单校验通过,执行提交逻辑...
|
||||
// 收回键盘
|
||||
FocusScope.of(context).unfocus();
|
||||
var res = await GetServices()
|
||||
.phoneLogin(phoneNumber, smsCode);
|
||||
setState(() {
|
||||
if (res['code'] != 1000) {
|
||||
showErrorSnackbar(
|
||||
_scaffoldKey.currentContext!, res["message"]);
|
||||
} else {
|
||||
loginPrefs.savePhone(phoneNumber);
|
||||
loginPrefs.saveExpire(res["data"]["expire"]);
|
||||
loginPrefs.saveToken(res["data"]["token"]);
|
||||
Navigator.pushNamed(
|
||||
_scaffoldKey.currentContext!, 'home'); //跳转至首页
|
||||
}
|
||||
});
|
||||
}
|
||||
controller.login();
|
||||
},
|
||||
child: const Text('登录'),
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'package:cpnav/models/user.dart';
|
||||
import 'package:cpnav/pages/login/user.dart';
|
||||
|
||||
class LoginPrefs extends GetxController {
|
||||
static const String expireStr = "expire"; //用户名
|
||||
|
48
lib/pages/login/my_routes.dart
Normal file
48
lib/pages/login/my_routes.dart
Normal file
@ -0,0 +1,48 @@
|
||||
//配置路由
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../main.dart';
|
||||
import 'login_page.dart';
|
||||
import 'loginprefs.dart';
|
||||
|
||||
/*
|
||||
* 这个方法是固定写法,功能就像是一个拦截器。
|
||||
*/
|
||||
Route<dynamic>? onGenerateRoute(RouteSettings settings) {
|
||||
Map<String, Widget> routes = {
|
||||
'home': MyHomePage(title: 'Flutter Demo Home Page'), //定义app路径
|
||||
'login': const Login(), //定义login路径
|
||||
};
|
||||
|
||||
String routerName = routeBeforeHook(settings);
|
||||
bool mathMap = false;
|
||||
Route<dynamic>? mathWidget;
|
||||
routes.forEach((key, v) {
|
||||
if (key == routerName) {
|
||||
mathMap = true;
|
||||
mathWidget = MaterialPageRoute(builder: (BuildContext context) => v);
|
||||
}
|
||||
});
|
||||
|
||||
if (mathMap) {
|
||||
return mathWidget;
|
||||
}
|
||||
return MaterialPageRoute(
|
||||
builder: (BuildContext context) => const Text('404'));
|
||||
}
|
||||
|
||||
String routeBeforeHook(RouteSettings settings) {
|
||||
if (checkToken() == false) {
|
||||
return 'login';
|
||||
} else {
|
||||
return settings.name!;
|
||||
}
|
||||
}
|
||||
|
||||
bool checkToken() {
|
||||
LoginPrefs loginPrefs = LoginPrefs();
|
||||
String token = loginPrefs.getToken();
|
||||
if ('' != token) return true;
|
||||
return false;
|
||||
}
|
@ -2,7 +2,8 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/http.dart';
|
||||
import 'loginprefs.dart';
|
||||
|
||||
import '../pages/login/loginprefs.dart';
|
||||
|
||||
LoginPrefs loginPrefs = LoginPrefs();
|
||||
|
||||
|
@ -1,74 +0,0 @@
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'package:cpnav/models/user.dart';
|
||||
|
||||
class LoginPrefs {
|
||||
static const String expireStr = "expire"; //用户名
|
||||
static const String tokenStr = "token"; //token
|
||||
static const String phoneStr = "phone";
|
||||
final box = GetStorage(); // 实例化 GetStorage
|
||||
|
||||
Future<String> init() async {
|
||||
await GetStorage.init(); // 初始化 GetStorage
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
void saveExpire(int expire) {
|
||||
box.write(expireStr, expire);
|
||||
// update();
|
||||
}
|
||||
|
||||
int getExpire() {
|
||||
return box.read(expireStr) ?? 0;
|
||||
}
|
||||
|
||||
void saveToken(String token) {
|
||||
box.write(tokenStr, token);
|
||||
// update();
|
||||
}
|
||||
|
||||
String getToken() {
|
||||
return box.read(tokenStr) ?? "";
|
||||
}
|
||||
|
||||
void removeExpire() {
|
||||
box.remove(expireStr);
|
||||
// update();
|
||||
}
|
||||
|
||||
void removeToken() {
|
||||
box.remove(tokenStr);
|
||||
// update();
|
||||
}
|
||||
|
||||
void savePhone(String phone) {
|
||||
box.write(phoneStr, phone);
|
||||
// update();
|
||||
}
|
||||
|
||||
String getPhone() {
|
||||
return box.read(phoneStr) ?? "";
|
||||
}
|
||||
|
||||
void clearLogin() {
|
||||
box.erase(); // 清除所有数据
|
||||
// update();
|
||||
}
|
||||
}
|
||||
|
||||
class UserController {
|
||||
final box = GetStorage(); // 实例化 GetStorage
|
||||
|
||||
UserModel? getUser() {
|
||||
final userMap = box.read('user');
|
||||
if (userMap != null) {
|
||||
return UserModel.fromJson(userMap);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void setUser(Map user) {
|
||||
box.write('user', user);
|
||||
// update();
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'package:cpnav/models/user.dart';
|
||||
|
||||
class LoginPrefs extends GetxController {
|
||||
static const String expireStr = "expire"; //用户名
|
||||
static const String tokenStr = "token"; //token
|
||||
static const String phoneStr = "phone";
|
||||
final box = GetStorage(); // 实例化 GetStorage
|
||||
|
||||
Future<String> init() async {
|
||||
await GetStorage.init(); // 初始化 GetStorage
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
void saveExpire(int expire) {
|
||||
box.write(expireStr, expire);
|
||||
update();
|
||||
}
|
||||
|
||||
int getExpire() {
|
||||
return box.read(expireStr) ?? 0;
|
||||
}
|
||||
|
||||
void saveToken(String token) {
|
||||
box.write(tokenStr, token);
|
||||
update();
|
||||
}
|
||||
|
||||
String getToken() {
|
||||
return box.read(tokenStr) ?? "";
|
||||
}
|
||||
|
||||
void removeExpire() {
|
||||
box.remove(expireStr);
|
||||
update();
|
||||
}
|
||||
|
||||
void removeToken() {
|
||||
box.remove(tokenStr);
|
||||
update();
|
||||
}
|
||||
|
||||
void savePhone(String phone) {
|
||||
box.write(phoneStr, phone);
|
||||
update();
|
||||
}
|
||||
|
||||
String getPhone() {
|
||||
return box.read(phoneStr) ?? "";
|
||||
}
|
||||
|
||||
void clearLogin() {
|
||||
box.erase(); // 清除所有数据
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
class UserController extends GetxController {
|
||||
final box = GetStorage(); // 实例化 GetStorage
|
||||
|
||||
UserModel? getUser() {
|
||||
final userMap = box.read('user');
|
||||
if (userMap != null) {
|
||||
return UserModel.fromJson(userMap);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void setUser(Map user) {
|
||||
box.write('user', user);
|
||||
update();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user