import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:lszlgl/base/base_lifecycle_state.dart'; import 'package:lszlgl/main.dart'; import 'package:lszlgl/model/req/login_req.dart'; import 'package:lszlgl/network/my_api.dart'; import 'package:lszlgl/service/dict_service.dart'; import 'package:lszlgl/service/upgrade_service.dart'; import 'package:lszlgl/service/user_service.dart'; import 'package:lszlgl/widget/button.dart'; import '../../config/reresh_config.dart'; import '../../network/base_dio.dart'; import '../../utils/location_utils.dart'; import '../../utils/sp_utils.dart'; import 'package:lszlgl/service/print_service.dart'; /// 登录页面 class LoginPage extends StatefulWidget { const LoginPage({Key? key}) : super(key: key); @override State createState() => _LoginPageState(); } class _LoginPageState extends BaseLifecycleState { late TextEditingController accountCtrl; late TextEditingController pwdCtrl; late ValueNotifier _showPwd; void onLogin() async { var account = accountCtrl.text; var pwd = pwdCtrl.text; if (account.isEmpty || pwd.isEmpty) { MyNavigator.showToast('请输入账号和密码'); return; } MyNavigator.showLoading(); try { // 登录 var login = await MyApi.get().login(LoginReq(username: account, password: pwd)); if (login.data == null) { MyNavigator.showToast('获取数据失败'); MyNavigator.dismissLoading(); return; } await UserService.get().saveLogin(login.data); getSystemData(); } on DioException catch (_) { } catch (e) { logger.e(e); MyNavigator.showToast('获取数据失败'); } MyNavigator.dismissLoading(); } /// 获取基础数据 void getSystemData() async { MyNavigator.showLoading(clickDismiss: false); try { // 获取用户数据 var user = await MyApi.get().userProfile(); await UserService.get().saveUser(user.data); // 获取字典 var dictData = await MyApi.get().getAllDict(); DictService.saveDictList(dictData.data); UpgradeService.checkUpgrade(false); // 进入主页 MyNavigator.dismissLoading(); startHome(); } on DioException catch (_) { } on Exception catch (a, _) { logger.e('$a'); MyNavigator.showToast('获取数据失败'); } MyNavigator.dismissLoading(); } /// 进入主页 void startHome() { var login = UserService.get().getLogin()!; if (login.defaultPassword ?? false) { MyNavigator.showToast('密码强度过低,请修改密码'); // 修改密码 MyRouter.startChangePwd(startHome: true); } else { // 进入主页 MyRouter.startMain(popAll: true); } } @override void onInit() { accountCtrl = TextEditingController(); pwdCtrl = TextEditingController(); _showPwd = ValueNotifier(true); } @override void onFirstShow(Duration timeStamp) async { // MyNavigator.showLoading(); /// 初始化基础库 start BaseDio.get().init(); await SPUtils.getInstance().init(); RefreshConfig.get().initDefault(); LocationUtils.updatePrivacyShow(true, true); LocationUtils.updatePrivacyAgree(true); LocationUtils.setApiKey( kReleaseMode ? '2c783509376e267b24d63b21681686fa' : '7d0c033909f84adc14a0e60a835f044f', ''); /// 获取手机设备信息 PrintService.getDeviceInfo(); /// 同步数据库里的蓝牙设备信息到服务器 database.savaBleDataToServer(); /// 初始化基础库 end MyNavigator.dismissLoading(); // 已登录 if (UserService.get().getLogin() != null) { getSystemData(); } } @override void onDestroy() { accountCtrl.dispose(); pwdCtrl.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF49AAF2), body: KeyboardDismissOnTap( child: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Stack( children: [ Positioned.fill(child: Image.asset(imgLoginBg, fit: BoxFit.fill)), SizedBox( height: MediaQuery.of(context).size.height, child: buildBody(), ), ], ), ), ), ); } Widget buildBody() { return Column( children: [ const Spacer(flex: 3), Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 48), child: Image.asset(imgLoginTitle, fit: BoxFit.fill), ), const Spacer(), loginContainer(), const Spacer(flex: 7), ], ); } Widget loginContainer() { return SizedBox( width: double.infinity, child: Stack( alignment: Alignment.topCenter, children: [ buildInputContent(), userTitle(), ], ), ); } Widget userTitle() { return Row( children: [ const Spacer(), Expanded( child: Container( padding: const EdgeInsets.symmetric(vertical: 12), alignment: Alignment.center, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(100)), border: Border.fromBorderSide(BorderSide(color: Color(0xFF49AAF2), width: 1)), boxShadow: [BoxShadow(color: Color(0x941C90FF), offset: Offset(0, 2))], ), child: const Text( '用户登录', style: TextStyle(color: Color(0xFF1187DE), fontSize: 14), ), ), ), const Spacer(), ], ); } Widget buildInputContent() { return Container( margin: const EdgeInsets.only(top: 18, left: 16, right: 16), padding: const EdgeInsets.all(6), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: const BorderRadius.all(Radius.circular(36)), ), child: Container( padding: const EdgeInsets.symmetric(horizontal: 24), alignment: Alignment.center, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(32))), child: Column( children: [ const SizedBox(height: 56), buildEdit( ctrl: accountCtrl, hint: '请输入登录账号', icon: imgLoginAccount, action: TextInputAction.next, ), const SizedBox(height: 32), ValueListenableBuilder( valueListenable: _showPwd, builder: (BuildContext ctx, bool show, Widget? child) { return buildEdit( ctrl: pwdCtrl, hint: '请输入登录密码', icon: imgLoginPwd, obscure: show, onSubmit: (value) => onLogin(), rightIcon: child, ); }, child: IconButton( icon: const Icon(Icons.remove_red_eye_outlined, size: 16, color: Color(0xFFBBBBBB)), onPressed: () { _showPwd.value = !_showPwd.value; }, )), const SizedBox(height: 44), buildLoginBtn(), SizedBox( width: double.infinity, child: TextButton( onPressed: () { MyRouter.forgetPwd(); }, style: const ButtonStyle(alignment: Alignment.centerRight), child: const Text('忘记密码', style: TextStyle(color: Color(0xFF25A6EE), fontSize: 14))), ), const SizedBox(height: 18), ], ), ), ); } Widget buildEdit({ required TextEditingController ctrl, required String hint, String? icon, TextInputAction action = TextInputAction.done, bool obscure = false, ValueChanged? onSubmit, Widget? rightIcon, }) { return TextField( controller: ctrl, decoration: InputDecoration( prefixIcon: icon == null ? null : Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), child: Image.asset(icon, height: 18), ), prefixIconConstraints: const BoxConstraints(), border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(100))), enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Color(0xFFE6E6E6), width: 1), borderRadius: BorderRadius.all(Radius.circular(100)), ), hintText: hint, hintStyle: const TextStyle(color: Color(0xFFBBBBBB)), isDense: true, contentPadding: EdgeInsets.zero, suffixIcon: rightIcon, ), style: const TextStyle(fontSize: 14), textInputAction: action, obscureText: obscure, onSubmitted: onSubmit, ); } Widget buildLoginBtn() { return MyButton( '登录', onTap: onLogin, gradient: const LinearGradient(colors: [Color(0xFF60B5F4), Color(0xFF62A4D6)]), ); } }