feat: 完成智能电网电工端 Flutter 应用初始化
创建完整的 Flutter 项目结构,包含 Android 和 iOS 平台配置、核心网络层、路由、状态管理及业务模块(订单、收益、认证),适配原 uni-app 项目功能逻辑
This commit is contained in:
commit
56830e94ec
108 files changed
+9272
No files matched your search
@@ -0,0 +1,46 @@
|
||||
import '../../../core/network/api_client.dart';
|
||||
import '../../../core/network/api_response.dart';
|
||||
import 'order_models.dart';
|
||||
|
||||
/// 订单接口,对应后端 `/api/worker-app/orders*`。
|
||||
class OrderApi {
|
||||
OrderApi(this._client);
|
||||
|
||||
final ApiClient _client;
|
||||
|
||||
/// 订单池:四类未被接单的订单合并。
|
||||
Future<ApiResponse<List<Order>>> pool() => _client.get<List<Order>>(
|
||||
'/worker-app/orders/pool',
|
||||
parse: _parseList,
|
||||
);
|
||||
|
||||
/// 我的订单。`status` 传 `pending` / `completed`,留空取全部。
|
||||
Future<ApiResponse<List<Order>>> myOrders({String? status}) =>
|
||||
_client.get<List<Order>>(
|
||||
'/worker-app/orders',
|
||||
query: {'status': status},
|
||||
parse: _parseList,
|
||||
);
|
||||
|
||||
/// 订单详情。
|
||||
Future<ApiResponse<Order>> detail(String source, int id) =>
|
||||
_client.get<Order>(
|
||||
'/worker-app/orders/$source/$id',
|
||||
parse: (d) => Order.fromJson((d as Map).cast<String, dynamic>()),
|
||||
);
|
||||
|
||||
/// 接单。订单被他人接走时后端返回 409。
|
||||
Future<ApiResponse<void>> grab(String source, int id) =>
|
||||
_client.post<void>('/worker-app/orders/$source/$id/grab');
|
||||
|
||||
/// 完成订单。非本人订单后端返回 403。
|
||||
Future<ApiResponse<void>> complete(String source, int id) =>
|
||||
_client.put<void>('/worker-app/orders/$source/$id/complete');
|
||||
|
||||
static List<Order> _parseList(dynamic data) {
|
||||
final map = (data as Map).cast<String, dynamic>();
|
||||
return (map['list'] as List? ?? const [])
|
||||
.map((e) => Order.fromJson((e as Map).cast<String, dynamic>()))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import '../../../core/utils/id_util.dart';
|
||||
|
||||
/// 统一订单视图,对应后端 `WorkerAppService.toOrderView()`。
|
||||
///
|
||||
/// `id` 形如 `repair-12` / `install-5`,`source` 为四类来源之一。
|
||||
class Order {
|
||||
const Order({
|
||||
required this.id,
|
||||
required this.source,
|
||||
required this.status,
|
||||
required this.jobId,
|
||||
required this.title,
|
||||
required this.type,
|
||||
required this.amount,
|
||||
required this.distance,
|
||||
required this.schedule,
|
||||
required this.description,
|
||||
required this.customerName,
|
||||
required this.customerPhone,
|
||||
required this.photos,
|
||||
required this.address,
|
||||
required this.laborFee,
|
||||
required this.materialFee,
|
||||
required this.estimatedDuration,
|
||||
});
|
||||
|
||||
/// `repair-12`
|
||||
final String id;
|
||||
|
||||
/// repair | install | maintenance | survey
|
||||
final String source;
|
||||
|
||||
final int status;
|
||||
|
||||
/// 业务单号(repairNo / installNo / maintenanceNo / surveyNo)
|
||||
final String jobId;
|
||||
|
||||
final String title;
|
||||
|
||||
/// urgent | standard | regular
|
||||
final String type;
|
||||
|
||||
final double amount;
|
||||
final double distance;
|
||||
final String schedule;
|
||||
final String description;
|
||||
final String customerName;
|
||||
final String customerPhone;
|
||||
final List<String> photos;
|
||||
final String address;
|
||||
final double laborFee;
|
||||
final double materialFee;
|
||||
final String estimatedDuration;
|
||||
|
||||
/// 来源中文名,用于收益明细副标题等场景。
|
||||
String get sourceName => switch (source) {
|
||||
'repair' => '家庭电路维修',
|
||||
'install' => '设备安装',
|
||||
'maintenance' => '设备维保',
|
||||
'survey' => '现场勘察',
|
||||
_ => '服务订单',
|
||||
};
|
||||
|
||||
/// 列表页类型标签:紧急呼叫 / 标准预约 / 常规巡检。
|
||||
String get listTypeText => switch (type) {
|
||||
'urgent' => '紧急呼叫',
|
||||
'standard' => '标准预约',
|
||||
_ => '常规巡检',
|
||||
};
|
||||
|
||||
/// 详情页类型标签:紧急 / 标准 / 常规。
|
||||
String get detailTypeText => switch (type) {
|
||||
'urgent' => '紧急',
|
||||
'standard' => '标准',
|
||||
_ => '常规',
|
||||
};
|
||||
|
||||
/// 客户头像占位文字:后端无头像字段,用姓名首字(与「我的」页一致)。
|
||||
String get customerAvatarText => customerName.isEmpty
|
||||
? '客'
|
||||
: String.fromCharCode(customerName.runes.first);
|
||||
|
||||
/// 卡片上展示的订单号:后端 `id` 前缀即来源,取 `jobId` 更贴近源 `#EL-8821` 的观感。
|
||||
String get displayNo => jobId.isNotEmpty ? jobId : id;
|
||||
|
||||
/// 后端接口里的数字主键:`repair-12` → 12。
|
||||
int get intId {
|
||||
final idx = id.lastIndexOf('-');
|
||||
return toIntOr(idx >= 0 ? id.substring(idx + 1) : id, 0);
|
||||
}
|
||||
|
||||
factory Order.fromJson(Map<String, dynamic> json) => Order(
|
||||
id: json['id'] as String? ?? '',
|
||||
source: json['source'] as String? ?? '',
|
||||
status: toIntOr(json['status'], 0),
|
||||
jobId: json['jobId'] as String? ?? '',
|
||||
title: json['title'] as String? ?? '',
|
||||
type: json['type'] as String? ?? 'regular',
|
||||
amount: toDoubleOr(json['amount'], 0),
|
||||
distance: toDoubleOr(json['distance'], 0),
|
||||
schedule: json['schedule'] as String? ?? '',
|
||||
description: json['description'] as String? ?? '',
|
||||
customerName: json['customerName'] as String? ?? '',
|
||||
customerPhone: json['customerPhone'] as String? ?? '',
|
||||
photos:
|
||||
(json['photos'] as List?)?.map((e) => e.toString()).toList() ??
|
||||
const [],
|
||||
address: json['address'] as String? ?? '',
|
||||
laborFee: toDoubleOr(json['laborFee'], 0),
|
||||
materialFee: toDoubleOr(json['materialFee'], 0),
|
||||
estimatedDuration: json['estimatedDuration'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user