扫码结果处理

This commit is contained in:
2025-11-13 15:56:05 +08:00
parent 5c79a27ac4
commit feedc8c511
5 changed files with 139 additions and 55 deletions

View File

@@ -0,0 +1,52 @@
import 'dart:convert';
// 将 JSON 字符串转换为 VehicleInfo 对象的辅助函数
VehicleInfo vehicleInfoFromJson(String str) => VehicleInfo.fromJson(json.decode(str));
// 将 VehicleInfo 对象转换为 JSON 字符串的辅助函数
String vehicleInfoToJson(VehicleInfo data) => json.encode(data.toJson());
/// 车辆信息数据模型
class VehicleInfo {
final String plateNumber;
final String vin;
final String modelName;
final String brandName;
final String engineNum;
final String truckNum;
final num hydrogenCapacity;
final num maxHydrogen;
VehicleInfo({
required this.plateNumber,
required this.vin,
required this.modelName,
required this.brandName,
required this.engineNum,
required this.truckNum,
required this.hydrogenCapacity,
required this.maxHydrogen,
});
factory VehicleInfo.fromJson(Map<String, dynamic> json) => VehicleInfo(
plateNumber: json["plateNumber"] ?? '',
vin: json["vin"] ?? '',
modelName: json["modelName"] ?? '',
brandName: json["brandName"] ?? '',
engineNum: json["engineNum"] ?? '',
truckNum: json["truckNum"] ?? '',
hydrogenCapacity: json["hydrogenCapacity"] ?? 0,
maxHydrogen: json["maxHydrogen"] ?? 0,
);
Map<String, dynamic> toJson() => {
"plateNumber": plateNumber,
"vin": vin,
"modelName": modelName,
"brandName": brandName,
"engineNum": engineNum,
"truckNum": truckNum,
"hydrogenCapacity": hydrogenCapacity,
"maxHydrogen": maxHydrogen,
};
}

View File

@@ -421,7 +421,7 @@ class ReservationController extends GetxController with BaseControllerMixin {
var responseData = await HttpService.to.get("hydrogen/queryHydrogenSiteInfo"); var responseData = await HttpService.to.get("hydrogen/queryHydrogenSiteInfo");
if (responseData == null && responseData!.data == null) { if (responseData == null || responseData.data == null) {
showToast('暂时无法获取站点信息'); showToast('暂时无法获取站点信息');
dismissLoading(); dismissLoading();
return; return;

View File

@@ -1,8 +1,9 @@
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:ln_jq_app/common/model/vehicle_info.dart';
import 'package:ln_jq_app/pages/qr_code/view.dart'; import 'package:ln_jq_app/pages/qr_code/view.dart';
import 'package:ln_jq_app/storage_service.dart';
import 'controller.dart'; import 'controller.dart';
@@ -142,11 +143,7 @@ class ReservationPage extends GetView<ReservationController> {
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Icon( Icon(Icons.propane_rounded, size: 50, color: Colors.blue.withOpacity(0.5)),
Icons.propane_rounded,
size: 50,
color: Colors.blue.withOpacity(0.5),
),
], ],
), ),
), ),
@@ -162,8 +159,18 @@ class ReservationPage extends GetView<ReservationController> {
const SizedBox(width: 8), const SizedBox(width: 8),
isButton isButton
? GestureDetector( ? GestureDetector(
onTap: () { onTap: () async {
Get.to(() => const QrCodePage()); //判断是否绑定成功
var scanResult = await Get.to(() => const QrCodePage());
if (scanResult == true) {
VehicleInfo? bean = StorageService.to.vehicleInfo;
if (bean != null) {
showToast(
"已绑定${bean.plateNumber}-${StorageService.to.hasVehicleInfo}",
);
}
}
}, },
child: Container( child: Container(
margin: EdgeInsetsGeometry.only(left: 10.w), margin: EdgeInsetsGeometry.only(left: 10.w),
@@ -181,7 +188,10 @@ class ReservationPage extends GetView<ReservationController> {
Text( Text(
value, value,
style: const TextStyle( style: const TextStyle(
color: Colors.blue, fontSize: 11, fontWeight: FontWeight.w500), color: Colors.blue,
fontSize: 11,
fontWeight: FontWeight.w500,
),
), ),
], ],
), ),
@@ -411,13 +421,9 @@ class ReservationPage extends GetView<ReservationController> {
), ),
dropdownStyleData: DropdownStyleData( dropdownStyleData: DropdownStyleData(
maxHeight: 200, maxHeight: 200,
decoration: BoxDecoration( decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
borderRadius: BorderRadius.circular(8),
),
),
menuItemStyleData: const MenuItemStyleData(
height: 40,
), ),
menuItemStyleData: const MenuItemStyleData(height: 40),
), ),
), ),
), ),

