一次大的提交
This commit is contained in:
@@ -1,12 +1,35 @@
|
||||
import '../models/workorder_model.dart';
|
||||
|
||||
/// 工单远程数据源抽象类
|
||||
abstract class WorkOrderRemoteDataSource {
|
||||
/// 获取工单列表
|
||||
Future<List<WorkOrderModel>> getWorkOrderList({
|
||||
String? status,
|
||||
required int page,
|
||||
required int pageSize,
|
||||
int? siteId,
|
||||
int? orgId,
|
||||
});
|
||||
|
||||
/// 获取工单统计
|
||||
Future<WorkOrderCountModel> getWorkOrderCount();
|
||||
|
||||
Future<WorkOrderModel> getWorkOrderDetail(
|
||||
String orderId, {
|
||||
int? siteId,
|
||||
int? orgId,
|
||||
});
|
||||
|
||||
Future<List<Map<String, dynamic>>> fetchUsers({
|
||||
required int orgId,
|
||||
required int siteId,
|
||||
});
|
||||
|
||||
Future<void> dispatchWorkOrder({
|
||||
required String orderId,
|
||||
required String assigneeId,
|
||||
required String assigneeName,
|
||||
String? dispatchRemark,
|
||||
String? collaboratorIds,
|
||||
String? collaboratorNames,
|
||||
String? planStartTime,
|
||||
String? planEndTime,
|
||||
String? deadlineTime,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,87 +1,145 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import '../../../../../core/consts/http_api_consts.dart';
|
||||
import '../../../../../core/consts/workorder_consts.dart';
|
||||
import 'workorder_remote_datasource.dart';
|
||||
import '../models/workorder_model.dart';
|
||||
|
||||
/// 工单远程数据源实现(模拟数据)
|
||||
class WorkOrderRemoteDataSourceImpl implements WorkOrderRemoteDataSource {
|
||||
WorkOrderRemoteDataSourceImpl(this._dio);
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
@override
|
||||
Future<List<WorkOrderModel>> getWorkOrderList({String? status}) async {
|
||||
// 模拟网络延迟
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
Future<List<WorkOrderModel>> getWorkOrderList({
|
||||
required int page,
|
||||
required int pageSize,
|
||||
int? siteId,
|
||||
int? orgId,
|
||||
}) async {
|
||||
final queryParameters = {'page': page, 'pageSize': pageSize};
|
||||
if (siteId != null) {
|
||||
queryParameters['siteId'] = siteId;
|
||||
}
|
||||
if (orgId != null) {
|
||||
queryParameters['orgId'] = orgId;
|
||||
}
|
||||
final response = await _dio.get(
|
||||
HttpApiConsts.workOrderList,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
|
||||
// 模拟数据
|
||||
final allOrders = [
|
||||
WorkOrderModel(
|
||||
id: '1',
|
||||
title: '逆变器通讯故障处理',
|
||||
orderNo: 'WO-20250521001',
|
||||
priority: WorkOrderPriority.high,
|
||||
executor: null,
|
||||
createTime: DateTime(2025, 5, 21, 10, 12),
|
||||
completeTime: null,
|
||||
location: 'A区 / INV-001',
|
||||
status: WorkOrderStatus.pending,
|
||||
progress: null,
|
||||
),
|
||||
WorkOrderModel(
|
||||
id: '2',
|
||||
title: '组件清洗作业',
|
||||
orderNo: 'WO-20250521002',
|
||||
priority: WorkOrderPriority.medium,
|
||||
executor: '张工',
|
||||
createTime: DateTime(2025, 5, 21, 9, 30),
|
||||
completeTime: null,
|
||||
location: 'B区',
|
||||
status: WorkOrderStatus.executing,
|
||||
progress: 60.0,
|
||||
),
|
||||
WorkOrderModel(
|
||||
id: '3',
|
||||
title: '汇流箱巡检',
|
||||
orderNo: 'WO-20250520098',
|
||||
priority: WorkOrderPriority.low,
|
||||
executor: '李工',
|
||||
createTime: DateTime(2025, 5, 20, 14, 20),
|
||||
completeTime: DateTime(2025, 5, 20, 16, 32),
|
||||
location: 'C区',
|
||||
status: WorkOrderStatus.completed,
|
||||
progress: 100.0,
|
||||
),
|
||||
];
|
||||
|
||||
// 根据状态筛选
|
||||
if (status != null && status != 'all') {
|
||||
return allOrders
|
||||
.where((order) => _statusToString(order.status) == status)
|
||||
.toList();
|
||||
final responseData = response.data;
|
||||
final int code = responseData['code'] ?? -1;
|
||||
if (code != 0 && code != 200) {
|
||||
throw Exception('获取工单列表失败: code=$code');
|
||||
}
|
||||
|
||||
return allOrders;
|
||||
final List<dynamic> rows = responseData['rows'] ?? [];
|
||||
return rows
|
||||
.map((item) => WorkOrderModel.fromJson(item as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WorkOrderCountModel> getWorkOrderCount() async {
|
||||
// 模拟网络延迟
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// 模拟统计数据
|
||||
return WorkOrderCountModel(
|
||||
pendingCount: 12,
|
||||
executingCount: 8,
|
||||
todayCompletedCount: 18,
|
||||
final response = await _dio.get(HttpApiConsts.workOrderCount);
|
||||
final responseData = response.data;
|
||||
final int code = responseData['code'] ?? -1;
|
||||
if (code != 0 && code != 200) {
|
||||
throw Exception('获取工单统计失败: code=$code');
|
||||
}
|
||||
return WorkOrderCountModel.fromJson(
|
||||
responseData['data'] as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
|
||||
String _statusToString(WorkOrderStatus status) {
|
||||
switch (status) {
|
||||
case WorkOrderStatus.pending:
|
||||
return 'pending';
|
||||
case WorkOrderStatus.executing:
|
||||
return 'executing';
|
||||
case WorkOrderStatus.completed:
|
||||
return 'completed';
|
||||
case WorkOrderStatus.all:
|
||||
return 'all';
|
||||
@override
|
||||
Future<WorkOrderModel> getWorkOrderDetail(
|
||||
String orderId, {
|
||||
int? siteId,
|
||||
int? orgId,
|
||||
}) async {
|
||||
final queryParameters = <String, dynamic>{};
|
||||
if (siteId != null) {
|
||||
queryParameters['siteId'] = siteId;
|
||||
}
|
||||
if (orgId != null) {
|
||||
queryParameters['orgId'] = orgId;
|
||||
}
|
||||
final response = await _dio.get(
|
||||
'${HttpApiConsts.workOrderDetail}/$orderId',
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
|
||||
final responseData = response.data;
|
||||
final int code = responseData['code'] ?? -1;
|
||||
if (code != 0 && code != 200) {
|
||||
throw Exception('获取工单详情失败: code=$code');
|
||||
}
|
||||
|
||||
final data = responseData['data'];
|
||||
if (data == null) {
|
||||
throw Exception('工单详情数据为空');
|
||||
}
|
||||
|
||||
return WorkOrderModel.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> fetchUsers({
|
||||
required int orgId,
|
||||
required int siteId,
|
||||
}) async {
|
||||
final response = await _dio.get(
|
||||
HttpApiConsts.systemUserList,
|
||||
queryParameters: {
|
||||
'pageNum': 1,
|
||||
'pageSize': 99999,
|
||||
'orgId': orgId,
|
||||
'siteId': siteId,
|
||||
},
|
||||
);
|
||||
|
||||
final responseData = response.data;
|
||||
final int code = responseData['code'] ?? -1;
|
||||
if (code != 0 && code != 200) {
|
||||
throw Exception('获取人员列表失败: code=$code');
|
||||
}
|
||||
|
||||
final List<dynamic> rows =
|
||||
responseData['rows'] ?? responseData['data'] ?? [];
|
||||
return rows.cast<Map<String, dynamic>>();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> dispatchWorkOrder({
|
||||
required String orderId,
|
||||
required String assigneeId,
|
||||
required String assigneeName,
|
||||
String? dispatchRemark,
|
||||
String? collaboratorIds,
|
||||
String? collaboratorNames,
|
||||
String? planStartTime,
|
||||
String? planEndTime,
|
||||
String? deadlineTime,
|
||||
}) async {
|
||||
final data = <String, dynamic>{
|
||||
'orderId': orderId,
|
||||
'assigneeId': assigneeId,
|
||||
'assigneeName': assigneeName,
|
||||
'collaboratorIds': collaboratorIds ?? '',
|
||||
'collaboratorNames': collaboratorNames ?? '',
|
||||
'planStartTime': planStartTime ?? '',
|
||||
'planEndTime': planEndTime ?? '',
|
||||
'deadlineTime': deadlineTime ?? '',
|
||||
};
|
||||
|
||||
final response = await _dio.post(HttpApiConsts.workOrderDispat, data: data);
|
||||
|
||||
final responseData = response.data;
|
||||
final int code = responseData['code'] ?? -1;
|
||||
if (code != 0 && code != 200) {
|
||||
throw Exception('转派工单失败: ${responseData['msg'] ?? '未知错误'}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,140 @@
|
||||
import '../../../../../core/consts/workorder_consts.dart';
|
||||
import '../../domain/entities/workorder_entity.dart';
|
||||
import 'dart:developer' as developer;
|
||||
|
||||
/// 设备对象数据模型
|
||||
class DeviceObjectModel {
|
||||
final String deviceName;
|
||||
final String deviceType;
|
||||
final String assetCode;
|
||||
|
||||
DeviceObjectModel({
|
||||
required this.deviceName,
|
||||
required this.deviceType,
|
||||
required this.assetCode,
|
||||
});
|
||||
|
||||
factory DeviceObjectModel.fromJson(Map<String, dynamic> json) {
|
||||
return DeviceObjectModel(
|
||||
deviceName: json['deviceName'] as String? ?? '',
|
||||
deviceType: json['deviceType'] as String? ?? '',
|
||||
assetCode: json['assetCode'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'deviceName': deviceName,
|
||||
'deviceType': deviceType,
|
||||
'assetCode': assetCode,
|
||||
};
|
||||
}
|
||||
|
||||
DeviceObjectEntity toEntity() {
|
||||
return DeviceObjectEntity(
|
||||
deviceName: deviceName,
|
||||
deviceType: deviceType,
|
||||
assetCode: assetCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 地点数据模型
|
||||
class LocationModel {
|
||||
final String stationName;
|
||||
final String area;
|
||||
final String region;
|
||||
final String detailAddress;
|
||||
|
||||
LocationModel({
|
||||
required this.stationName,
|
||||
required this.area,
|
||||
required this.region,
|
||||
required this.detailAddress,
|
||||
});
|
||||
|
||||
factory LocationModel.fromJson(Map<String, dynamic> json) {
|
||||
return LocationModel(
|
||||
stationName: json['stationName'] as String? ?? '',
|
||||
area: json['area'] as String? ?? '',
|
||||
region: json['region'] as String? ?? '',
|
||||
detailAddress: json['detailAddress'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'stationName': stationName,
|
||||
'area': area,
|
||||
'region': region,
|
||||
'detailAddress': detailAddress,
|
||||
};
|
||||
}
|
||||
|
||||
LocationEntity toEntity() {
|
||||
return LocationEntity(
|
||||
stationName: stationName,
|
||||
area: area,
|
||||
region: region,
|
||||
detailAddress: detailAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 时限要求数据模型
|
||||
class TimeLimitModel {
|
||||
final String expectedCompleteTime;
|
||||
final String remainingTime;
|
||||
|
||||
TimeLimitModel({
|
||||
required this.expectedCompleteTime,
|
||||
required this.remainingTime,
|
||||
});
|
||||
|
||||
factory TimeLimitModel.fromJson(Map<String, dynamic> json) {
|
||||
return TimeLimitModel(
|
||||
expectedCompleteTime: json['expectedCompleteTime'] as String? ?? '',
|
||||
remainingTime: json['remainingTime'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'expectedCompleteTime': expectedCompleteTime,
|
||||
'remainingTime': remainingTime,
|
||||
};
|
||||
}
|
||||
|
||||
TimeLimitEntity toEntity() {
|
||||
return TimeLimitEntity(
|
||||
expectedCompleteTime: expectedCompleteTime,
|
||||
remainingTime: remainingTime,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 附件数据模型
|
||||
class AttachmentModel {
|
||||
final String fileName;
|
||||
final String url;
|
||||
|
||||
AttachmentModel({required this.fileName, required this.url});
|
||||
|
||||
factory AttachmentModel.fromJson(Map<String, dynamic> json) {
|
||||
return AttachmentModel(
|
||||
fileName: json['fileName'] as String? ?? '',
|
||||
url: json['url'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'fileName': fileName, 'url': url};
|
||||
}
|
||||
|
||||
AttachmentEntity toEntity() {
|
||||
return AttachmentEntity(fileName: fileName, url: url);
|
||||
}
|
||||
}
|
||||
|
||||
/// 工单数据模型
|
||||
class WorkOrderModel {
|
||||
@@ -13,6 +148,34 @@ class WorkOrderModel {
|
||||
final String location;
|
||||
final WorkOrderStatus status;
|
||||
final double? progress;
|
||||
final String? source;
|
||||
final DeviceObjectModel? deviceObject;
|
||||
final LocationModel? locationDetail;
|
||||
final TimeLimitModel? timeLimit;
|
||||
final String? description;
|
||||
final List<AttachmentModel>? attachments;
|
||||
final String? orderType;
|
||||
final String? alarmId;
|
||||
final String? alarmNo;
|
||||
final String? handleResult;
|
||||
final String? handleRemark;
|
||||
final String? planStartTime;
|
||||
final String? planEndTime;
|
||||
final String? siteName;
|
||||
final String? deviceId;
|
||||
final String? deviceName;
|
||||
final String? deviceType;
|
||||
final String? assigneeName;
|
||||
final String? aiSuggestion;
|
||||
final String? requiredEquipment;
|
||||
final String? estimatedImpact;
|
||||
final String? taskDescription;
|
||||
final String? actualStartTime;
|
||||
final String? actualEndTime;
|
||||
final String? deadlineTime;
|
||||
final int? sourceType;
|
||||
final List<String>? videoUrls;
|
||||
final String? updateTime;
|
||||
|
||||
WorkOrderModel({
|
||||
required this.id,
|
||||
@@ -25,27 +188,118 @@ class WorkOrderModel {
|
||||
required this.location,
|
||||
required this.status,
|
||||
this.progress,
|
||||
this.source,
|
||||
this.deviceObject,
|
||||
this.locationDetail,
|
||||
this.timeLimit,
|
||||
this.description,
|
||||
this.attachments,
|
||||
this.orderType,
|
||||
this.alarmId,
|
||||
this.alarmNo,
|
||||
this.handleResult,
|
||||
this.handleRemark,
|
||||
this.planStartTime,
|
||||
this.planEndTime,
|
||||
this.siteName,
|
||||
this.deviceId,
|
||||
this.deviceName,
|
||||
this.deviceType,
|
||||
this.assigneeName,
|
||||
this.aiSuggestion,
|
||||
this.requiredEquipment,
|
||||
this.estimatedImpact,
|
||||
this.taskDescription,
|
||||
this.actualStartTime,
|
||||
this.actualEndTime,
|
||||
this.deadlineTime,
|
||||
this.sourceType,
|
||||
this.videoUrls,
|
||||
this.updateTime,
|
||||
});
|
||||
|
||||
/// 从 JSON 创建
|
||||
factory WorkOrderModel.fromJson(Map<String, dynamic> json) {
|
||||
final attachments = _parseAttachments(json);
|
||||
final videoUrls = _parseVideoUrls(json);
|
||||
|
||||
developer.log(
|
||||
'WorkOrderModel.fromJson keys: ${json.keys.toList()}',
|
||||
name: 'WorkOrder',
|
||||
);
|
||||
developer.log(
|
||||
'attachments: ${attachments?.length ?? 0}',
|
||||
name: 'WorkOrder',
|
||||
);
|
||||
developer.log('videoUrls: ${videoUrls?.length ?? 0}', name: 'WorkOrder');
|
||||
|
||||
return WorkOrderModel(
|
||||
id: json['id'] as String,
|
||||
title: json['title'] as String,
|
||||
orderNo: json['orderNo'] as String,
|
||||
priority: _parsePriority(json['priority'] as String),
|
||||
executor: json['executor'] as String?,
|
||||
createTime: DateTime.parse(json['createTime'] as String),
|
||||
completeTime: json['completeTime'] != null
|
||||
? DateTime.parse(json['completeTime'] as String)
|
||||
id: (json['id'] as dynamic)?.toString() ?? '',
|
||||
title: json['orderTitle'] as String? ?? '',
|
||||
orderNo: json['orderNo'] as String? ?? '',
|
||||
priority: _parsePriority(json['priorityLevel'] as String? ?? 'medium'),
|
||||
executor: json['assigneeName'] as String?,
|
||||
createTime: DateTime.parse(
|
||||
json['createTime'] as String? ?? '2026-01-01 00:00:00',
|
||||
),
|
||||
completeTime: json['actualEndTime'] != null
|
||||
? DateTime.parse(json['actualEndTime'] as String)
|
||||
: null,
|
||||
location: json['location'] as String,
|
||||
status: _parseStatus(json['status'] as String),
|
||||
progress: json['progress'] as double?,
|
||||
location: json['siteName'] as String? ?? '',
|
||||
status: _parseStatusFromInt(json['orderStatus'] as int? ?? 1),
|
||||
progress: (json['progress'] as dynamic)?.toDouble(),
|
||||
source: _parseSourceType(json['sourceType'] as int? ?? 0),
|
||||
deviceObject: json['deviceName'] != null
|
||||
? DeviceObjectModel(
|
||||
deviceName: json['deviceName'] as String? ?? '',
|
||||
deviceType: json['deviceType'] as String? ?? '',
|
||||
assetCode: json['deviceId'] as String? ?? '',
|
||||
)
|
||||
: null,
|
||||
locationDetail: json['siteName'] != null
|
||||
? LocationModel(
|
||||
stationName: json['siteName'] as String? ?? '',
|
||||
area: json['area'] as String? ?? '',
|
||||
region: json['region'] as String? ?? '',
|
||||
detailAddress: json['detailAddress'] as String? ?? '',
|
||||
)
|
||||
: null,
|
||||
timeLimit: json['planEndTime'] != null
|
||||
? TimeLimitModel(
|
||||
expectedCompleteTime: json['planEndTime'] as String? ?? '',
|
||||
remainingTime: '',
|
||||
)
|
||||
: null,
|
||||
description: json['taskDescription'] as String?,
|
||||
attachments: attachments,
|
||||
orderType: json['orderType'] as String?,
|
||||
alarmId: (json['alarmId'] as dynamic)?.toString(),
|
||||
alarmNo: json['alarmNo'] as String?,
|
||||
handleResult: json['handleResult'] as String?,
|
||||
handleRemark: json['handleRemark'] as String?,
|
||||
planStartTime: json['planStartTime'] as String?,
|
||||
planEndTime: json['planEndTime'] as String?,
|
||||
siteName: json['siteName'] as String?,
|
||||
deviceId: json['deviceId'] as String?,
|
||||
deviceName: json['deviceName'] as String?,
|
||||
deviceType: json['deviceType'] as String?,
|
||||
assigneeName:
|
||||
json['assigneeName'] as String? ??
|
||||
json['executorName'] as String? ??
|
||||
json['executor'] as String? ??
|
||||
json['assignee'] as String?,
|
||||
aiSuggestion: json['aiSuggestion'] as String?,
|
||||
requiredEquipment: json['requiredEquipment'] as String?,
|
||||
estimatedImpact: json['estimatedImpact'] as String?,
|
||||
taskDescription: json['taskDescription'] as String?,
|
||||
actualStartTime: json['actualStartTime'] as String?,
|
||||
actualEndTime: json['actualEndTime'] as String?,
|
||||
deadlineTime: json['deadlineTime'] as String?,
|
||||
sourceType: json['sourceType'] as int?,
|
||||
videoUrls: videoUrls,
|
||||
updateTime: json['updateTime'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// 转换为 JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
@@ -58,10 +312,15 @@ class WorkOrderModel {
|
||||
'location': location,
|
||||
'status': _statusToString(status),
|
||||
'progress': progress,
|
||||
'source': source,
|
||||
'deviceObject': deviceObject?.toJson(),
|
||||
'locationDetail': locationDetail?.toJson(),
|
||||
'timeLimit': timeLimit?.toJson(),
|
||||
'description': description,
|
||||
'attachments': attachments?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
/// 转换为实体
|
||||
WorkOrderEntity toEntity() {
|
||||
return WorkOrderEntity(
|
||||
id: id,
|
||||
@@ -74,10 +333,37 @@ class WorkOrderModel {
|
||||
location: location,
|
||||
status: status,
|
||||
progress: progress,
|
||||
source: source,
|
||||
deviceObject: deviceObject?.toEntity(),
|
||||
locationDetail: locationDetail?.toEntity(),
|
||||
timeLimit: timeLimit?.toEntity(),
|
||||
description: description,
|
||||
attachments: attachments?.map((e) => e.toEntity()).toList(),
|
||||
orderType: orderType,
|
||||
alarmId: alarmId,
|
||||
alarmNo: alarmNo,
|
||||
handleResult: handleResult,
|
||||
handleRemark: handleRemark,
|
||||
planStartTime: planStartTime,
|
||||
planEndTime: planEndTime,
|
||||
siteName: siteName,
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
deviceType: deviceType,
|
||||
assigneeName: assigneeName,
|
||||
aiSuggestion: aiSuggestion,
|
||||
requiredEquipment: requiredEquipment,
|
||||
estimatedImpact: estimatedImpact,
|
||||
taskDescription: taskDescription,
|
||||
actualStartTime: actualStartTime,
|
||||
actualEndTime: actualEndTime,
|
||||
deadlineTime: deadlineTime,
|
||||
sourceType: sourceType,
|
||||
videoUrls: videoUrls,
|
||||
updateTime: updateTime,
|
||||
);
|
||||
}
|
||||
|
||||
/// 从实体创建
|
||||
factory WorkOrderModel.fromEntity(WorkOrderEntity entity) {
|
||||
return WorkOrderModel(
|
||||
id: entity.id,
|
||||
@@ -90,17 +376,217 @@ class WorkOrderModel {
|
||||
location: entity.location,
|
||||
status: entity.status,
|
||||
progress: entity.progress,
|
||||
source: entity.source,
|
||||
deviceObject: entity.deviceObject != null
|
||||
? DeviceObjectModel(
|
||||
deviceName: entity.deviceObject!.deviceName,
|
||||
deviceType: entity.deviceObject!.deviceType,
|
||||
assetCode: entity.deviceObject!.assetCode,
|
||||
)
|
||||
: null,
|
||||
locationDetail: entity.locationDetail != null
|
||||
? LocationModel(
|
||||
stationName: entity.locationDetail!.stationName,
|
||||
area: entity.locationDetail!.area,
|
||||
region: entity.locationDetail!.region,
|
||||
detailAddress: entity.locationDetail!.detailAddress,
|
||||
)
|
||||
: null,
|
||||
timeLimit: entity.timeLimit != null
|
||||
? TimeLimitModel(
|
||||
expectedCompleteTime: entity.timeLimit!.expectedCompleteTime,
|
||||
remainingTime: entity.timeLimit!.remainingTime,
|
||||
)
|
||||
: null,
|
||||
description: entity.description,
|
||||
attachments: entity.attachments
|
||||
?.map((e) => AttachmentModel(fileName: e.fileName, url: e.url))
|
||||
.toList(),
|
||||
orderType: entity.orderType,
|
||||
alarmId: entity.alarmId,
|
||||
alarmNo: entity.alarmNo,
|
||||
handleResult: entity.handleResult,
|
||||
handleRemark: entity.handleRemark,
|
||||
planStartTime: entity.planStartTime,
|
||||
planEndTime: entity.planEndTime,
|
||||
siteName: entity.siteName,
|
||||
deviceId: entity.deviceId,
|
||||
deviceName: entity.deviceName,
|
||||
deviceType: entity.deviceType,
|
||||
assigneeName: entity.assigneeName,
|
||||
aiSuggestion: entity.aiSuggestion,
|
||||
requiredEquipment: entity.requiredEquipment,
|
||||
estimatedImpact: entity.estimatedImpact,
|
||||
taskDescription: entity.taskDescription,
|
||||
actualStartTime: entity.actualStartTime,
|
||||
actualEndTime: entity.actualEndTime,
|
||||
deadlineTime: entity.deadlineTime,
|
||||
sourceType: entity.sourceType,
|
||||
videoUrls: entity.videoUrls,
|
||||
updateTime: entity.updateTime,
|
||||
);
|
||||
}
|
||||
|
||||
static List<AttachmentModel>? _parseAttachments(Map<String, dynamic> json) {
|
||||
const fieldNames = [
|
||||
'imgUrl',
|
||||
'imageUrl',
|
||||
'imageUrls',
|
||||
'photos',
|
||||
'images',
|
||||
'attachments',
|
||||
'files',
|
||||
'media',
|
||||
];
|
||||
for (final field in fieldNames) {
|
||||
final dynamic value = json[field];
|
||||
if (value == null) continue;
|
||||
|
||||
if (value is String && value.isNotEmpty) {
|
||||
return [AttachmentModel(fileName: '', url: value)];
|
||||
}
|
||||
if (value is List) {
|
||||
final list = <AttachmentModel>[];
|
||||
for (final item in value) {
|
||||
if (item is String && item.isNotEmpty) {
|
||||
list.add(AttachmentModel(fileName: '', url: item));
|
||||
} else if (item is Map) {
|
||||
final type =
|
||||
(item['type']?.toString() ??
|
||||
item['mediaType']?.toString() ??
|
||||
'')
|
||||
.toLowerCase();
|
||||
if (type == 'video' || type == 'video/mp4') continue;
|
||||
final url =
|
||||
item['url']?.toString() ?? item['fileUrl']?.toString() ?? '';
|
||||
final fileName =
|
||||
item['fileName']?.toString() ?? item['name']?.toString() ?? '';
|
||||
if (url.isNotEmpty) {
|
||||
list.add(AttachmentModel(fileName: fileName, url: url));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list.isNotEmpty) return list;
|
||||
}
|
||||
if (value is Map) {
|
||||
final dynamic nestedImages =
|
||||
value['images'] ??
|
||||
value['photos'] ??
|
||||
value['imgUrl'] ??
|
||||
value['imageUrls'];
|
||||
if (nestedImages != null) {
|
||||
if (nestedImages is List) {
|
||||
final list = <AttachmentModel>[];
|
||||
for (final item in nestedImages) {
|
||||
if (item is String && item.isNotEmpty) {
|
||||
list.add(AttachmentModel(fileName: '', url: item));
|
||||
} else if (item is Map) {
|
||||
final url =
|
||||
item['url']?.toString() ??
|
||||
item['fileUrl']?.toString() ??
|
||||
'';
|
||||
final fileName =
|
||||
item['fileName']?.toString() ??
|
||||
item['name']?.toString() ??
|
||||
'';
|
||||
if (url.isNotEmpty)
|
||||
list.add(AttachmentModel(fileName: fileName, url: url));
|
||||
}
|
||||
}
|
||||
if (list.isNotEmpty) return list;
|
||||
} else if (nestedImages is String && nestedImages.isNotEmpty) {
|
||||
return [AttachmentModel(fileName: '', url: nestedImages)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<String>? _parseVideoUrls(Map<String, dynamic> json) {
|
||||
const fieldNames = ['videoUrl', 'videoUrls', 'videos', 'videoList'];
|
||||
for (final field in fieldNames) {
|
||||
final dynamic value = json[field];
|
||||
if (value == null) continue;
|
||||
|
||||
if (value is String && value.isNotEmpty) {
|
||||
return [value];
|
||||
}
|
||||
if (value is List) {
|
||||
final list = <String>[];
|
||||
for (final item in value) {
|
||||
if (item is String && item.isNotEmpty) {
|
||||
list.add(item);
|
||||
} else if (item is Map) {
|
||||
final url =
|
||||
item['url']?.toString() ?? item['fileUrl']?.toString() ?? '';
|
||||
if (url.isNotEmpty) list.add(url);
|
||||
}
|
||||
}
|
||||
if (list.isNotEmpty) return list;
|
||||
}
|
||||
}
|
||||
|
||||
final dynamic attachments = json['attachments'];
|
||||
if (attachments is List) {
|
||||
final list = <String>[];
|
||||
for (final item in attachments) {
|
||||
if (item is Map) {
|
||||
final type =
|
||||
(item['type']?.toString() ?? item['mediaType']?.toString() ?? '')
|
||||
.toLowerCase();
|
||||
if (type == 'video' || type == 'video/mp4') {
|
||||
final url =
|
||||
item['url']?.toString() ?? item['fileUrl']?.toString() ?? '';
|
||||
if (url.isNotEmpty) list.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list.isNotEmpty) return list;
|
||||
}
|
||||
|
||||
final dynamic media = json['media'];
|
||||
if (media is Map) {
|
||||
final dynamic nestedVideos =
|
||||
media['videos'] ?? media['videoUrls'] ?? media['videoUrl'];
|
||||
if (nestedVideos != null) {
|
||||
if (nestedVideos is List) {
|
||||
final list = <String>[];
|
||||
for (final item in nestedVideos) {
|
||||
if (item is String && item.isNotEmpty) list.add(item);
|
||||
if (item is Map) {
|
||||
final url =
|
||||
item['url']?.toString() ?? item['fileUrl']?.toString() ?? '';
|
||||
if (url.isNotEmpty) list.add(url);
|
||||
}
|
||||
}
|
||||
if (list.isNotEmpty) return list;
|
||||
} else if (nestedVideos is String && nestedVideos.isNotEmpty) {
|
||||
return [nestedVideos];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static WorkOrderPriority _parsePriority(String value) {
|
||||
switch (value) {
|
||||
switch (value.toUpperCase()) {
|
||||
case 'HIGH':
|
||||
case 'high':
|
||||
return WorkOrderPriority.high;
|
||||
case 'MEDIUM':
|
||||
case 'medium':
|
||||
return WorkOrderPriority.medium;
|
||||
case 'LOW':
|
||||
case 'low':
|
||||
return WorkOrderPriority.low;
|
||||
case 'ERROR':
|
||||
return WorkOrderPriority.high;
|
||||
case 'WARNING':
|
||||
return WorkOrderPriority.medium;
|
||||
case 'INFO':
|
||||
return WorkOrderPriority.low;
|
||||
default:
|
||||
return WorkOrderPriority.medium;
|
||||
}
|
||||
@@ -130,6 +616,40 @@ class WorkOrderModel {
|
||||
}
|
||||
}
|
||||
|
||||
static WorkOrderStatus _parseStatusFromInt(int value) {
|
||||
switch (value) {
|
||||
case 1:
|
||||
return WorkOrderStatus.pending;
|
||||
case 2:
|
||||
return WorkOrderStatus.executing;
|
||||
case 3:
|
||||
return WorkOrderStatus.completed;
|
||||
default:
|
||||
return WorkOrderStatus.pending;
|
||||
}
|
||||
}
|
||||
|
||||
static String _parseSourceType(int value) {
|
||||
switch (value) {
|
||||
case 1:
|
||||
return '手动创建';
|
||||
case 2:
|
||||
return '计划任务';
|
||||
case 3:
|
||||
return '定期维护';
|
||||
case 4:
|
||||
return '巡检发现';
|
||||
case 5:
|
||||
return '设备上报';
|
||||
case 6:
|
||||
return '客户反馈';
|
||||
case 7:
|
||||
return '告警联动';
|
||||
default:
|
||||
return '未知来源';
|
||||
}
|
||||
}
|
||||
|
||||
static String _statusToString(WorkOrderStatus status) {
|
||||
switch (status) {
|
||||
case WorkOrderStatus.pending:
|
||||
@@ -156,7 +676,6 @@ class WorkOrderCountModel {
|
||||
required this.todayCompletedCount,
|
||||
});
|
||||
|
||||
/// 从 JSON 创建
|
||||
factory WorkOrderCountModel.fromJson(Map<String, dynamic> json) {
|
||||
return WorkOrderCountModel(
|
||||
pendingCount: json['pendingCount'] as int,
|
||||
@@ -165,7 +684,6 @@ class WorkOrderCountModel {
|
||||
);
|
||||
}
|
||||
|
||||
/// 转换为 JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'pendingCount': pendingCount,
|
||||
@@ -174,7 +692,6 @@ class WorkOrderCountModel {
|
||||
};
|
||||
}
|
||||
|
||||
/// 转换为实体
|
||||
WorkOrderCountEntity toEntity() {
|
||||
return WorkOrderCountEntity(
|
||||
pendingCount: pendingCount,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import '../../../../../core/consts/workorder_consts.dart';
|
||||
import '../../../../../core/error/failure.dart';
|
||||
import '../../../../../core/error/workorder_failure.dart';
|
||||
import '../../domain/repositories/workorder_repository.dart';
|
||||
@@ -6,7 +5,6 @@ import '../../domain/entities/workorder_entity.dart';
|
||||
import '../datasources/workorder_remote_datasource.dart';
|
||||
import 'package:fpdart/fpdart.dart';
|
||||
|
||||
|
||||
class WorkOrderRepositoryImpl implements WorkOrderRepository {
|
||||
final WorkOrderRemoteDataSource remoteDataSource;
|
||||
|
||||
@@ -14,11 +12,17 @@ class WorkOrderRepositoryImpl implements WorkOrderRepository {
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<WorkOrderEntity>>> getWorkOrderList({
|
||||
WorkOrderStatus? status,
|
||||
required int page,
|
||||
required int pageSize,
|
||||
int? siteId,
|
||||
int? orgId,
|
||||
}) async {
|
||||
try {
|
||||
final models = await remoteDataSource.getWorkOrderList(
|
||||
status: status != null ? _statusToString(status) : null,
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
siteId: siteId,
|
||||
orgId: orgId,
|
||||
);
|
||||
final entities = models.map((model) => model.toEntity()).toList();
|
||||
return Right(entities);
|
||||
@@ -26,7 +30,7 @@ class WorkOrderRepositoryImpl implements WorkOrderRepository {
|
||||
return Left(UnknownFailure(message: '获取工单列表失败: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<Either<Failure, WorkOrderCountEntity>> getWorkOrderCount() async {
|
||||
try {
|
||||
@@ -38,22 +42,66 @@ class WorkOrderRepositoryImpl implements WorkOrderRepository {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<WorkOrderEntity>>> filterWorkOrders({
|
||||
required WorkOrderStatus status,
|
||||
Future<Either<Failure, WorkOrderEntity>> getWorkOrderDetail(
|
||||
String orderId, {
|
||||
int? siteId,
|
||||
int? orgId,
|
||||
}) async {
|
||||
return getWorkOrderList(status: status);
|
||||
try {
|
||||
final model = await remoteDataSource.getWorkOrderDetail(
|
||||
orderId,
|
||||
siteId: siteId,
|
||||
orgId: orgId,
|
||||
);
|
||||
return Right(model.toEntity());
|
||||
} catch (e) {
|
||||
return Left(UnknownFailure(message: '获取工单详情失败: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
String _statusToString(WorkOrderStatus status) {
|
||||
switch (status) {
|
||||
case WorkOrderStatus.pending:
|
||||
return 'pending';
|
||||
case WorkOrderStatus.executing:
|
||||
return 'executing';
|
||||
case WorkOrderStatus.completed:
|
||||
return 'completed';
|
||||
case WorkOrderStatus.all:
|
||||
return 'all';
|
||||
@override
|
||||
Future<Either<Failure, List<Map<String, dynamic>>>> fetchUsers({
|
||||
required int orgId,
|
||||
required int siteId,
|
||||
}) async {
|
||||
try {
|
||||
final result = await remoteDataSource.fetchUsers(
|
||||
orgId: orgId,
|
||||
siteId: siteId,
|
||||
);
|
||||
return Right(result);
|
||||
} catch (e) {
|
||||
return Left(UnknownFailure(message: '获取人员列表失败: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, void>> dispatchWorkOrder({
|
||||
required String orderId,
|
||||
required String assigneeId,
|
||||
required String assigneeName,
|
||||
String? dispatchRemark,
|
||||
String? collaboratorIds,
|
||||
String? collaboratorNames,
|
||||
String? planStartTime,
|
||||
String? planEndTime,
|
||||
String? deadlineTime,
|
||||
}) async {
|
||||
try {
|
||||
await remoteDataSource.dispatchWorkOrder(
|
||||
orderId: orderId,
|
||||
assigneeId: assigneeId,
|
||||
assigneeName: assigneeName,
|
||||
dispatchRemark: dispatchRemark,
|
||||
collaboratorIds: collaboratorIds,
|
||||
collaboratorNames: collaboratorNames,
|
||||
planStartTime: planStartTime,
|
||||
planEndTime: planEndTime,
|
||||
deadlineTime: deadlineTime,
|
||||
);
|
||||
return const Right(null);
|
||||
} catch (e) {
|
||||
return Left(UnknownFailure(message: '转派工单失败: $e'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user