263 lines
8.5 KiB
Dart
263 lines
8.5 KiB
Dart
import 'package:autosos_flutter/model/user.dart';
|
||
|
||
/// 订单状态枚举(对应 Android ui.order.* 状态机)
|
||
enum OrderStatus {
|
||
pending, // 待处理(check 阶段)
|
||
waiting, // 等待接单
|
||
accepted, // 已接单
|
||
conducting, // 救援中
|
||
photographing, // 拍照取证
|
||
signing, // 客户签名
|
||
collecting, // 收款中
|
||
completed, // 已完成
|
||
cancelled, // 已取消
|
||
offline, // 离线模式
|
||
unknown,
|
||
}
|
||
|
||
extension OrderStatusX on OrderStatus {
|
||
String get label {
|
||
switch (this) {
|
||
case OrderStatus.pending: return '待核单';
|
||
case OrderStatus.waiting: return '等待接单';
|
||
case OrderStatus.accepted: return '已接单';
|
||
case OrderStatus.conducting: return '救援中';
|
||
case OrderStatus.photographing: return '拍照取证';
|
||
case OrderStatus.signing: return '客户签字';
|
||
case OrderStatus.collecting: return '收款中';
|
||
case OrderStatus.completed: return '已完成';
|
||
case OrderStatus.cancelled: return '已取消';
|
||
case OrderStatus.offline: return '离线模式';
|
||
case OrderStatus.unknown: return '未知';
|
||
}
|
||
}
|
||
|
||
static OrderStatus fromString(String? s) {
|
||
switch (s) {
|
||
case 'pending': return OrderStatus.pending;
|
||
case 'waiting': return OrderStatus.waiting;
|
||
case 'accepted': return OrderStatus.accepted;
|
||
case 'conducting': return OrderStatus.conducting;
|
||
case 'photographing': return OrderStatus.photographing;
|
||
case 'signing': return OrderStatus.signing;
|
||
case 'collecting': return OrderStatus.collecting;
|
||
case 'completed': return OrderStatus.completed;
|
||
case 'cancelled': return OrderStatus.cancelled;
|
||
case 'offline': return OrderStatus.offline;
|
||
default: return OrderStatus.unknown;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 订单主体(对应 Android OrderDetailEntity / OrderList)
|
||
class Order {
|
||
final int id;
|
||
final String orderNo; // 订单编号
|
||
final OrderStatus status;
|
||
final String serviceType; // 救援类型:非事故拖车、事故拖车、应急搭电等
|
||
final String? address; // 救援地点
|
||
final double? lat;
|
||
final double? lng;
|
||
final String? customerName;
|
||
final String? customerPhone;
|
||
final String? carNo; // 车牌号
|
||
final String? carType; // 车型
|
||
final String? description; // 描述/备注
|
||
final double amount; // 总金额
|
||
final double? mileage; // 拖车里程
|
||
final DateTime createdAt;
|
||
final DateTime? acceptedAt;
|
||
final DateTime? arrivedAt;
|
||
final DateTime? completedAt;
|
||
final List<String> photoUrls; // 现场照片
|
||
final String? signatureUrl; // 客户签字
|
||
final String? payMethod; // wx / cash
|
||
final UserInfo? technician; // 接单技师
|
||
|
||
const Order({
|
||
required this.id,
|
||
required this.orderNo,
|
||
required this.status,
|
||
required this.serviceType,
|
||
required this.amount,
|
||
required this.createdAt,
|
||
this.address,
|
||
this.lat,
|
||
this.lng,
|
||
this.customerName,
|
||
this.customerPhone,
|
||
this.carNo,
|
||
this.carType,
|
||
this.description,
|
||
this.mileage,
|
||
this.acceptedAt,
|
||
this.arrivedAt,
|
||
this.completedAt,
|
||
this.photoUrls = const [],
|
||
this.signatureUrl,
|
||
this.payMethod,
|
||
this.technician,
|
||
});
|
||
|
||
factory Order.fromJson(Map<String, dynamic> json) {
|
||
return Order(
|
||
id: json['id'] as int? ?? 0,
|
||
orderNo: json['order_no'] as String? ?? '',
|
||
status: OrderStatusX.fromString(json['status'] as String?),
|
||
serviceType: json['service_type'] as String? ?? '',
|
||
address: json['address'] as String?,
|
||
lat: (json['lat'] as num?)?.toDouble(),
|
||
lng: (json['lng'] as num?)?.toDouble(),
|
||
customerName: json['customer_name'] as String?,
|
||
customerPhone: json['customer_phone'] as String?,
|
||
carNo: json['car_no'] as String?,
|
||
carType: json['car_type'] as String?,
|
||
description: json['description'] as String?,
|
||
amount: (json['amount'] as num?)?.toDouble() ?? 0,
|
||
mileage: (json['mileage'] as num?)?.toDouble(),
|
||
createdAt: DateTime.tryParse(json['created_at'] as String? ?? '') ??
|
||
DateTime.now(),
|
||
acceptedAt: json['accepted_at'] != null
|
||
? DateTime.tryParse(json['accepted_at'] as String)
|
||
: null,
|
||
arrivedAt: json['arrived_at'] != null
|
||
? DateTime.tryParse(json['arrived_at'] as String)
|
||
: null,
|
||
completedAt: json['completed_at'] != null
|
||
? DateTime.tryParse(json['completed_at'] as String)
|
||
: null,
|
||
photoUrls: (json['photo_urls'] as List?)?.cast<String>() ?? const [],
|
||
signatureUrl: json['signature_url'] as String?,
|
||
payMethod: json['pay_method'] as String?,
|
||
technician: json['technician'] != null
|
||
? UserInfo.fromJson(json['technician'] as Map<String, dynamic>)
|
||
: null,
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() => {
|
||
'id': id,
|
||
'order_no': orderNo,
|
||
'status': status.name,
|
||
'service_type': serviceType,
|
||
'address': address,
|
||
'lat': lat,
|
||
'lng': lng,
|
||
'customer_name': customerName,
|
||
'customer_phone': customerPhone,
|
||
'car_no': carNo,
|
||
'car_type': carType,
|
||
'description': description,
|
||
'amount': amount,
|
||
'mileage': mileage,
|
||
'created_at': createdAt.toIso8601String(),
|
||
'accepted_at': acceptedAt?.toIso8601String(),
|
||
'arrived_at': arrivedAt?.toIso8601String(),
|
||
'completed_at': completedAt?.toIso8601String(),
|
||
'photo_urls': photoUrls,
|
||
'signature_url': signatureUrl,
|
||
'pay_method': payMethod,
|
||
};
|
||
|
||
Order copyWith({
|
||
OrderStatus? status,
|
||
double? amount,
|
||
DateTime? arrivedAt,
|
||
DateTime? completedAt,
|
||
List<String>? photoUrls,
|
||
String? signatureUrl,
|
||
String? payMethod,
|
||
}) {
|
||
return Order(
|
||
id: id,
|
||
orderNo: orderNo,
|
||
status: status ?? this.status,
|
||
serviceType: serviceType,
|
||
address: address,
|
||
lat: lat,
|
||
lng: lng,
|
||
customerName: customerName,
|
||
customerPhone: customerPhone,
|
||
carNo: carNo,
|
||
carType: carType,
|
||
description: description,
|
||
amount: amount ?? this.amount,
|
||
mileage: mileage,
|
||
createdAt: createdAt,
|
||
acceptedAt: acceptedAt,
|
||
arrivedAt: arrivedAt ?? this.arrivedAt,
|
||
completedAt: completedAt ?? this.completedAt,
|
||
photoUrls: photoUrls ?? this.photoUrls,
|
||
signatureUrl: signatureUrl ?? this.signatureUrl,
|
||
payMethod: payMethod ?? this.payMethod,
|
||
technician: technician,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 核单列表项(对应 Android CheckItemViewModel)
|
||
class CheckItem {
|
||
final int orderId;
|
||
final String orderNo;
|
||
final String serviceType;
|
||
final String? address;
|
||
final DateTime createdAt;
|
||
final double amount;
|
||
final bool checked; // 是否已核单
|
||
|
||
const CheckItem({
|
||
required this.orderId,
|
||
required this.orderNo,
|
||
required this.serviceType,
|
||
required this.createdAt,
|
||
required this.amount,
|
||
this.address,
|
||
this.checked = false,
|
||
});
|
||
|
||
factory CheckItem.fromJson(Map<String, dynamic> json) => CheckItem(
|
||
orderId: json['order_id'] as int? ?? 0,
|
||
orderNo: json['order_no'] as String? ?? '',
|
||
serviceType: json['service_type'] as String? ?? '',
|
||
address: json['address'] as String?,
|
||
createdAt: DateTime.tryParse(json['created_at'] as String? ?? '') ??
|
||
DateTime.now(),
|
||
amount: (json['amount'] as num?)?.toDouble() ?? 0,
|
||
checked: json['checked'] as bool? ?? false,
|
||
);
|
||
}
|
||
|
||
/// 等待接单项(对应 Android OrderWaitingItemViewModel)
|
||
class WaitingOrder {
|
||
final int orderId;
|
||
final String orderNo;
|
||
final String serviceType;
|
||
final String? address;
|
||
final double? distance; // 距离技师当前位置
|
||
final double amount;
|
||
final DateTime createdAt;
|
||
final int countdown; // 接单倒计时(秒)
|
||
|
||
const WaitingOrder({
|
||
required this.orderId,
|
||
required this.orderNo,
|
||
required this.serviceType,
|
||
required this.amount,
|
||
required this.createdAt,
|
||
required this.countdown,
|
||
this.address,
|
||
this.distance,
|
||
});
|
||
|
||
factory WaitingOrder.fromJson(Map<String, dynamic> json) => WaitingOrder(
|
||
orderId: json['order_id'] as int? ?? 0,
|
||
orderNo: json['order_no'] as String? ?? '',
|
||
serviceType: json['service_type'] as String? ?? '',
|
||
address: json['address'] as String?,
|
||
distance: (json['distance'] as num?)?.toDouble(),
|
||
amount: (json['amount'] as num?)?.toDouble() ?? 0,
|
||
createdAt: DateTime.tryParse(json['created_at'] as String? ?? '') ??
|
||
DateTime.now(),
|
||
countdown: json['countdown'] as int? ?? 0,
|
||
);
|
||
} |