Compare commits
2 Commits
288d629f99
...
6629c8047f
| Author | SHA1 | Date | |
|---|---|---|---|
| 6629c8047f | |||
| bfa615a7f4 |
@@ -131,13 +131,13 @@
|
||||
<!-- 1. 配置安全密钥 -->
|
||||
<script type="text/javascript">
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: '0529b72df6bf0c577ff2182cb8b1d970',
|
||||
securityJsCode: 'aa3a22c19ed76b27f8a587555d6981c8',
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- 2. 加载地图和插件 (去掉了 Geolocation 插件,避免弹窗) -->
|
||||
<script
|
||||
src="https://webapi.amap.com/maps?v=2.0&key=2cc1d822e313307fe311c3127a1deeb5&plugin=AMap.MoveAnimation,AMap.Driving,AMap.TruckDriving,AMap.AutoComplete,AMap.ToolBar,AMap.Scale,AMap.Geocoder">
|
||||
src="https://webapi.amap.com/maps?v=2.0&key=ecd74ece8cb14c9dad67675f83c3274d&plugin=AMap.MoveAnimation,AMap.Driving,AMap.TruckDriving,AMap.AutoComplete,AMap.ToolBar,AMap.Scale,AMap.Geocoder">
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||
import 'package:ln_jq_app/common/model/base_model.dart';
|
||||
import 'package:ln_jq_app/common/styles/theme.dart';
|
||||
@@ -277,9 +278,10 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
child: TextField(
|
||||
controller: amountController,
|
||||
textAlign: TextAlign.center,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true,
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly, // 只允许数字输入
|
||||
],
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
||||
@@ -17,6 +17,7 @@ import 'package:ln_jq_app/pages/qr_code/view.dart';
|
||||
import 'package:ln_jq_app/storage_service.dart';
|
||||
|
||||
import '../../../common/styles/theme.dart';
|
||||
import 'reservation_list_bottomsheet.dart';
|
||||
|
||||
/// Helper class for managing time slots
|
||||
class TimeSlot {
|
||||
@@ -547,6 +548,10 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
||||
num maxHydrogen = 0;
|
||||
String difference = "";
|
||||
|
||||
//用来管理查看预约的弹窗
|
||||
Worker? _sheetWorker;
|
||||
bool init = false;
|
||||
|
||||
@override
|
||||
bool get listenLifecycleEvent => true;
|
||||
|
||||
@@ -555,6 +560,32 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
||||
super.onInit();
|
||||
getUserBindCarInfo();
|
||||
getSiteList();
|
||||
|
||||
if (!init) {
|
||||
_setupListener();
|
||||
init = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_sheetWorker?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _setupListener() {
|
||||
_sheetWorker = ever(shouldShowReservationList, (bool shouldShow) {
|
||||
if (shouldShow) {
|
||||
Get.bottomSheet(
|
||||
const ReservationListBottomSheet(),
|
||||
isScrollControlled: true, // 允许弹窗使用更多屏幕高度
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
|
||||
// 重要:显示后立即将信号重置为 false,防止不必要的重复弹出
|
||||
shouldShowReservationList.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void getUserBindCarInfo() {
|
||||
@@ -628,6 +659,11 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
||||
final leftHydrogenNum = double.tryParse(leftHydrogen) ?? 0.0;
|
||||
difference = (maxHydrogen - leftHydrogenNum).toStringAsFixed(2);
|
||||
|
||||
int flooredDifference = (maxHydrogen - leftHydrogenNum).floor();
|
||||
if (flooredDifference > 0) {
|
||||
amountController.text = flooredDifference.toString();
|
||||
}
|
||||
|
||||
updateUi();
|
||||
} catch (e) {
|
||||
} finally {
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'reservation_list_bottomsheet.dart';
|
||||
class ReservationPage extends GetView<C_ReservationController> {
|
||||
ReservationPage({super.key});
|
||||
|
||||
bool init = false;
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -21,10 +21,7 @@ class ReservationPage extends GetView<C_ReservationController> {
|
||||
init: C_ReservationController(),
|
||||
id: 'reservation',
|
||||
builder: (_) {
|
||||
if (!init) {
|
||||
_setupListener(context);
|
||||
init = true;
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey[100],
|
||||
body: GestureDetector(
|
||||
@@ -335,20 +332,7 @@ class ReservationPage extends GetView<C_ReservationController> {
|
||||
);
|
||||
}
|
||||
|
||||
void _setupListener(BuildContext context) {
|
||||
ever(controller.shouldShowReservationList, (bool shouldShow) {
|
||||
if (shouldShow) {
|
||||
Get.bottomSheet(
|
||||
const ReservationListBottomSheet(),
|
||||
isScrollControlled: true, // 允许弹窗使用更多屏幕高度
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
|
||||
// 重要:显示后立即将信号重置为 false,防止不必要的重复弹出
|
||||
controller.shouldShowReservationList.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 表单中的可点击行 (用于日期和时间选择)
|
||||
Widget _buildPickerRow({
|
||||
|
||||
@@ -24,6 +24,8 @@ class QrCodeController extends GetxController
|
||||
final RxBool isFlashOn = false.obs;
|
||||
final RxBool isProcessingResult = false.obs;
|
||||
|
||||
final RxBool hasPermission = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
@@ -47,7 +49,6 @@ class QrCodeController extends GetxController
|
||||
isProcessingResult.value = true;
|
||||
scannerController.stop();
|
||||
animationController.stop();
|
||||
print("相机识别到的内容: ${barcode.rawValue!}");
|
||||
renderResult(barcode.rawValue!);
|
||||
}
|
||||
}
|
||||
@@ -57,10 +58,10 @@ class QrCodeController extends GetxController
|
||||
isProcessingResult.value = false;
|
||||
try {
|
||||
scannerController.start();
|
||||
animationController.repeat(reverse: false);
|
||||
} catch (e) {
|
||||
print("无法重启相机: $e");
|
||||
}
|
||||
animationController.repeat(reverse: false);
|
||||
}
|
||||
|
||||
/// 从相册选择图片并扫描二维码
|
||||
@@ -120,10 +121,19 @@ class QrCodeController extends GetxController
|
||||
/// 请求相机权限
|
||||
void requestPermission() async {
|
||||
var status = await Permission.camera.request();
|
||||
|
||||
hasPermission.value = status.isGranted;
|
||||
|
||||
if (!status.isGranted) {
|
||||
showErrorToast('请授予相机权限以使用扫描功能');
|
||||
Get.back();
|
||||
if (status.isPermanentlyDenied) {
|
||||
showErrorToast('相机权限已被永久拒绝,请到系统设置中开启');
|
||||
// 延迟一会再引导用户去设置
|
||||
Future.delayed(const Duration(seconds: 2), () => openAppSettings());
|
||||
} else {
|
||||
showErrorToast('请授予相机权限以使用扫描功能');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void requestPhotoPermission() async {
|
||||
|
||||
@@ -29,27 +29,77 @@ class QrCodePage extends GetView<QrCodeController> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// 1. 使用 MobileScanner 作为扫描视图
|
||||
MobileScanner(
|
||||
controller: controller.scannerController,
|
||||
onDetect: controller.onDetect,
|
||||
// 您可以自定义扫描框的样式
|
||||
scanWindow: Rect.fromCenter(
|
||||
center: Offset(
|
||||
MediaQuery.of(context).size.width / 2,
|
||||
MediaQuery.of(context).size.height / 2 - 50,
|
||||
),
|
||||
width: 250,
|
||||
height: 250,
|
||||
body: Obx(() { // 1. 使用 Obx 包裹整个 body
|
||||
// 根据权限状态来决定显示什么
|
||||
if (controller.hasPermission.value) {
|
||||
// 如果有权限,显示扫描器
|
||||
return _buildScannerView(context);
|
||||
} else {
|
||||
// 如果没有权限,显示引导界面
|
||||
return _buildPermissionDeniedView();
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
Widget _buildScannerView(BuildContext context){
|
||||
if (!controller.animationController.isAnimating) {
|
||||
controller.animationController.repeat(reverse: false);
|
||||
}
|
||||
return Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// 使用 MobileScanner 作为扫描视图
|
||||
MobileScanner(
|
||||
controller: controller.scannerController,
|
||||
onDetect: controller.onDetect,
|
||||
// 您可以自定义扫描框的样式
|
||||
scanWindow: Rect.fromCenter(
|
||||
center: Offset(
|
||||
MediaQuery.of(context).size.width / 2,
|
||||
MediaQuery.of(context).size.height / 2 - 50,
|
||||
),
|
||||
width: 250,
|
||||
height: 250,
|
||||
),
|
||||
),
|
||||
// 扫描动画和覆盖层
|
||||
_buildScannerOverlay(context),
|
||||
// 底部的功能按钮
|
||||
Positioned(bottom: 80, left: 0, right: 0, child: _buildActionButtons()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPermissionDeniedView() {
|
||||
// 确保动画是停止的
|
||||
if (controller.animationController.isAnimating) {
|
||||
controller.animationController.stop();
|
||||
}
|
||||
|
||||
return Container(
|
||||
color: Colors.black,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.no_photography, color: Colors.white70, size: 64),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
'需要相机权限',
|
||||
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'请授予相机权限以使用扫码功能。',
|
||||
style: TextStyle(color: Colors.white70, fontSize: 14),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: controller.requestPermission, // 点击按钮重新请求权限
|
||||
child: const Text('授予权限'),
|
||||
),
|
||||
// 扫描动画和覆盖层
|
||||
_buildScannerOverlay(context),
|
||||
// 底部的功能按钮
|
||||
Positioned(bottom: 80, left: 0, right: 0, child: _buildActionButtons()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user