/// 巡检管理相关 API 调用服务 /// 当前使用 mock 数据,后端 API 就绪后替换为真实请求 class PatrolService { PatrolService._internal(); static final PatrolService instance = PatrolService._internal(); factory PatrolService() => instance; // ==================== Mock 数据 ==================== /// 获取巡检任务列表 Future> getTaskList({PatrolTaskStatus? status}) async { await Future.delayed(const Duration(milliseconds: 800)); final tasks = [ PatrolTask( id: 'XJ-2024-001', routeName: '城东片区巡检路线', date: DateTime(2024, 6, 14), totalPoints: 8, completedPoints: 0, priority: PatrolPriority.high, status: PatrolTaskStatus.pending, assignee: '张建国', description: '城东片区主干管网及加压站设备巡检,包含8个巡检点', points: _mockPointsEast, ), PatrolTask( id: 'XJ-2024-002', routeName: '城北加压站巡检', date: DateTime(2024, 6, 14), totalPoints: 4, completedPoints: 0, priority: PatrolPriority.medium, status: PatrolTaskStatus.pending, assignee: '李明', description: '城北加压站设备日检,包含泵站、配电柜、压力表等设备', points: _mockPointsNorth, ), PatrolTask( id: 'XJ-2024-003', routeName: '水厂设备日检', date: DateTime(2024, 6, 15), totalPoints: 12, completedPoints: 0, priority: PatrolPriority.high, status: PatrolTaskStatus.pending, assignee: '王芳', description: '水厂全部设备日检,包含取水泵房、净水设备、加药间、消毒间等', points: _mockPointsFactory, ), PatrolTask( id: 'XJ-2024-004', routeName: '城西管网巡检', date: DateTime(2024, 6, 14), totalPoints: 6, completedPoints: 3, priority: PatrolPriority.medium, status: PatrolTaskStatus.ongoing, assignee: '赵强', description: '城西片区管网巡检,重点检查阀门井和消防栓', points: _mockPointsWest, ), PatrolTask( id: 'XJ-2024-005', routeName: '城南片区周检', date: DateTime(2024, 6, 13), totalPoints: 10, completedPoints: 10, priority: PatrolPriority.low, status: PatrolTaskStatus.completed, assignee: '刘伟', description: '城南片区管网周检', points: _mockPointsSouth, result: PatrolResult.normal, reportTime: DateTime(2024, 6, 13, 16, 30), ), PatrolTask( id: 'XJ-2024-006', routeName: '水厂设备周检', date: DateTime(2024, 6, 13), totalPoints: 12, completedPoints: 12, priority: PatrolPriority.high, status: PatrolTaskStatus.completed, assignee: '张建国', description: '水厂全部设备周检', points: _mockPointsFactory, result: PatrolResult.issueFound, reportTime: DateTime(2024, 6, 13, 15, 0), issues: '2号加药泵存在异响,已记录待维修', ), ]; if (status != null) { return tasks.where((t) => t.status == status).toList(); } return tasks; } /// 获取任务详情 Future getTaskDetail(String taskId) async { await Future.delayed(const Duration(milliseconds: 500)); final tasks = await getTaskList(); try { return tasks.firstWhere((t) => t.id == taskId); } catch (_) { return null; } } /// 开始巡检任务 Future startTask(String taskId) async { await Future.delayed(const Duration(milliseconds: 600)); return true; } /// 提交巡检点上报 Future submitPointReport({ required String taskId, required String pointId, required PatrolPointStatus status, String? remark, List? photoPaths, }) async { await Future.delayed(const Duration(milliseconds: 700)); return true; } /// 完成巡检任务 Future completeTask({ required String taskId, required PatrolResult result, String? summary, }) async { await Future.delayed(const Duration(milliseconds: 800)); return true; } /// 获取GPS轨迹点列表 Future> getTrackPoints(String taskId) async { await Future.delayed(const Duration(milliseconds: 500)); return [ TrackPoint( id: 'TP001', lat: 30.2741, lng: 120.1551, altitude: 15.2, speed: 0, timestamp: DateTime(2024, 6, 14, 8, 0), address: '水厂大门', ), TrackPoint( id: 'TP002', lat: 30.2748, lng: 120.1562, altitude: 14.8, speed: 3.2, timestamp: DateTime(2024, 6, 14, 8, 5), address: '城东路段阀门井', ), TrackPoint( id: 'TP003', lat: 30.2755, lng: 120.1578, altitude: 15.0, speed: 2.8, timestamp: DateTime(2024, 6, 14, 8, 12), address: '阳光小区加压站', ), TrackPoint( id: 'TP004', lat: 30.2763, lng: 120.1590, altitude: 14.5, speed: 0, timestamp: DateTime(2024, 6, 14, 8, 20), address: '城东消防栓-03', ), TrackPoint( id: 'TP005', lat: 30.2770, lng: 120.1605, altitude: 15.3, speed: 4.1, timestamp: DateTime(2024, 6, 14, 8, 28), address: '东方名城阀门井', ), TrackPoint( id: 'TP006', lat: 30.2778, lng: 120.1618, altitude: 14.9, speed: 0, timestamp: DateTime(2024, 6, 14, 8, 35), address: '城东片区末端压力表', ), ]; } // ==================== Mock 巡检点数据 ==================== static final List _mockPointsEast = [ PatrolPoint(id: 'PP001', name: '城东路段阀门井', type: PatrolPointType.valve, lat: 30.2748, lng: 120.1562, order: 1), PatrolPoint(id: 'PP002', name: '阳光小区加压站', type: PatrolPointType.pumpStation, lat: 30.2755, lng: 120.1578, order: 2), PatrolPoint(id: 'PP003', name: '城东消防栓-03', type: PatrolPointType.hydrant, lat: 30.2763, lng: 120.1590, order: 3), PatrolPoint(id: 'PP004', name: '东方名城阀门井', type: PatrolPointType.valve, lat: 30.2770, lng: 120.1605, order: 4), PatrolPoint(id: 'PP005', name: '城东片区末端压力表', type: PatrolPointType.meter, lat: 30.2778, lng: 120.1618, order: 5), PatrolPoint(id: 'PP006', name: '锦绣家园管网接口', type: PatrolPointType.junction, lat: 30.2785, lng: 120.1630, order: 6), PatrolPoint(id: 'PP007', name: '翠湖路排气阀', type: PatrolPointType.valve, lat: 30.2792, lng: 120.1645, order: 7), PatrolPoint(id: 'PP008', name: '城东片区测流点', type: PatrolPointType.meter, lat: 30.2800, lng: 120.1660, order: 8), ]; static final List _mockPointsNorth = [ PatrolPoint(id: 'PP009', name: '城北加压站1号泵', type: PatrolPointType.pumpStation, lat: 30.2900, lng: 120.1500, order: 1), PatrolPoint(id: 'PP010', name: '城北加压站配电柜', type: PatrolPointType.electrical, lat: 30.2902, lng: 120.1505, order: 2), PatrolPoint(id: 'PP011', name: '城北加压站出水压力表', type: PatrolPointType.meter, lat: 30.2905, lng: 120.1510, order: 3), PatrolPoint(id: 'PP012', name: '城北加压站流量计', type: PatrolPointType.meter, lat: 30.2908, lng: 120.1515, order: 4), ]; static final List _mockPointsFactory = [ PatrolPoint(id: 'PP013', name: '取水泵房', type: PatrolPointType.pumpStation, lat: 30.2700, lng: 120.1400, order: 1), PatrolPoint(id: 'PP014', name: '混合池', type: PatrolPointType.equipment, lat: 30.2705, lng: 120.1410, order: 2), PatrolPoint(id: 'PP015', name: '絮凝池', type: PatrolPointType.equipment, lat: 30.2710, lng: 120.1420, order: 3), PatrolPoint(id: 'PP016', name: '沉淀池', type: PatrolPointType.equipment, lat: 30.2715, lng: 120.1430, order: 4), PatrolPoint(id: 'PP017', name: '滤池-1号', type: PatrolPointType.equipment, lat: 30.2720, lng: 120.1440, order: 5), PatrolPoint(id: 'PP018', name: '滤池-2号', type: PatrolPointType.equipment, lat: 30.2722, lng: 120.1445, order: 6), PatrolPoint(id: 'PP019', name: '清水池', type: PatrolPointType.reservoir, lat: 30.2725, lng: 120.1450, order: 7), PatrolPoint(id: 'PP020', name: '加药间', type: PatrolPointType.equipment, lat: 30.2728, lng: 120.1455, order: 8), PatrolPoint(id: 'PP021', name: '消毒间', type: PatrolPointType.equipment, lat: 30.2730, lng: 120.1460, order: 9), PatrolPoint(id: 'PP022', name: '送水泵房', type: PatrolPointType.pumpStation, lat: 30.2733, lng: 120.1465, order: 10), PatrolPoint(id: 'PP023', name: '出厂水水质仪', type: PatrolPointType.meter, lat: 30.2735, lng: 120.1470, order: 11), PatrolPoint(id: 'PP024', name: '出水流量计', type: PatrolPointType.meter, lat: 30.2738, lng: 120.1475, order: 12), ]; static final List _mockPointsWest = [ PatrolPoint(id: 'PP025', name: '城西阀门井-01', type: PatrolPointType.valve, lat: 30.2750, lng: 120.1450, order: 1), PatrolPoint(id: 'PP026', name: '城西消防栓-01', type: PatrolPointType.hydrant, lat: 30.2758, lng: 120.1438, order: 2), PatrolPoint(id: 'PP027', name: '翠湖花园加压站', type: PatrolPointType.pumpStation, lat: 30.2765, lng: 120.1425, order: 3), PatrolPoint(id: 'PP028', name: '城西排气阀', type: PatrolPointType.valve, lat: 30.2772, lng: 120.1412, order: 4), PatrolPoint(id: 'PP029', name: '城西测流点', type: PatrolPointType.meter, lat: 30.2780, lng: 120.1400, order: 5), PatrolPoint(id: 'PP030', name: '城西末端压力表', type: PatrolPointType.meter, lat: 30.2788, lng: 120.1388, order: 6), ]; static final List _mockPointsSouth = [ PatrolPoint(id: 'PP031', name: '城南阀门井-01', type: PatrolPointType.valve, lat: 30.2650, lng: 120.1520, order: 1), PatrolPoint(id: 'PP032', name: '城南加压站', type: PatrolPointType.pumpStation, lat: 30.2640, lng: 120.1530, order: 2), PatrolPoint(id: 'PP033', name: '阳光小区消防栓', type: PatrolPointType.hydrant, lat: 30.2630, lng: 120.1540, order: 3), PatrolPoint(id: 'PP034', name: '城南排气阀', type: PatrolPointType.valve, lat: 30.2620, lng: 120.1550, order: 4), PatrolPoint(id: 'PP035', name: '城南测流点', type: PatrolPointType.meter, lat: 30.2610, lng: 120.1560, order: 5), PatrolPoint(id: 'PP036', name: '学校管网接口', type: PatrolPointType.junction, lat: 30.2600, lng: 120.1570, order: 6), PatrolPoint(id: 'PP037', name: '医院管网接口', type: PatrolPointType.junction, lat: 30.2590, lng: 120.1580, order: 7), PatrolPoint(id: 'PP038', name: '城南末端压力表', type: PatrolPointType.meter, lat: 30.2580, lng: 120.1590, order: 8), PatrolPoint(id: 'PP039', name: '城南消防栓-02', type: PatrolPointType.hydrant, lat: 30.2570, lng: 120.1600, order: 9), PatrolPoint(id: 'PP040', name: '城南回水阀门', type: PatrolPointType.valve, lat: 30.2560, lng: 120.1610, order: 10), ]; } // ==================== 数据模型 ==================== /// 巡检任务状态 enum PatrolTaskStatus { pending('待执行'), ongoing('进行中'), completed('已完成'); final String label; const PatrolTaskStatus(this.label); } /// 巡检优先级 enum PatrolPriority { high('高', 0xFFF44336), medium('中', 0xFFFF9800), low('低', 0xFF4CAF50); final String label; final int color; const PatrolPriority(this.label, this.color); } /// 巡检结果 enum PatrolResult { normal('正常'), issueFound('发现问题'); final String label; const PatrolResult(this.label); } /// 巡检点类型 enum PatrolPointType { valve('阀门井'), pumpStation('泵站'), hydrant('消防栓'), meter('仪表'), junction('管网接口'), electrical('配电柜'), equipment('设备'), reservoir('水池'); final String label; const PatrolPointType(this.label); } /// 巡检点状态 enum PatrolPointStatus { normal('正常'), abnormal('异常'), maintenance('需维护'); final String label; const PatrolPointStatus(this.label); } /// 巡检点 class PatrolPoint { final String id; final String name; final PatrolPointType type; final double lat; final double lng; final int order; PatrolPointStatus? status; String? remark; List? photos; PatrolPoint({ required this.id, required this.name, required this.type, required this.lat, required this.lng, required this.order, this.status, this.remark, this.photos, }); } /// GPS 轨迹点 class TrackPoint { final String id; final double lat; final double lng; final double altitude; final double speed; final DateTime timestamp; final String address; const TrackPoint({ required this.id, required this.lat, required this.lng, required this.altitude, required this.speed, required this.timestamp, required this.address, }); } /// 巡检任务 class PatrolTask { final String id; final String routeName; final DateTime date; final int totalPoints; final int completedPoints; final PatrolPriority priority; final PatrolTaskStatus status; final String assignee; final String description; final List points; final PatrolResult? result; final DateTime? reportTime; final String? issues; const PatrolTask({ required this.id, required this.routeName, required this.date, required this.totalPoints, required this.completedPoints, required this.priority, required this.status, required this.assignee, required this.description, required this.points, this.result, this.reportTime, this.issues, }); double get progress => totalPoints > 0 ? completedPoints / totalPoints : 0; String get dateStr => '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; }