一次大的提交

This commit is contained in:
2026-08-07 08:49:29 +08:00
parent bf2fc49c19
commit db70665ced
181 changed files with 23060 additions and 2804 deletions

View File

@@ -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,