站点 确认拒绝流程

This commit is contained in:
2025-12-08 09:32:06 +08:00
parent 88b16ca69e
commit a3fb0d8018
3 changed files with 271 additions and 22 deletions

View File

@@ -1,7 +1,9 @@
import 'dart:async';
import 'package:flutter/material.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';
import 'package:ln_jq_app/storage_service.dart';
enum ReservationStatus {
@@ -216,37 +218,282 @@ class SiteController extends GetxController with BaseControllerMixin {
/// 确认预约
Future<void> confirmReservation(String id) async {
final item = reservationList.firstWhere((item) => item.id == id);
DialogX.to.showConfirmDialog(
title: '确认预约',
message: '确定要确认车牌号${item.plateNumber}的预约吗',
onConfirm: () {
upDataService(id, 1, item);
},
onCancel: () {},
final item = reservationList.firstWhere(
(item) => item.id == id,
orElse: () => throw Exception('Reservation not found'),
);
final TextEditingController amountController = TextEditingController(
text: item.hydAmount,
);
Get.dialog(
Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), // 圆角
child: Padding(
padding: const EdgeInsets.only(top: 24.0),
child: Column(
mainAxisSize: MainAxisSize.min, // 高度自适应
children: [
const Text(
'确认加氢状态',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 5),
// content 部分
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
children: [
Text(
'车牌号 ${item.plateNumber}',
style: const TextStyle(
fontSize: 16,
color: AppTheme.themeColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'加氢量',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(width: 16),
SizedBox(
width: 100,
child: TextField(
controller: amountController,
textAlign: TextAlign.center,
keyboardType: const TextInputType.numberWithOptions(
decimal: true,
),
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Get.theme.primaryColor,
),
decoration: const InputDecoration(
suffixText: 'kg',
suffixStyle: TextStyle(fontSize: 16, color: Colors.grey),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 2),
),
),
),
),
],
),
const SizedBox(height: 12),
const Text(
'请选择本次加氢的实际状态\n用于更新预约记录。',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.grey),
),
],
),
),
const SizedBox(height: 24),
// actions 部分 (按钮)
Padding(
padding: const EdgeInsets.only(left: 24, right: 24, bottom: 24),
child: Column(
children: [
ElevatedButton(
onPressed: () {
Get.back(); // 关闭弹窗
final num addHydAmount = num.tryParse(amountController.text) ?? 0;
upDataService(id, 0, 1, addHydAmount, "", item);
},
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
child: const Text('加氢完成', style: TextStyle(fontSize: 16)),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () {
Get.back(); // 关闭弹窗
upDataService(id, 0, 2, 0, "", item);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange,
minimumSize: const Size(double.infinity, 48),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
child: const Text('未加氢', style: TextStyle(fontSize: 16)),
),
const SizedBox(height: 12),
TextButton(
onPressed: () => Get.back(), // 只关闭弹窗
child: const Text(
'暂不处理',
style: TextStyle(color: Colors.grey, fontSize: 14),
),
),
],
),
),
],
),
),
),
barrierDismissible: false, // 点击外部不关闭弹窗
);
}
/// 拒绝预约
Future<void> rejectReservation(String id) async {
final item = reservationList.firstWhere((item) => item.id == id);
DialogX.to.showConfirmDialog(
title: '拒绝预约',
message: '确定要拒绝车牌号${item.plateNumber}的预约吗',
onConfirm: () {
upDataService(id, 2, item);
},
onCancel: () {},
final TextEditingController reasonController = TextEditingController();
final RxString selectedReason = ''.obs;
// 预设的拒绝原因列表
final List<String> presetReasons = ['车辆未到场', '司机联系不上', '设备故障无法加氢'];
Get.dialog(
Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'拒绝预约',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16),
Text(
'正在处理车牌号 ${item.plateNumber} 的预约',
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16, color: AppTheme.themeColor),
),
const SizedBox(height: 24),
// 4. 预设原因选择区域
const Text('选择或填写拒绝原因:', style: TextStyle(color: Colors.grey)),
const SizedBox(height: 8),
Obx(
() => Wrap(
// 使用 Wrap 自动换行
spacing: 8.0, // 水平间距
children: presetReasons.map((reason) {
final isSelected = selectedReason.value == reason;
return ChoiceChip(
label: Text(reason),
selected: isSelected,
onSelected: (selected) {
if (selected) {
selectedReason.value = reason;
reasonController.clear(); // 选择预设原因时,清空自定义输入
}
},
selectedColor: Get.theme.primaryColor.withOpacity(0.2),
labelStyle: TextStyle(
color: isSelected ? Get.theme.primaryColor : Colors.black,
),
);
}).toList(),
),
),
const SizedBox(height: 16),
// 5. 自定义原因输入框
TextField(
controller: reasonController,
maxLines: 2,
decoration: InputDecoration(
hintText: '输入其它原因',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.grey.shade300),
),
),
onChanged: (text) {
if (text.isNotEmpty) {
selectedReason.value = ''; // 输入自定义原因时,取消预设选择
}
},
),
const SizedBox(height: 24),
// 6. 按钮区域
Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
// 获取最终的拒绝原因
String finalReason = reasonController.text.trim();
if (finalReason.isEmpty) {
finalReason = selectedReason.value;
}
if (finalReason.isEmpty) {
showToast('请选择或填写一个拒绝原因');
return;
}
Get.back(); // 关闭弹窗
upDataService(id, 1, -1, 0, finalReason, item);
},
child: const Text('确认拒绝', style: TextStyle(color: Colors.red)),
),
),
const SizedBox(width: 16),
Expanded(
child: TextButton(
onPressed: () => Get.back(),
child: const Text('暂不处理', style: TextStyle(color: Colors.grey)),
),
),
],
),
],
),
),
),
),
barrierDismissible: false,
);
}
void upDataService(String id, int status, ReservationModel item) async {
//addStatus 1完成 2未加 -1拒绝
void upDataService(
String id,
int status,
int addStatus,
num addHydAmount,
String rejectReason,
ReservationModel item,
) async {
showLoading("确认中");
try {
var responseData = await HttpService.to.post(
'appointment/orderAddHyd/completeOrder',
data: {'id': id, 'addStatus': status},
data: status == 0
? {
'id': id,
'addStatus': addStatus, //完成使用 完成1,未加2
"addHydAmount": addHydAmount,
}
: {
'id': id,
'state': addStatus, //拒绝使用 -1
"rejectReason": rejectReason,
},
);
if (responseData == null && responseData!.data == null) {
@@ -260,10 +507,12 @@ class SiteController extends GetxController with BaseControllerMixin {
}
dismissLoading();
if (status == 1) {
if (addStatus == 1) {
item.status = ReservationStatus.completed;
} else if (status == 2) {
} else if (addStatus == -1) {
item.status = ReservationStatus.rejected;
} else if (addStatus == -2) {
item.status = ReservationStatus.pending;
}
updateUi();
} catch (e) {

View File

@@ -408,7 +408,7 @@ class SitePage extends GetView<SiteController> {
child: ElevatedButton(
onPressed: () => controller.confirmReservation(item.id),
style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
child: const Text(''),
child: const Text(''),
),
),
const SizedBox(width: 16),

View File

@@ -307,7 +307,7 @@ class C_ReservationController extends GetxController with BaseControllerMixin {
if (lastSuccessfulReservation != null &&
lastSuccessfulReservation!.id == selectedStationId.value &&
lastSuccessfulReservation!.startTime == startTimeStr) {
showToast("请勿重复提交相同的预约");
showToast("请勿重复提交相同时间段的预约,可在“查看预约”中修改");
return;
}