diff --git a/ln_jq_app/lib/pages/login/view.dart b/ln_jq_app/lib/pages/login/view.dart index c101a8c..d47b141 100644 --- a/ln_jq_app/lib/pages/login/view.dart +++ b/ln_jq_app/lib/pages/login/view.dart @@ -18,25 +18,26 @@ class LoginPage extends StatefulWidget { class _LoginPageState extends State with SingleTickerProviderStateMixin { late TabController tabController; - //默认司机端 bool cLogin = true; - bool _obscureText = true; // 默认密码为隐藏状态 + bool _obscureText = true; + // 用于管理“记住密码”的复选框状态 + bool _rememberPassword = true; + // 用于确保凭证只在首次加载时回填一次 + bool _credentialsLoaded = false; + @override void initState() { super.initState(); - // 初始化 TabController,传入 vsync 参数 tabController = TabController(length: 2, vsync: this); tabController.addListener(_tabChangeListener); } void _tabChangeListener() { - // 如果 TabController 不是正在被用户手动滑动(即是初始化或其他操作) if (!tabController.indexIsChanging) { switchTab(tabController.index); } } - // 切换Tab void switchTab(int index) { setState(() { cLogin = (index == 0); @@ -45,14 +46,22 @@ class _LoginPageState extends State with SingleTickerProviderStateMix @override void dispose() { - tabController.dispose(); // 销毁 TabController + tabController.dispose(); super.dispose(); } - // 主视图 - Widget _buildView() { - // 使用 Get.find 获取控制器 - final controller = Get.find(); + Widget _buildView(LoginController controller) { + // 在视图构建时,检查并回填已保存的凭证 + if (!_credentialsLoaded) { + final savedAccount = StorageService.to.stationAccount; + final savedPassword = StorageService.to.stationPassword; + if (savedAccount != null && savedPassword != null) { + controller.stationIdController.text = savedAccount; + controller.passwordController.text = savedPassword; + _rememberPassword = true; // 如果有保存的密码,则默认勾选 + } + _credentialsLoaded = true; // 标记为已加载,防止重复执行 + } return Container( color: Color(0xFFEFF4F7), @@ -69,10 +78,9 @@ class _LoginPageState extends State with SingleTickerProviderStateMix margin: EdgeInsets.all(15), elevation: 4, child: Container( - height: cLogin ? 285.h : 350.h, + height: cLogin ? 285.h : 360.h, padding: EdgeInsets.all(15), - child: // TabBar切换 - Column( + child: Column( children: [ Card( elevation: 2, @@ -82,19 +90,15 @@ class _LoginPageState extends State with SingleTickerProviderStateMix child: TabBar( controller: tabController, onTap: (index) { - //保证尺寸变化 delayed(300, () { switchTab(index); }); }, - // 修改TabBar的选中状态和未选中状态样式 labelColor: Colors.white, - // 选中时的文字颜色 unselectedLabelColor: Colors.black, - // 未选中时的文字颜色 indicator: BoxDecoration( - color: AppTheme.themeColor, // 选中的Tab背景色(模拟卡片式效果) - borderRadius: BorderRadius.circular(12), // 卡片的圆角效果 + color: AppTheme.themeColor, + borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.blue.withOpacity(0.2), @@ -111,14 +115,11 @@ class _LoginPageState extends State with SingleTickerProviderStateMix ), ), ), - // 根据选择的Tab展示不同的输入框 Flexible( child: TabBarView( controller: tabController, children: [ - // 司机端登录 _driverLoginView(controller), - // 加氢站登录 _stationLoginView(controller), ], ), @@ -131,7 +132,6 @@ class _LoginPageState extends State with SingleTickerProviderStateMix ); } - // 司机端登录界面 Widget _driverLoginView(LoginController controller) { return !cLogin ? SizedBox() @@ -158,44 +158,28 @@ class _LoginPageState extends State with SingleTickerProviderStateMix SizedBox(height: 20.h), ElevatedButton( onPressed: () async { - // 司机端登录 String password = controller.driverIdentityController.text; - if (password.isEmpty) { showToast("请输入密码"); return; } - showLoading('登录中...'); - try { - // 调用登录接口 var responseData = await HttpService.to.post( 'appointment/login/loginForDriver', data: {'idNo': password}, ); - if (responseData == null && responseData!.data == null) { dismissLoading(); showToast('登录失败:无法获取凭证'); return; } - try { var result = BaseModel.fromJson(responseData.data); - - //保存用户信息 String token = result.data['token'] ?? ''; String idCard = result.data['idCard'] ?? ''; String name = result.data['name'] ?? ''; String phone = result.data['phone'] ?? ''; - /*{ - "token": "a615cf38a066473ebf8e9a956fc51928", - "idCard": "330324200010241024", - "name": "王小龙", - "phone": "15888331828" - }*/ - await StorageService.to.saveLoginInfo( token: token, userId: "", @@ -204,14 +188,10 @@ class _LoginPageState extends State with SingleTickerProviderStateMix name: name, phone: phone, ); - dismissLoading(); showToast('登录成功,欢迎您'); - - // 跳转到主页,并清除所有历史页面 Get.offAll(() => BaseWidgetsPage()); } catch (e) { - // 如果解析 JSON 失败 dismissLoading(); showToast('登录失败:数据异常'); } @@ -221,7 +201,7 @@ class _LoginPageState extends State with SingleTickerProviderStateMix }, style: ElevatedButton.styleFrom( backgroundColor: AppTheme.themeColor, - minimumSize: Size(double.infinity, 50), // 设置按钮宽度占满,指定最小高度 + minimumSize: Size(double.infinity, 50), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: Text('登录'), @@ -230,7 +210,6 @@ class _LoginPageState extends State with SingleTickerProviderStateMix ); } - // 加氢站登录界面 Widget _stationLoginView(LoginController controller) { return cLogin ? SizedBox() @@ -253,7 +232,7 @@ class _LoginPageState extends State with SingleTickerProviderStateMix ), ), ), - SizedBox(height: 20), + SizedBox(height: 10), TextFormField( controller: controller.passwordController, obscureText: _obscureText, @@ -266,7 +245,7 @@ class _LoginPageState extends State with SingleTickerProviderStateMix border: OutlineInputBorder(), suffixIcon: IconButton( icon: Icon( - _obscureText ? Icons.visibility_off : Icons.visibility, // 切换图标 + _obscureText ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() { @@ -280,22 +259,40 @@ class _LoginPageState extends State with SingleTickerProviderStateMix ), ), ), - SizedBox(height: 20), + SizedBox(height: 10), + //记住密码复选框 --- + Row( + children: [ + SizedBox( + height: 24, + width: 24, + child: Checkbox( + value: _rememberPassword, + activeColor: AppTheme.themeColor, + onChanged: (bool? value) { + setState(() { + _rememberPassword = value ?? true; + }); + }, + ), + ), + GestureDetector( + onTap: () => setState(() => _rememberPassword = !_rememberPassword), + child: const Text('记住密码', style: TextStyle(color: Colors.grey)), + ) + ], + ), + SizedBox(height: 20), // 调整间距 ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppTheme.themeColor, - minimumSize: Size(double.infinity, 50), // 设置按钮宽度占满,指定最小高度 + minimumSize: Size(double.infinity, 50), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), onPressed: () async { - // 加氢站登录逻辑 String account = controller.stationIdController.text; String password = controller.passwordController.text; - - //todo 删除 - account = "000017"; - password = "LnQn.314000"; - + if (account.isEmpty || password.isEmpty) { showToast("请输入账号和密码"); return; @@ -304,10 +301,7 @@ class _LoginPageState extends State with SingleTickerProviderStateMix showLoading('登录中...'); try { - // 对密码进行AES加密 String encryptedPassword = LoginUtil.encrypt(password); - - // 调用登录接口 var responseData = await HttpService.to.post( '/login/password', data: { @@ -325,10 +319,7 @@ class _LoginPageState extends State with SingleTickerProviderStateMix try { var result = BaseModel.fromJson(responseData.data); - - //保存用户信息 String token = result.data['token'] ?? ''; - //hydrogenId String userId = result.data['userId'] ?? ''; await StorageService.to.saveLoginInfo( @@ -337,13 +328,17 @@ class _LoginPageState extends State with SingleTickerProviderStateMix channel: "station", ); + // 根据复选框状态保存或清除密码 --- + if (_rememberPassword) { + await StorageService.to.saveStationCredentials(account, password); + } else { + await StorageService.to.clearStationCredentials(); + } + dismissLoading(); showToast('登录成功,欢迎您'); - - // 跳转到主页,并清除所有历史页面 Get.offAll(() => B_BaseWidgetsPage()); } catch (e) { - // 如果解析 JSON 失败 dismissLoading(); showToast('登录失败:数据异常'); } @@ -362,8 +357,8 @@ class _LoginPageState extends State with SingleTickerProviderStateMix return GetBuilder( init: LoginController(), id: 'login', - builder: (_) { - return Scaffold(body: _buildView()); + builder: (controller) { + return Scaffold(body: _buildView(controller)); }, ); } diff --git a/ln_jq_app/lib/storage_service.dart b/ln_jq_app/lib/storage_service.dart index f614f0e..44f8634 100644 --- a/ln_jq_app/lib/storage_service.dart +++ b/ln_jq_app/lib/storage_service.dart @@ -19,41 +19,40 @@ class StorageService extends GetxService { static const String _nameKey = 'user_name'; static const String _phoneKey = 'user_phone'; static const String _idCardKey = 'user_id_card'; - // 车辆信息的键名 static const String _vehicleInfoKey = 'vehicle_info'; + // 加氢站登录凭证的键名 + static const String _stationAccountKey = 'station_account'; + static const String _stationPasswordKey = 'station_password'; + - // 提供一个静态的 'to' 方法,方便全局访问 static StorageService get to => Get.find(); - // Service 初始化 Future init() async { _box = GetStorage(); return this; } - /// --- Getter 方法,用于读取状态 --- - + // --- Getters --- bool get isLoggedIn => _box.read(_tokenKey)?.isNotEmpty ?? false; String? get token => _box.read(_tokenKey); String? get userId => _box.read(_userIdKey); String? get name => _box.read(_nameKey); String? get phone => _box.read(_phoneKey); String? get idCard => _box.read(_idCardKey); - - /// 判断是否已有车辆信息缓存 bool get hasVehicleInfo => _box.hasData(_vehicleInfoKey); - /// 获取已缓存的车辆信息 + // 记住密码:获取加氢站账号和密码 + String? get stationAccount => _box.read(_stationAccountKey); + String? get stationPassword => _box.read(_stationPasswordKey); + VehicleInfo? get vehicleInfo { final vehicleJson = _box.read(_vehicleInfoKey); if (vehicleJson != null) { - // 使用我们之前创建的辅助函数来解析 return vehicleInfoFromJson(vehicleJson); } return null; } - ///获取当前登录渠道 LoginChannel get loginChannel { final channelString = _box.read(_channelKey); if (channelString == 'station') { @@ -64,7 +63,7 @@ class StorageService extends GetxService { return LoginChannel.none; } - /// --- 操作方法 --- + // --- Methods --- Future saveLoginInfo({ required String token, required String userId, @@ -81,18 +80,26 @@ class StorageService extends GetxService { await _box.write(_idCardKey, idCard); } - /// 保存车辆信息 Future saveVehicleInfo(VehicleInfo data) async { - // 使用辅助函数将对象转换为 JSON 字符串并保存 await _box.write(_vehicleInfoKey, vehicleInfoToJson(data)); } - /// 清除车辆信息 + // 保存加氢站登录凭证 + Future saveStationCredentials(String account, String password) async { + await _box.write(_stationAccountKey, account); + await _box.write(_stationPasswordKey, password); + } + Future clearVehicleInfo() async { await _box.remove(_vehicleInfoKey); } - /// 删除用户信息 (登出) + // 清除加氢站登录凭证 + Future clearStationCredentials() async { + await _box.remove(_stationAccountKey); + await _box.remove(_stationPasswordKey); + } + Future clearLoginInfo() async { await _box.remove(_tokenKey); await _box.remove(_userIdKey); @@ -100,7 +107,7 @@ class StorageService extends GetxService { await _box.remove(_nameKey); await _box.remove(_phoneKey); await _box.remove(_idCardKey); - // 登出时一并清除车辆信息 await clearVehicleInfo(); + // 注意:登出时我们不清除“记住的密码”,以便下次用户登录时仍然可以回填 } }