View File

@@ -6,6 +6,9 @@ import 'package:get/get.dart';
import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:image/image.dart' as img; import 'package:image/image.dart' as img;
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:ln_jq_app/common/model/base_model.dart';
import 'package:ln_jq_app/common/model/vehicle_info.dart';
import 'package:ln_jq_app/storage_service.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart'; import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
import 'package:zxing_lib/common.dart'; import 'package:zxing_lib/common.dart';
import 'package:zxing_lib/qrcode.dart'; import 'package:zxing_lib/qrcode.dart';
@@ -134,28 +137,43 @@ class QrCodeController extends GetxController
showErrorToast('相机权限未被授予,请到权限管理中打开'); showErrorToast('相机权限未被授予,请到权限管理中打开');
} }
if (!isPhotosGranted) { if (!isPhotosGranted) {
showErrorToast( showErrorToast('相册权限未被授予,请到权限管理中打开');
'相册权限未被授予,请到权限管理中打开',
);
} }
} }
//扫码结果处理 //扫码结果处理
void renderResult(String resultStr) { void renderResult(String resultStr) async {
Get.defaultDialog( showLoading("正在获取车辆信息...");
title: "扫描结果", try {
middleText: resultStr, var responseData = await HttpService.to.get(
onConfirm: () { "appointment/truck/base-info?vin=$resultStr",
Get.back();
resumeScanner();
},
onCancel: () {
resumeScanner();
},
); );
if (responseData == null || responseData.data == null) {
showToast('无法获取车辆信息,请检查网络或稍后重试');
resumeScanner();
return;
} }
var result = BaseModel.fromJson(responseData.data);
final vehicle = VehicleInfo.fromJson(result.data as Map<String, dynamic>);
//保存使用
await StorageService.to.saveVehicleInfo(vehicle);
Get.back(result: true);
} on DioException catch (e) {
showErrorToast("网络请求失败,请稍后重试");
resumeScanner();
} catch (e, stackTrace) {
showErrorToast("处理失败,请稍后重试");
resumeScanner(); // 未知异常,恢复扫描
} finally {
dismissLoading();
}
}
@override @override
void onClose() { void onClose() {
qrViewController?.dispose(); qrViewController?.dispose();

View File

@@ -1,5 +1,6 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
import 'package:ln_jq_app/common/model/vehicle_info.dart';
/// 定义登录渠道的枚举类型 /// 定义登录渠道的枚举类型
enum LoginChannel { enum LoginChannel {
@@ -15,10 +16,11 @@ class StorageService extends GetxService {
static const String _tokenKey = 'user_token'; static const String _tokenKey = 'user_token';
static const String _userIdKey = 'user_id'; static const String _userIdKey = 'user_id';
static const String _channelKey = 'login_channel'; static const String _channelKey = 'login_channel';
// 为新字段增加键名
static const String _nameKey = 'user_name'; static const String _nameKey = 'user_name';
static const String _phoneKey = 'user_phone'; static const String _phoneKey = 'user_phone';
static const String _idCardKey = 'user_id_card'; static const String _idCardKey = 'user_id_card';
// 车辆信息的键名
static const String _vehicleInfoKey = 'vehicle_info';
// 提供一个静态的 'to' 方法,方便全局访问 // 提供一个静态的 'to' 方法,方便全局访问
static StorageService get to => Get.find(); static StorageService get to => Get.find();
@@ -31,30 +33,27 @@ class StorageService extends GetxService {
/// --- Getter 方法,用于读取状态 --- /// --- Getter 方法,用于读取状态 ---
/// 判断是否已登录 (通过检查 token 是否存在且不为空) bool get isLoggedIn => _box.read<String?>(_tokenKey)?.isNotEmpty ?? false;
bool get isLoggedIn =>
_box
.read<String?>(_tokenKey)
?.isNotEmpty ?? false;
/// 获取 Token
String? get token => _box.read<String?>(_tokenKey); String? get token => _box.read<String?>(_tokenKey);
/// 获取 UserId
String? get userId => _box.read<String?>(_userIdKey); String? get userId => _box.read<String?>(_userIdKey);
/// 获取 Name
String? get name => _box.read<String?>(_nameKey); String? get name => _box.read<String?>(_nameKey);
/// 获取 Phone
String? get phone => _box.read<String?>(_phoneKey); String? get phone => _box.read<String?>(_phoneKey);
/// 获取 ID Card
String? get idCard => _box.read<String?>(_idCardKey); String? get idCard => _box.read<String?>(_idCardKey);
/// 判断是否已有车辆信息缓存
bool get hasVehicleInfo => _box.hasData(_vehicleInfoKey);
/// 获取已缓存的车辆信息
VehicleInfo? get vehicleInfo {
final vehicleJson = _box.read<String?>(_vehicleInfoKey);
if (vehicleJson != null) {
// 使用我们之前创建的辅助函数来解析
return vehicleInfoFromJson(vehicleJson);
}
return null;
}
///获取当前登录渠道 ///获取当前登录渠道
/// 从存储中读取字符串,并转换为枚举类型
LoginChannel get loginChannel { LoginChannel get loginChannel {
final channelString = _box.read<String?>(_channelKey); final channelString = _box.read<String?>(_channelKey);
if (channelString == 'station') { if (channelString == 'station') {
@@ -66,12 +65,10 @@ class StorageService extends GetxService {
} }
/// --- 操作方法 --- /// --- 操作方法 ---
/// 保存用户信息
/// @param channel - 登录渠道station 或 driver
Future<void> saveLoginInfo({ Future<void> saveLoginInfo({
required String token, required String token,
required String userId, required String userId,
required String channel, // 接收一个字符串类型的渠道 required String channel,
String? name, String? name,
String? phone, String? phone,
String? idCard, String? idCard,
@@ -79,20 +76,31 @@ class StorageService extends GetxService {
await _box.write(_tokenKey, token); await _box.write(_tokenKey, token);
await _box.write(_userIdKey, userId); await _box.write(_userIdKey, userId);
await _box.write(_channelKey, channel); await _box.write(_channelKey, channel);
// 保存新增的字段,如果为 null, GetStorage 会移除该键
await _box.write(_nameKey, name); await _box.write(_nameKey, name);
await _box.write(_phoneKey, phone); await _box.write(_phoneKey, phone);
await _box.write(_idCardKey, idCard); await _box.write(_idCardKey, idCard);
} }
///删除用户信息,增加删除渠道信息 /// 保存车辆信息
Future<void> saveVehicleInfo(VehicleInfo data) async {
// 使用辅助函数将对象转换为 JSON 字符串并保存
await _box.write(_vehicleInfoKey, vehicleInfoToJson(data));
}
/// 清除车辆信息
Future<void> clearVehicleInfo() async {
await _box.remove(_vehicleInfoKey);
}
/// 删除用户信息 (登出)
Future<void> clearLoginInfo() async { Future<void> clearLoginInfo() async {
await _box.remove(_tokenKey); await _box.remove(_tokenKey);
await _box.remove(_userIdKey); await _box.remove(_userIdKey);
await _box.remove(_channelKey); await _box.remove(_channelKey);
// 退出时一并清除新增的字段
await _box.remove(_nameKey); await _box.remove(_nameKey);
await _box.remove(_phoneKey); await _box.remove(_phoneKey);
await _box.remove(_idCardKey); await _box.remove(_idCardKey);
// 登出时一并清除车辆信息
await clearVehicleInfo();
} }
} }