366 lines
14 KiB
Dart
366 lines
14 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:getx_scaffold/getx_scaffold.dart';
|
|
import 'package:ln_jq_app/common/login_util.dart';
|
|
import 'package:ln_jq_app/common/model/base_model.dart';
|
|
import 'package:ln_jq_app/common/styles/theme.dart';
|
|
import 'package:ln_jq_app/pages/b_page/base_widgets/view.dart';
|
|
import 'package:ln_jq_app/pages/c_page/base_widgets/view.dart';
|
|
import 'package:ln_jq_app/pages/login/controller.dart';
|
|
import 'package:ln_jq_app/storage_service.dart';
|
|
|
|
class LoginPage extends StatefulWidget {
|
|
const LoginPage({super.key});
|
|
|
|
@override
|
|
State<LoginPage> createState() => _LoginPageState();
|
|
}
|
|
|
|
class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMixin {
|
|
late TabController tabController;
|
|
|
|
bool cLogin = true;
|
|
bool _obscureText = true;
|
|
// 用于管理“记住密码”的复选框状态
|
|
bool _rememberPassword = true;
|
|
// 用于确保凭证只在首次加载时回填一次
|
|
bool _credentialsLoaded = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
tabController = TabController(length: 2, vsync: this);
|
|
tabController.addListener(_tabChangeListener);
|
|
}
|
|
|
|
void _tabChangeListener() {
|
|
if (!tabController.indexIsChanging) {
|
|
switchTab(tabController.index);
|
|
}
|
|
}
|
|
|
|
void switchTab(int index) {
|
|
setState(() {
|
|
cLogin = (index == 0);
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
tabController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
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),
|
|
child: <Widget>[
|
|
Icon(cLogin ? AntdIcon.car : AntdIcon.USB),
|
|
SizedBox(height: 5.h),
|
|
TextX.bodyLarge(cLogin ? '司机端' : "加氢站", weight: FontWeight.w700),
|
|
SizedBox(height: 5.h),
|
|
TextX.bodyLarge(cLogin ? '安全驾驶·智能服务' : "氢能服务·专业运营"),
|
|
Card(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(15), // 设置圆角弧度
|
|
),
|
|
margin: EdgeInsets.all(15),
|
|
elevation: 4,
|
|
child: Container(
|
|
height: cLogin ? 285.h : 360.h,
|
|
padding: EdgeInsets.all(15),
|
|
child: Column(
|
|
children: [
|
|
Card(
|
|
elevation: 2,
|
|
child: Container(
|
|
height: 55.h,
|
|
padding: EdgeInsets.all(3),
|
|
child: TabBar(
|
|
controller: tabController,
|
|
onTap: (index) {
|
|
delayed(300, () {
|
|
switchTab(index);
|
|
});
|
|
},
|
|
labelColor: Colors.white,
|
|
unselectedLabelColor: Colors.black,
|
|
indicator: BoxDecoration(
|
|
color: AppTheme.themeColor,
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.blue.withOpacity(0.2),
|
|
spreadRadius: 1,
|
|
blurRadius: 6,
|
|
),
|
|
],
|
|
),
|
|
tabs: [
|
|
Tab(text: '司机端登录'),
|
|
Tab(text: '加氢站登录'),
|
|
],
|
|
isScrollable: false,
|
|
),
|
|
),
|
|
),
|
|
Flexible(
|
|
child: TabBarView(
|
|
controller: tabController,
|
|
children: [
|
|
_driverLoginView(controller),
|
|
_stationLoginView(controller),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
].toColumn(mainAxisSize: MainAxisSize.min).center(),
|
|
);
|
|
}
|
|
|
|
Widget _driverLoginView(LoginController controller) {
|
|
return !cLogin
|
|
? SizedBox()
|
|
: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 20.h),
|
|
TextFormField(
|
|
controller: controller.driverIdentityController,
|
|
cursorColor: AppTheme.themeColor,
|
|
maxLength: 8,
|
|
style: TextStyle(fontSize: 14),
|
|
decoration: InputDecoration(
|
|
hintText: '请输入身份后8位',
|
|
border: OutlineInputBorder(),
|
|
hintStyle: TextStyle(fontSize: 14),
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
prefixIcon: Icon(Icons.person_2_outlined, color: Colors.grey),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(color: AppTheme.themeColor),
|
|
),
|
|
),
|
|
),
|
|
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'] ?? '';
|
|
await StorageService.to.saveLoginInfo(
|
|
token: token,
|
|
userId: "",
|
|
channel: "driver",
|
|
idCard: idCard,
|
|
name: name,
|
|
phone: phone,
|
|
);
|
|
dismissLoading();
|
|
showToast('登录成功,欢迎您');
|
|
Get.offAll(() => BaseWidgetsPage());
|
|
} catch (e) {
|
|
dismissLoading();
|
|
showToast('登录失败:数据异常');
|
|
}
|
|
} catch (e) {
|
|
dismissLoading();
|
|
}
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppTheme.themeColor,
|
|
minimumSize: Size(double.infinity, 50),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
),
|
|
child: Text('登录'),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _stationLoginView(LoginController controller) {
|
|
return cLogin
|
|
? SizedBox()
|
|
: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 20),
|
|
TextFormField(
|
|
controller: controller.stationIdController,
|
|
cursorColor: AppTheme.themeColor,
|
|
style: TextStyle(fontSize: 14),
|
|
decoration: InputDecoration(
|
|
hintText: '请输入加氢站编号',
|
|
border: OutlineInputBorder(),
|
|
hintStyle: TextStyle(fontSize: 14),
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
prefixIcon: Icon(Icons.person_2_outlined, color: Colors.grey),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(color: AppTheme.themeColor),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
TextFormField(
|
|
controller: controller.passwordController,
|
|
obscureText: _obscureText,
|
|
style: TextStyle(fontSize: 14),
|
|
cursorColor: AppTheme.themeColor,
|
|
decoration: InputDecoration(
|
|
hintStyle: TextStyle(fontSize: 14),
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
hintText: '请输入密码',
|
|
border: OutlineInputBorder(),
|
|
suffixIcon: IconButton(
|
|
icon: Icon(
|
|
_obscureText ? Icons.visibility_off : Icons.visibility,
|
|
),
|
|
onPressed: () {
|
|
setState(() {
|
|
_obscureText = !_obscureText;
|
|
});
|
|
},
|
|
),
|
|
prefixIcon: Icon(Icons.lock_outline, color: Colors.grey),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(color: AppTheme.themeColor),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
//记住密码复选框 ---
|
|
Row(
|
|
children: <Widget>[
|
|
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),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
),
|
|
onPressed: () async {
|
|
String account = controller.stationIdController.text;
|
|
String password = controller.passwordController.text;
|
|
|
|
if (account.isEmpty || password.isEmpty) {
|
|
showToast("请输入账号和密码");
|
|
return;
|
|
}
|
|
|
|
showLoading('登录中...');
|
|
|
|
try {
|
|
String encryptedPassword = LoginUtil.encrypt(password);
|
|
var responseData = await HttpService.to.post(
|
|
'/login/password',
|
|
data: {
|
|
'account': account,
|
|
'password': encryptedPassword,
|
|
'loginType': "station",
|
|
},
|
|
);
|
|
|
|
if (responseData == null && responseData!.data == null) {
|
|
dismissLoading();
|
|
showToast('登录失败:无法获取凭证');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
var result = BaseModel.fromJson(responseData.data);
|
|
String token = result.data['token'] ?? '';
|
|
String userId = result.data['userId'] ?? '';
|
|
|
|
await StorageService.to.saveLoginInfo(
|
|
token: token,
|
|
userId: userId,
|
|
channel: "station",
|
|
);
|
|
|
|
// 根据复选框状态保存或清除密码 ---
|
|
if (_rememberPassword) {
|
|
await StorageService.to.saveStationCredentials(account, password);
|
|
} else {
|
|
await StorageService.to.clearStationCredentials();
|
|
}
|
|
|
|
dismissLoading();
|
|
showToast('登录成功,欢迎您');
|
|
Get.offAll(() => B_BaseWidgetsPage());
|
|
} catch (e) {
|
|
dismissLoading();
|
|
showToast('登录失败:数据异常');
|
|
}
|
|
} catch (e) {
|
|
dismissLoading();
|
|
}
|
|
},
|
|
child: Text('登录'),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GetBuilder<LoginController>(
|
|
init: LoginController(),
|
|
id: 'login',
|
|
builder: (controller) {
|
|
return Scaffold(body: _buildView(controller));
|
|
},
|
|
);
|
|
}
|
|
}
|