加氢站-查看证件
This commit is contained in:
BIN
ln_jq_app/assets/images/ic_close@2x.png
Normal file
BIN
ln_jq_app/assets/images/ic_close@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 892 B |
@@ -1,11 +1,18 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||
import 'package:image_gallery_saver/image_gallery_saver.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/storage_service.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photo_view/photo_view_gallery.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
enum ReservationStatus {
|
||||
@@ -46,6 +53,8 @@ class ReservationModel {
|
||||
final int isTruckAttachment; // 1为有证件数据 0为缺少
|
||||
final bool hasDrivingAttachment; // 是否有行驶证
|
||||
final bool hasHydrogenationAttachment; // 是否有加氢证
|
||||
final List<String> drivingAttachments; // 行驶证图片列表
|
||||
final List<String> hydrogenationAttachments; // 加氢证图片列表
|
||||
|
||||
ReservationModel({
|
||||
required this.id,
|
||||
@@ -73,6 +82,8 @@ class ReservationModel {
|
||||
required this.hasDrivingAttachment,
|
||||
required this.hasHydrogenationAttachment,
|
||||
required this.isEdit,
|
||||
required this.drivingAttachments,
|
||||
required this.hydrogenationAttachments,
|
||||
});
|
||||
|
||||
/// 工厂构造函数,用于从JSON创建ReservationModel实例
|
||||
@@ -146,6 +157,8 @@ class ReservationModel {
|
||||
hasDrivingAttachment: drivingList.isNotEmpty,
|
||||
hasHydrogenationAttachment: hydrogenationList.isNotEmpty,
|
||||
isEdit: json['isEdit']?.toString() ?? '0',
|
||||
drivingAttachments: drivingList.map((e) => e.toString()).toList(),
|
||||
hydrogenationAttachments: hydrogenationList.map((e) => e.toString()).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -348,6 +361,8 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
hasDrivingAttachment: false,
|
||||
hasHydrogenationAttachment: false,
|
||||
isEdit: "0",
|
||||
drivingAttachments: [],
|
||||
hydrogenationAttachments: [],
|
||||
);
|
||||
} else {
|
||||
item = reservationList.firstWhere(
|
||||
@@ -416,13 +431,13 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
),
|
||||
SizedBox(width: 16.w),
|
||||
if (item.plateNumber != "---" && item.hasDrivingAttachment)
|
||||
_buildInfoTag('行驶证'),
|
||||
buildInfoTag('行驶证', item.drivingAttachments),
|
||||
if (item.plateNumber != "---" && item.hasHydrogenationAttachment)
|
||||
_buildInfoTag('加氢证'),
|
||||
buildInfoTag('加氢证', item.hydrogenationAttachments),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 6.h),
|
||||
SizedBox(height: 6.h),
|
||||
|
||||
// 提示逻辑
|
||||
if (isEdit)
|
||||
@@ -458,7 +473,7 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 6.h),
|
||||
SizedBox(height: 6.h),
|
||||
|
||||
// 预定加氢量输入区
|
||||
Container(
|
||||
@@ -590,7 +605,7 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
1,
|
||||
addHydAmount,
|
||||
"",
|
||||
item,
|
||||
item!,
|
||||
gunNumber: selectedGun.value,
|
||||
plateNumber: item.plateNumber,
|
||||
isEdit: true,
|
||||
@@ -600,7 +615,7 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
}
|
||||
//订单确认
|
||||
if (!isEdit &&
|
||||
(item.plateNumber == "---" ||
|
||||
(item!.plateNumber == "---" ||
|
||||
item.isTruckAttachment == 0) &&
|
||||
!isOfflineChecked.value) {
|
||||
showToast("车辆未上传加氢证 , 请确保线下登记后点击确认");
|
||||
@@ -663,14 +678,14 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
child: OutlinedButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
if (!isEdit) {
|
||||
if (!isEdit && !isAdd) {
|
||||
upDataService(
|
||||
id,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"",
|
||||
item,
|
||||
item!,
|
||||
gunNumber: selectedGun.value,
|
||||
plateNumber: item.plateNumber,
|
||||
);
|
||||
@@ -684,7 +699,7 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
isEdit ? '取消' : '未加氢',
|
||||
isEdit || isAdd ? '取消' : '未加氢',
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 16),
|
||||
),
|
||||
),
|
||||
@@ -725,17 +740,170 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInfoTag(String label) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(left: 4),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF2F3F5),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
/// 保存图片到相册
|
||||
Future<void> saveImageToLocal(String url) async {
|
||||
try {
|
||||
// 1. 权限请求
|
||||
if (Platform.isAndroid) {
|
||||
var status = await Permission.storage.request();
|
||||
if (!status.isGranted) {
|
||||
showErrorToast("请在系统设置中开启存储权限");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
var status = await Permission.photos.request();
|
||||
if (!status.isGranted) {
|
||||
showErrorToast("请在系统设置中开启相册权限");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
showLoading("正在保存...");
|
||||
|
||||
// 2. 下载图片
|
||||
var response = await Dio().get(
|
||||
url,
|
||||
options: Options(responseType: ResponseType.bytes),
|
||||
);
|
||||
|
||||
// 3. 保存到相册
|
||||
final result = await ImageGallerySaver.saveImage(
|
||||
Uint8List.fromList(response.data),
|
||||
quality: 100,
|
||||
name: "certificate_${DateTime.now().millisecondsSinceEpoch}",
|
||||
);
|
||||
|
||||
dismissLoading();
|
||||
|
||||
if (result != null && result['isSuccess'] == true) {
|
||||
showSuccessToast("图片已保存至相册");
|
||||
} else {
|
||||
showErrorToast("保存失败");
|
||||
}
|
||||
} catch (e) {
|
||||
dismissLoading();
|
||||
showErrorToast("保存异常");
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildInfoTag(String label, List<String> images) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
showImagePreview(images);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 4),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF2F3F5),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(color: Color(0xFF999999), fontSize: 11.sp),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(color: Color(0xFF999999), fontSize: 11.sp),
|
||||
);
|
||||
}
|
||||
|
||||
/// 显示图片预览弹窗
|
||||
void showImagePreview(List<String> images) {
|
||||
if (images.isEmpty) return;
|
||||
|
||||
final RxInt currentIndex = 0.obs;
|
||||
final PageController pageController = PageController();
|
||||
|
||||
Get.dialog(
|
||||
GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 图片翻页
|
||||
SizedBox(
|
||||
height: Get.height * 0.5,
|
||||
child: PhotoViewGallery.builder(
|
||||
scrollPhysics: const BouncingScrollPhysics(),
|
||||
builder: (BuildContext context, int index) {
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: NetworkImage(images[index]),
|
||||
initialScale: PhotoViewComputedScale.contained,
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: images[index]),
|
||||
onTapDown: (context, details, controllerValue) {
|
||||
_showSaveImageMenu(images[index]);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: images.length,
|
||||
loadingBuilder: (context, event) => const Center(
|
||||
child: CircularProgressIndicator(color: Colors.white),
|
||||
),
|
||||
backgroundDecoration: const BoxDecoration(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
pageController: pageController,
|
||||
onPageChanged: (index) => currentIndex.value = index,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
// 页码指示器
|
||||
Center(
|
||||
child: Text(
|
||||
"${currentIndex.value + 1} / ${images.length}",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 关闭按钮
|
||||
Positioned(
|
||||
top: 150.h,
|
||||
right: 20,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.close, color: Colors.white, size: 30),
|
||||
onPressed: () => Get.back(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
useSafeArea: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _showSaveImageMenu(String url) {
|
||||
Get.bottomSheet(
|
||||
Container(
|
||||
color: Colors.white,
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.download),
|
||||
title: const Text('保存图片到相册'),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
saveImageToLocal(url);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
title: const Text('取消', textAlign: TextAlign.center),
|
||||
onTap: () => Get.back(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -550,10 +550,11 @@ class SitePage extends GetView<SiteController> {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (item.hasDrivingAttachment) _buildInfoTag('行驶证'),
|
||||
if (item.hasDrivingAttachment)
|
||||
controller.buildInfoTag('行驶证',item.drivingAttachments),
|
||||
if (item.hasHydrogenationAttachment) ...[
|
||||
SizedBox(width: 8.w),
|
||||
_buildInfoTag('加氢证'),
|
||||
controller.buildInfoTag('加氢证',item.hydrogenationAttachments)
|
||||
],
|
||||
Spacer(),
|
||||
if (item.isEdit == "1") ...[
|
||||
@@ -602,19 +603,7 @@ class SitePage extends GetView<SiteController> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInfoTag(String label) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color.fromRGBO(242, 243, 245, 1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(color: Color.fromRGBO(78, 89, 105, 1), fontSize: 11.sp),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget _buildSmallButton(
|
||||
String text, {
|
||||
|
||||
@@ -227,6 +227,8 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
|
||||
hasHydrogenationAttachment: true,
|
||||
hasDrivingAttachment: true,
|
||||
isEdit: '',
|
||||
drivingAttachments: [],
|
||||
hydrogenationAttachments: [],
|
||||
);
|
||||
|
||||
//打开预约列表
|
||||
|
||||
@@ -589,6 +589,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.7.2"
|
||||
image_gallery_saver:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image_gallery_saver
|
||||
sha256: "0aba74216a4d9b0561510cb968015d56b701ba1bd94aace26aacdd8ae5761816"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@@ -16,12 +16,12 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.2.3+6
|
||||
version: 1.2.2+5
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.0
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# Dependencies specify other packages tha。。。t your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
@@ -53,6 +53,7 @@ dependencies:
|
||||
aliyun_push_flutter: ^1.3.6
|
||||
pull_to_refresh: ^2.0.0
|
||||
flutter_app_update: ^3.2.2
|
||||
image_gallery_saver: ^2.0.3
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
Reference in New Issue
Block a user