import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'vehicle_model.dart'; import 'vehicle_api.dart'; class VehicleApplyState { final VehicleModel vehicle; final bool isSubmitting; final bool hasConflict; final List passengers; const VehicleApplyState({ required this.vehicle, this.isSubmitting = false, this.hasConflict = false, this.passengers = const [], }); VehicleApplyState copyWith({ VehicleModel? vehicle, bool? isSubmitting, bool? hasConflict, List? passengers, }) => VehicleApplyState( vehicle: vehicle ?? this.vehicle, isSubmitting: isSubmitting ?? this.isSubmitting, hasConflict: hasConflict ?? this.hasConflict, passengers: passengers ?? this.passengers, ); } class VehicleApplyController extends StateNotifier { final VehicleApi _api; VehicleApplyController(this._api) : super( VehicleApplyState( vehicle: VehicleModel( id: '', applicationNo: '', applicantId: '', applicantName: '', deptId: '', deptName: '', purpose: '', reason: '', origin: '', destination: '', startTime: DateTime.now(), endTime: DateTime.now().add(const Duration(hours: 4)), createTime: DateTime.now(), updateTime: DateTime.now(), ), ), ); void updateVehicleId(String v) { state = state.copyWith( vehicle: state.vehicle.copyWith(vehicleId: v), ); _checkConflict(); } void updatePurpose(String v) => state = state.copyWith(vehicle: state.vehicle.copyWith(purpose: v)); void updateReason(String v) => state = state.copyWith(vehicle: state.vehicle.copyWith(reason: v)); void updateOrigin(String v) => state = state.copyWith(vehicle: state.vehicle.copyWith(origin: v)); void updateOriginCoords(double? lng, double? lat) => state = state.copyWith( vehicle: state.vehicle.copyWith( originLongitude: lng, originLatitude: lat, ), ); void updateDestination(String v) => state = state.copyWith(vehicle: state.vehicle.copyWith(destination: v)); void updateDestCoords(double? lng, double? lat) => state = state.copyWith( vehicle: state.vehicle.copyWith( destLongitude: lng, destLatitude: lat, ), ); void updateStartTime(DateTime t) { state = state.copyWith(vehicle: state.vehicle.copyWith(startTime: t)); _checkConflict(); } void updateEndTime(DateTime t) { state = state.copyWith(vehicle: state.vehicle.copyWith(endTime: t)); _checkConflict(); } void updatePassengerCount(int v) => state = state.copyWith( vehicle: state.vehicle.copyWith(passengerCount: v < 1 ? 1 : v), ); void addPassenger(String name) { if (!state.passengers.contains(name)) { state = state.copyWith(passengers: [...state.passengers, name]); } } void removePassenger(String name) { state = state.copyWith( passengers: state.passengers.where((p) => p != name).toList(), ); } /// Mock conflict detection void _checkConflict() { final vid = state.vehicle.vehicleId; if (vid.isEmpty) { state = state.copyWith(hasConflict: false); return; } // Mock: 车牌 '京A88888' 在所选时段冲突 final hasConflict = vid == '京A88888' && state.vehicle.startTime.isBefore( DateTime(2026, 6, 4, 12, 0), ); state = state.copyWith(hasConflict: hasConflict); } bool validate() { final v = state.vehicle; if (v.vehicleId.isEmpty) return false; if (v.reason.trim().isEmpty) return false; if (v.purpose.isEmpty) return false; if (!v.endTime.isAfter(v.startTime)) return false; if (state.hasConflict) return false; return true; } Future submit() async { if (!validate()) return false; state = state.copyWith(isSubmitting: true); try { await _api.submit(state.vehicle.copyWith(status: 'pending')); return true; } catch (_) { return false; } finally { state = state.copyWith(isSubmitting: false); } } Future saveDraft() async { state = state.copyWith(isSubmitting: true); try { await _api.saveDraft(state.vehicle); return true; } catch (_) { return false; } finally { state = state.copyWith(isSubmitting: false); } } } final vehicleApplyProvider = StateNotifierProvider.autoDispose .family((ref, editId) { return VehicleApplyController(ref.read(vehicleApiProvider)); });