加氢站-预约

This commit is contained in:
2026-02-27 10:54:55 +08:00
parent 14fd6c75d0
commit 39cae906e9
3 changed files with 531 additions and 324 deletions

View File

@@ -40,6 +40,12 @@ class ReservationModel {
final String addStatus; final String addStatus;
final String addStatusName; final String addStatusName;
bool hasEdit; bool hasEdit;
final String isEdit; // "1" 表示可以修改信息
// 新增附件相关字段
final int isTruckAttachment; // 1为有证件数据 0为缺少
final bool hasDrivingAttachment; // 是否有行驶证
final bool hasHydrogenationAttachment; // 是否有加氢证
ReservationModel({ ReservationModel({
required this.id, required this.id,
@@ -63,6 +69,10 @@ class ReservationModel {
required this.addStatus, required this.addStatus,
required this.addStatusName, required this.addStatusName,
required this.rejectReason, required this.rejectReason,
required this.isTruckAttachment,
required this.hasDrivingAttachment,
required this.hasHydrogenationAttachment,
required this.isEdit,
}); });
/// 工厂构造函数用于从JSON创建ReservationModel实例 /// 工厂构造函数用于从JSON创建ReservationModel实例
@@ -101,11 +111,17 @@ class ReservationModel {
? '$dateStr ${startTimeStr.substring(11, 16)}-${endTimeStr.substring(11, 16)}' // 截取 HH:mm ? '$dateStr ${startTimeStr.substring(11, 16)}-${endTimeStr.substring(11, 16)}' // 截取 HH:mm
: '时间未定'; : '时间未定';
// 解析附件信息
Map<String, dynamic> attachmentVo = json['truckAttachmentVo'] ?? {};
int isTruckAttachment = attachmentVo['isTruckAttachment'] as int? ?? 0;
List drivingList = attachmentVo['drivingAttachment'] ?? [];
List hydrogenationList = attachmentVo['hydrogenationAttachment'] ?? [];
return ReservationModel( return ReservationModel(
// 原始字段用于UI兼容 // 原始字段用于UI兼容
id: json['id']?.toString() ?? '', id: json['id']?.toString() ?? '',
stationId: json['stationId']?.toString() ?? '', stationId: json['stationId']?.toString() ?? '',
plateNumber: json['plateNumber']?.toString() ?? '未知车牌', plateNumber: json['plateNumber']?.toString() ?? '---',
amount: '${json['hydAmount']?.toString() ?? '0'}kg', amount: '${json['hydAmount']?.toString() ?? '0'}kg',
time: timeRange, time: timeRange,
contactPerson: json['contacts']?.toString() ?? '无联系人', contactPerson: json['contacts']?.toString() ?? '无联系人',
@@ -126,6 +142,10 @@ class ReservationModel {
stateName: json['stateName']?.toString() ?? '', stateName: json['stateName']?.toString() ?? '',
rejectReason: json['rejectReason']?.toString() ?? '', rejectReason: json['rejectReason']?.toString() ?? '',
hasEdit: true, hasEdit: true,
isTruckAttachment: isTruckAttachment,
hasDrivingAttachment: drivingList.isNotEmpty,
hasHydrogenationAttachment: hydrogenationList.isNotEmpty,
isEdit: json['isEdit']?.toString() ?? '0',
); );
} }
} }
@@ -147,6 +167,9 @@ class SiteController extends GetxController with BaseControllerMixin {
bool isNotice = false; bool isNotice = false;
final RefreshController refreshController = RefreshController(initialRefresh: false); final RefreshController refreshController = RefreshController(initialRefresh: false);
// 加氢枪列表
final RxList<String> gasGunList = <String>[].obs;
@override @override
bool get listenLifecycleEvent => true; bool get listenLifecycleEvent => true;
@@ -156,6 +179,7 @@ class SiteController extends GetxController with BaseControllerMixin {
renderData(); renderData();
msgNotice(); msgNotice();
startAutoRefresh(); startAutoRefresh();
fetchGasGunList();
} }
@override @override
@@ -212,6 +236,24 @@ class SiteController extends GetxController with BaseControllerMixin {
print("【自动刷新】定时器已停止。"); print("【自动刷新】定时器已停止。");
} }
/// 获取加氢枪列表
Future<void> fetchGasGunList() async {
try {
var response = await HttpService.to.get(
'appointment/station/getGasGunList?hydrogenId=${StorageService.to.userId}',
);
if (response != null && response.data != null) {
final result = BaseModel<dynamic>.fromJson(response.data);
if (result.code == 0 && result.data != null) {
List dataList = result.data as List;
gasGunList.assignAll(dataList.map((e) => e['deviceName'].toString()).toList());
}
}
} catch (e) {
Logger.d("获取加氢枪列表失败: $e");
}
}
/// 获取预约数据的方法 /// 获取预约数据的方法
Future<void> fetchReservationData() async { Future<void> fetchReservationData() async {
showLoading("加载中"); showLoading("加载中");
@@ -272,138 +314,375 @@ class SiteController extends GetxController with BaseControllerMixin {
} }
} }
/// 确认预约 /// 确认预约弹窗重构
Future<void> confirmReservation(String id) async { Future<void> confirmReservation(String id, {bool isEdit = false}) async {
final item = reservationList.firstWhere( final item = reservationList.firstWhere(
(item) => item.id == id, (item) => item.id == id,
orElse: () => throw Exception('Reservation not found'), orElse: () => throw Exception('Reservation not found'),
); );
// 加氢量保留3位小数
double initialAmount = double.tryParse(item.hydAmount) ?? 0.0;
final TextEditingController amountController = TextEditingController( final TextEditingController amountController = TextEditingController(
text: item.hydAmount, text: initialAmount.toStringAsFixed(3),
); );
final RxString selectedGun = (gasGunList.isNotEmpty ? gasGunList.first : '').obs;
final RxBool isOfflineChecked = false.obs;
Get.dialog( Get.dialog(
Dialog( Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), // 圆角 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding( child: SingleChildScrollView(
padding: const EdgeInsets.only(top: 24.0), child: Padding(
child: Column( padding: const EdgeInsets.all(20.0),
mainAxisSize: MainAxisSize.min, // 高度自适应 child: Column(
children: [ mainAxisSize: MainAxisSize.min,
const Text( crossAxisAlignment: CrossAxisAlignment.start,
'确认加氢状态', children: [
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), Text(
), isEdit ? '修改加氢量' : '确认加氢状态',
const SizedBox(height: 5), style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
// content 部分 ),
Padding( const SizedBox(height: 16),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column( // 车牌号及标签
children: [ Row(
Text( children: [
'车牌号 ${item.plateNumber}', Text(
style: const TextStyle( item.plateNumber == "---" ? '-------' : item.plateNumber,
fontSize: 16, style: TextStyle(
color: AppTheme.themeColor, fontSize: 16.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
), color: item.plateNumber == "---" ? Colors.grey : Colors.black,
), letterSpacing: item.plateNumber == "---" ? 2 : 0,
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'加氢量',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
), ),
const SizedBox(width: 16), ),
SizedBox( const SizedBox(width: 8),
width: 100, Container(
child: TextField( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
controller: amountController, decoration: BoxDecoration(
textAlign: TextAlign.center, color: Color.fromRGBO(232, 243, 255, 1),
keyboardType: TextInputType.number, borderRadius: BorderRadius.circular(4),
inputFormatters: [ ),
FilteringTextInputFormatter.digitsOnly, // 只允许数字输入 child: Text(
item.plateNumber == "---" ? '车牌号识别' : '重新识别',
style: TextStyle(
color: Color.fromRGBO(22, 93, 255, 1),
fontSize: 13.sp,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(width: 16.w),
if (item.plateNumber != "---" && item.hasDrivingAttachment)
_buildInfoTag('行驶证'),
if (item.plateNumber != "---" && item.hasHydrogenationAttachment)
_buildInfoTag('加氢证'),
],
),
const SizedBox(height: 12),
// 提示逻辑
if (isEdit)
const Text(
'每个订单只能修改一次,请确认加氢量准确无误',
style: TextStyle(color: Colors.red, fontSize: 12),
)
else
if (item.plateNumber == "---" || item.isTruckAttachment == 0)
Row(
children: [
const Expanded(
child: Text(
'车辆未上传加氢证,请完成线下登记',
style: TextStyle(color: Colors.red, fontSize: 12),
),
),
Obx(
() =>
Checkbox(
value: isOfflineChecked.value,
onChanged: (v) => isOfflineChecked.value = v ?? false,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeColor: AppTheme.themeColor,
),
),
],
),
const SizedBox(height: 16),
// 预定加氢量输入区
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFF7F8FA),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'预定加氢量',
style: TextStyle(
color: Color.fromRGBO(51, 51, 51, 1),
fontSize: 14.sp,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 4),
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
IntrinsicWidth(
child: TextField(
controller: amountController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters: [
// 限制最多输入3位小数
FilteringTextInputFormatter.allow(
RegExp(r'^\d+\.?\d{0,3}'),
),
],
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Color(0xFF017143),
),
decoration: const InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xFF017143),
),
),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xFF017143),
),
),
isDense: true,
contentPadding: EdgeInsets.zero,
),
),
),
const Text(
' KG',
style: TextStyle(color: Colors.grey, fontSize: 14),
),
],
),
], ],
style: TextStyle( ),
fontSize: 22, ),
fontWeight: FontWeight.bold, Container(
color: Get.theme.primaryColor, padding: const EdgeInsets.symmetric(
), horizontal: 12,
decoration: const InputDecoration( vertical: 8,
suffixText: 'kg', ),
suffixStyle: TextStyle(fontSize: 16, color: Colors.grey), decoration: BoxDecoration(
enabledBorder: UnderlineInputBorder( color: const Color(0xFF017143),
borderSide: BorderSide(color: Colors.grey), borderRadius: BorderRadius.circular(8),
),
child: const Row(
children: [
Icon(Icons.qr_code_scanner, color: Colors.white, size: 18),
SizedBox(width: 4),
Text(
'识别',
style: TextStyle(color: Colors.white, fontSize: 14),
), ),
focusedBorder: UnderlineInputBorder( ],
borderSide: BorderSide(color: Colors.grey, width: 2),
),
),
), ),
), ),
], ],
), ),
const SizedBox(height: 12), ),
const Text(
'请选择本次加氢的实际状态\n用于更新预约记录。', const SizedBox(height: 16),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.grey), // 加氢枪号选择
), const Text(
], '请选择加氢枪号',
), style: TextStyle(color: Colors.grey, fontSize: 12),
), ),
const SizedBox(height: 24), const SizedBox(height: 8),
// actions 部分 (按钮) Obx(
Padding( () =>
padding: const EdgeInsets.only(left: 24, right: 24, bottom: 24), Container(
child: Column( padding: const EdgeInsets.symmetric(horizontal: 12),
children: [ decoration: BoxDecoration(
ElevatedButton( border: Border.all(color: Colors.grey.shade300),
onPressed: () { borderRadius: BorderRadius.circular(8),
Get.back(); // 关闭弹窗 ),
final num addHydAmount = num.tryParse(amountController.text) ?? 0; child: DropdownButtonHideUnderline(
upDataService(id, 0, 1, addHydAmount, "", item); child: DropdownButton<String>(
}, value: selectedGun.value.isEmpty ? null : selectedGun.value,
style: ElevatedButton.styleFrom( isExpanded: true,
minimumSize: const Size(double.infinity, 48), hint: const Text('请选择加氢枪号'),
shape: RoundedRectangleBorder( items: gasGunList.map((String gun) {
borderRadius: BorderRadius.circular(5), return DropdownMenuItem<String>(
value: gun, child: Text(gun));
}).toList(),
onChanged: (v) => selectedGun.value = v ?? '',
),
),
),
),
const SizedBox(height: 24),
// 按钮
Row(
children: [
Expanded(
flex: 2,
child: ElevatedButton(
onPressed: () {
//加氢后 订单编辑
if (isEdit) {
final num addHydAmount =
num.tryParse(amountController.text) ?? 0;
upDataService(
id,
0,
1,
addHydAmount,
"",
item,
gunNumber: selectedGun.value,
plateNumber: item.plateNumber,
isEdit: true
);
return;
}
//订单确认
if (!isEdit &&
(item.plateNumber == "---" ||
item.isTruckAttachment == 0) &&
!isOfflineChecked.value) {
showToast("车辆未上传加氢证 , 请确保线下登记后点击确认");
return;
}
if (selectedGun.value.isEmpty) {
showToast("请选择加氢枪号");
return;
}
Get.back();
final num addHydAmount =
num.tryParse(amountController.text) ?? 0;
upDataService(
id,
0,
1,
addHydAmount,
"",
item,
gunNumber: selectedGun.value,
plateNumber: item.plateNumber,
);
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF017143),
minimumSize: const Size(double.infinity, 48),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 0,
),
child: Text(
isEdit ? '确认修改' : '确认加氢',
style: const TextStyle(color: Colors.white, fontSize: 16),
),
), ),
), ),
child: const Text('加氢完成', style: TextStyle(fontSize: 16)), const SizedBox(width: 12),
), Expanded(
const SizedBox(height: 12), flex: 1,
ElevatedButton( child: OutlinedButton(
onPressed: () { onPressed: () {
Get.back(); // 关闭弹窗 Get.back();
upDataService(id, 0, 2, 0, "", item); if (!isEdit) {
}, upDataService(
style: ElevatedButton.styleFrom( id,
backgroundColor: Colors.orange, 0,
minimumSize: const Size(double.infinity, 48), 2,
shape: RoundedRectangleBorder( 0,
borderRadius: BorderRadius.circular(5), "",
item,
gunNumber: selectedGun.value,
plateNumber: item.plateNumber,
);
}
},
style: OutlinedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
side: BorderSide(color: Colors.grey.shade300),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: Text(
isEdit ? '取消' : '未加氢',
style: const TextStyle(color: Colors.grey, fontSize: 16),
),
), ),
), ),
child: const Text('未加氢', style: TextStyle(fontSize: 16)), ],
), ),
const SizedBox(height: 12),
TextButton( const SizedBox(height: 12),
onPressed: () => Get.back(), // 只关闭弹窗 Row(
child: const Text( children: [
'暂不处理', const Expanded(
style: TextStyle(color: Colors.grey, fontSize: 14), child: Divider(color: Color(0xFFEEEEEE), thickness: 1),
), ),
), Padding(
], padding: const EdgeInsets.symmetric(horizontal: 12),
), child: GestureDetector(
onTap: () => Get.back(),
child: Text(
'暂不处理',
style: TextStyle(
color: Color.fromRGBO(16, 185, 129, 1),
fontSize: 14.sp,
),
),
),
),
const Expanded(
child: Divider(color: Color(0xFFEEEEEE), thickness: 1),
),
],
),
],
), ),
], ),
), ),
), ),
barrierDismissible: true,
);
}
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),
),
child: Text(
label,
style: TextStyle(color: Color(0xFF999999), fontSize: 11.sp),
), ),
barrierDismissible: false, // 点击外部不关闭弹窗
); );
} }
@@ -442,27 +721,28 @@ class SiteController extends GetxController with BaseControllerMixin {
const Text('选择或填写拒绝原因:', style: TextStyle(color: Colors.grey)), const Text('选择或填写拒绝原因:', style: TextStyle(color: Colors.grey)),
const SizedBox(height: 8), const SizedBox(height: 8),
Obx( Obx(
() => Wrap( () =>
// 使用 Wrap 自动换行 Wrap(
spacing: 8.0, // 水平间距 // 使用 Wrap 自动换行
children: presetReasons.map((reason) { spacing: 8.0, // 水平间距
final isSelected = selectedReason.value == reason; children: presetReasons.map((reason) {
return ChoiceChip( final isSelected = selectedReason.value == reason;
label: Text(reason), return ChoiceChip(
selected: isSelected, label: Text(reason),
onSelected: (selected) { selected: isSelected,
if (selected) { onSelected: (selected) {
selectedReason.value = reason; if (selected) {
reasonController.clear(); // 选择预设原因时,清空自定义输入 selectedReason.value = reason;
} reasonController.clear(); // 选择预设原因时,清空自定义输入
}, }
selectedColor: Get.theme.primaryColor.withOpacity(0.2), },
labelStyle: TextStyle( selectedColor: Get.theme.primaryColor.withOpacity(0.2),
color: isSelected ? Get.theme.primaryColor : Colors.black, labelStyle: TextStyle(
), color: isSelected ? Get.theme.primaryColor : Colors.black,
); ),
}).toList(), );
), }).toList(),
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@@ -503,16 +783,26 @@ class SiteController extends GetxController with BaseControllerMixin {
} }
Get.back(); // 关闭弹窗 Get.back(); // 关闭弹窗
upDataService(id, 1, -1, 0, finalReason, item); upDataService(
id,
1,
-1,
0,
finalReason,
item,
plateNumber: item.plateNumber,
);
}, },
child: const Text('确认拒绝', style: TextStyle(color: Colors.red)), child: const Text('确认拒绝', style: TextStyle(color: Colors
.red)),
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
child: TextButton( child: TextButton(
onPressed: () => Get.back(), onPressed: () => Get.back(),
child: const Text('暂不处理', style: TextStyle(color: Colors.grey)), child: const Text('暂不处理', style: TextStyle(color: Colors
.grey)),
), ),
), ),
], ],
@@ -527,25 +817,38 @@ class SiteController extends GetxController with BaseControllerMixin {
} }
//addStatus 1完成 2未加 -1拒绝 //addStatus 1完成 2未加 -1拒绝
void upDataService( void upDataService(String id,
String id, int status,
int status, int addStatus,
int addStatus, num addHydAmount,
num addHydAmount, String rejectReason,
String rejectReason, ReservationModel item, {
ReservationModel item, String? gunNumber,
) async { String? plateNumber, bool isEdit = false
}) async {
showLoading("确认中"); showLoading("确认中");
try { try {
var responseData; var responseData;
if (addStatus == -1) { if (isEdit) {
responseData = await HttpService.to.post(
'appointment/orderAddHyd/modifyOrder',
data: {
'id': id,
"addHydAmount": addHydAmount,
"plateNumber": plateNumber,
if (gunNumber != null && gunNumber.isNotEmpty) "gunNumber": gunNumber,
},
);
}else if (addStatus == -1) {
responseData = await HttpService.to.post( responseData = await HttpService.to.post(
'appointment/orderAddHyd/rejectOrder', 'appointment/orderAddHyd/rejectOrder',
data: { data: {
'id': id, 'id': id,
'state': -1, //拒绝使用 'state': -1, //拒绝使用
"rejectReason": rejectReason, "rejectReason": rejectReason,
"plateNumber": plateNumber,
if (gunNumber != null && gunNumber.isNotEmpty) "gunNumber": gunNumber,
}, },
); );
} else { } else {
@@ -555,11 +858,13 @@ class SiteController extends GetxController with BaseControllerMixin {
'id': id, 'id': id,
'addStatus': addStatus, //完成使用 完成1,未加2 'addStatus': addStatus, //完成使用 完成1,未加2
"addHydAmount": addHydAmount, "addHydAmount": addHydAmount,
"plateNumber": plateNumber,
if (gunNumber != null && gunNumber.isNotEmpty) "gunNumber": gunNumber,
}, },
); );
} }
if (responseData == null && responseData!.data == null) { if (responseData == null || responseData.data == null) {
dismissLoading(); dismissLoading();
showToast('服务暂不可用,请稍后'); showToast('服务暂不可用,请稍后');
return; return;
@@ -567,6 +872,8 @@ class SiteController extends GetxController with BaseControllerMixin {
var result = BaseModel.fromJson(responseData.data); var result = BaseModel.fromJson(responseData.data);
if (result.code == 0) { if (result.code == 0) {
showSuccessToast("操作成功"); showSuccessToast("操作成功");
} else {
showToast(result.message);
} }
dismissLoading(); dismissLoading();
@@ -598,7 +905,7 @@ class SiteController extends GetxController with BaseControllerMixin {
'appointment/station/getStationInfoById?hydrogenId=${StorageService.to.userId}', 'appointment/station/getStationInfoById?hydrogenId=${StorageService.to.userId}',
); );
if (responseData == null && responseData!.data == null) { if (responseData == null || responseData.data == null) {
showToast('暂时无法获取站点信息'); showToast('暂时无法获取站点信息');
return; return;
} }
@@ -614,15 +921,15 @@ class SiteController extends GetxController with BaseControllerMixin {
orderUnfinishedAmount = result.data["orderUnfinishedAmount"].toString(); orderUnfinishedAmount = result.data["orderUnfinishedAmount"].toString();
leftHydrogen = leftHydrogen.isEmpty ? "统计中" : leftHydrogen.toString(); leftHydrogen = leftHydrogen.isEmpty ? "统计中" : leftHydrogen.toString();
orderTotalAmount = orderTotalAmount.isEmpty ? "统计中" : orderTotalAmount.toString(); orderTotalAmount =
orderTotalAmount.isEmpty ? "统计中" : orderTotalAmount.toString();
orderUnfinishedAmount = orderUnfinishedAmount.isEmpty orderUnfinishedAmount = orderUnfinishedAmount.isEmpty
? "统计中" ? "统计中"
: orderUnfinishedAmount.toString(); : orderUnfinishedAmount.toString();
} catch (e) { } catch (e) {
showToast('数据异常'); showToast('数据异常');
} }
} catch (e) { } catch (e) {} finally {
} finally {
//加载列表数据 //加载列表数据
fetchReservationData(); fetchReservationData();

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:ln_jq_app/common/login_util.dart'; import 'package:ln_jq_app/common/login_util.dart';
import 'package:ln_jq_app/common/styles/theme.dart';
import 'package:ln_jq_app/pages/b_page/history/view.dart'; import 'package:ln_jq_app/pages/b_page/history/view.dart';
import 'package:ln_jq_app/pages/c_page/message/view.dart'; import 'package:ln_jq_app/pages/c_page/message/view.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
@@ -466,7 +465,7 @@ class SitePage extends GetView<SiteController> {
/// 右侧具体数据卡片 /// 右侧具体数据卡片
Widget _buildInfoCard(ReservationModel item) { Widget _buildInfoCard(ReservationModel item) {
return Container( return Container(
padding: EdgeInsets.only(left: 16.w, top: 8.5, bottom: 8.5, right: 16.w), padding: EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
@@ -508,59 +507,91 @@ class SitePage extends GetView<SiteController> {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
// 联系信息 // 联系信息
Column( Text(
mainAxisAlignment: MainAxisAlignment.start, "${item.contactPerson} | ${item.contactPhone}",
children: [ style: TextStyle(
Text( color: Color(0xFF999999),
"${item.contactPerson} | ${item.contactPhone}", fontSize: 13.sp,
style: TextStyle( fontWeight: FontWeight.w400,
color: Color(0xFF999999), ),
fontSize: 13.sp,
fontWeight: FontWeight.w400,
),
),
],
), ),
SizedBox(height: 6.h),
//操作按钮(仅在待处理状态显示) Row(
if (item.status == ReservationStatus.pending) ...[ crossAxisAlignment: CrossAxisAlignment.end,
const SizedBox(height: 15), children: [
const Divider(height: 1, color: Color(0xFFF5F5F5)), if (item.hasDrivingAttachment) _buildInfoTag('行驶证'),
const SizedBox(height: 12), if (item.hasHydrogenationAttachment) ...[
Row( SizedBox(width: 8.w),
mainAxisAlignment: MainAxisAlignment.end, _buildInfoTag('加氢证'),
children: [ ],
_buildSmallButton( Spacer(),
"拒绝", if (item.isEdit == "1") ...[
isOutline: true, const SizedBox(height: 15),
onTap: () { const Divider(height: 1, color: Color(0xFFF5F5F5)),
controller.rejectReservation(item.id); const SizedBox(height: 12),
}, Align(
alignment: Alignment.centerRight,
child: _buildSmallButton(
"修改信息",
isOutline: true,
onTap: () {
controller.confirmReservation(item.id, isEdit: true);
},
),
), ),
const SizedBox(width: 12), ] else if (item.status == ReservationStatus.pending) ...[
_buildSmallButton( const SizedBox(height: 15),
"确认", const Divider(height: 1, color: Color(0xFFF5F5F5)),
isOutline: false, const SizedBox(height: 12),
onTap: () { Row(
controller.confirmReservation(item.id); mainAxisAlignment: MainAxisAlignment.end,
}, children: [
_buildSmallButton(
"拒绝",
isOutline: true,
onTap: () {
controller.rejectReservation(item.id);
},
),
const SizedBox(width: 12),
_buildSmallButton(
"确认",
isOutline: false,
onTap: () {
controller.confirmReservation(item.id);
},
),
],
), ),
], ],
), ],
], ),
], ],
), ),
); );
} }
/// 通用小按钮 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( Widget _buildSmallButton(
String text, { String text, {
required bool isOutline, required bool isOutline,
required VoidCallback onTap, required VoidCallback onTap,
}) { }) {
const kPrimaryGreen = Color(0xFF006D35); const kPrimaryGreen = Color(0xFF006D35);
const kDangerRed = Color(0xFFFF7D7D); var kDangerRed = text.contains('修改') ? Colors.red : Color.fromRGBO(255, 142, 98, 1);
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
@@ -634,139 +665,4 @@ class SitePage extends GetView<SiteController> {
), ),
); );
} }
/// 右侧操作按钮(拒绝/确认)
Widget _buildActionButtons(ReservationModel item) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
// 拒绝按钮(空心)
GestureDetector(
onTap: () => controller.rejectReservation(item.id),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: const Color(0xFFFF7D7D)),
),
child: const Text(
"拒绝",
style: TextStyle(
color: Color(0xFFFF7D7D),
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(width: 8),
// 确认按钮(实心深绿)
GestureDetector(
onTap: () => controller.confirmReservation(item.id),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
decoration: BoxDecoration(
color: const Color(0xFF006D35),
borderRadius: BorderRadius.circular(10),
),
child: const Text(
"确认",
style: TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
),
),
],
);
}
/// 构建状态标签
Widget _buildStatusChip(ReservationStatus status) {
String text;
Color color;
switch (status) {
case ReservationStatus.pending:
text = '待加氢';
color = Colors.orange;
break;
case ReservationStatus.completed:
text = '已加氢';
color = Colors.greenAccent;
break;
case ReservationStatus.rejected:
text = '拒绝加氢';
color = Colors.red;
break;
case ReservationStatus.unadded:
text = '未加氢';
color = Colors.red;
break;
case ReservationStatus.cancel:
text = '已取消';
color = Colors.red;
break;
default:
text = '未知状态';
color = Colors.grey;
break;
}
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.circle, color: color, size: 8),
const SizedBox(width: 4),
Text(
text,
style: TextStyle(color: color, fontSize: 12, fontWeight: FontWeight.bold),
),
],
),
);
}
/// 构建信息详情行
Widget _buildDetailRow(
IconData icon,
String label,
String value, {
Color valueColor = Colors.black87,
}) {
return Row(
children: [
Icon(icon, color: Colors.grey, size: 20),
const SizedBox(width: 8),
Text('$label: ', style: const TextStyle(fontSize: 14, color: Colors.grey)),
Expanded(
child: Text(
value,
style: TextStyle(
fontSize: 14,
color: valueColor,
fontWeight: FontWeight.w500,
),
),
),
],
);
}
/// 底部构建带图标的提示信息行
Widget _buildInfoItem(IconData icon, String text) {
return Row(
children: [
Icon(icon, color: Colors.blue, size: 20),
const SizedBox(width: 8),
Text(text, style: const TextStyle(fontSize: 14, color: Colors.black54)),
],
);
}
} }

View File

@@ -221,8 +221,12 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
stateName: '', stateName: '',
addStatus: '', addStatus: '',
addStatusName: '', addStatusName: '',
rejectReason: '',
hasEdit: true, hasEdit: true,
rejectReason: '',
isTruckAttachment: 0,
hasHydrogenationAttachment: true,
hasDrivingAttachment: true,
isEdit: '',
); );
//打开预约列表 //打开预约列表
@@ -546,7 +550,7 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
} }
try { try {
if(showloading){ if (showloading) {
showLoading("加氢站数据加载中"); showLoading("加氢站数据加载中");
} }