Files
ln-ios/ln_jq_app/lib/pages/login/view.dart
2025-11-07 18:08:41 +08:00

354 lines
12 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:convert';
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; // 默认密码为隐藏状态
@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);
});
}
@override
void dispose() {
tabController.dispose(); // 销毁 TabController
super.dispose();
}
// 主视图
Widget _buildView() {
// 使用 Get.find 获取控制器
final controller = Get.find<LoginController>();
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 ? 260.h : 320.h,
padding: EdgeInsets.all(15),
child: // TabBar切换
Column(
children: [
Card(
elevation: 2,
child: Padding(
padding: EdgeInsets.all(3),
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), // 卡片的圆角效果
boxShadow: [
BoxShadow(
color: Colors.blue.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 6,
),
],
),
tabs: [
Tab(text: '司机端登录'),
Tab(text: '加氢站登录'),
],
isScrollable: false,
),
),
),
// 根据选择的Tab展示不同的输入框
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,
decoration: InputDecoration(
hintText: '请输入身份后8位',
border: OutlineInputBorder(),
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",
);
dismissLoading();
showToast('登录成功,欢迎您');
// 跳转到主页,并清除所有历史页面
Get.offAll(() => BaseWidgetsPage());
} catch (e) {
// 如果解析 JSON 失败
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,
decoration: InputDecoration(
hintText: '请输入加氢站编号',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person_2_outlined, color: Colors.grey),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: AppTheme.themeColor),
),
),
),
SizedBox(height: 20),
TextFormField(
controller: controller.passwordController,
obscureText: _obscureText,
cursorColor: AppTheme.themeColor,
decoration: InputDecoration(
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: 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;
//todo 删除
account = "000017";
password = "LnQn.314000";
if (account.isEmpty || password.isEmpty) {
showToast("请输入账号和密码");
return;
}
showLoading('登录中...');
try {
// 对密码进行AES加密
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'] ?? '';
//hydrogenId
String userId = result.data['userId'] ?? '';
await StorageService.to.saveLoginInfo(
token: token,
userId: userId,
channel: "station",
);
dismissLoading();
showToast('登录成功,欢迎您');
// 跳转到主页,并清除所有历史页面
Get.offAll(() => B_BaseWidgetsPage());
} catch (e) {
// 如果解析 JSON 失败
dismissLoading();
showToast('登录失败:数据异常');
}
} catch (e) {
dismissLoading();
}
},
child: Text('登录'),
),
],
);
}
@override
Widget build(BuildContext context) {
return GetBuilder<LoginController>(
init: LoginController(),
id: 'login',
builder: (_) {
return Scaffold(body: _buildView());
},
);
}
}