- Flutter 3.x 项目初始化(pubspec.yaml + 目录结构) - 核心依赖:dio/go_router/provider/shared_preferences/hive/geolocator - 统一登录页 + Token管理(TokenService + AuthInterceptor) - 底部Tab三合一导航(供水/巡检/营收) - 供水管理Tab:监测数据列表(MonitorListPage) - 巡检Tab:任务列表+状态筛选+进度展示(PatrolTaskListPage) - 营收Tab:抄表页面+账单列表(MeterReadingPage/BillListPage) - 消息推送服务(PushService) - GPS定位服务(LocationService) - 拍照/相册服务(CameraService) - 离线缓存服务(CacheService) - Android/iOS打包配置+权限声明 - GoRouter路由+Auth认证守卫 - Provider状态管理
126 lines
3.6 KiB
Dart
126 lines
3.6 KiB
Dart
import 'dart:async';
|
|
|
|
/// GPS 定位服务
|
|
/// 提供获取当前位置、权限请求等功能
|
|
class LocationService {
|
|
static LocationService? _instance;
|
|
|
|
LocationService._internal();
|
|
|
|
factory LocationService() {
|
|
_instance ??= LocationService._internal();
|
|
return _instance!;
|
|
}
|
|
|
|
/// 请求位置权限
|
|
Future<bool> requestPermission() async {
|
|
// TODO: 使用 geolocator 请求权限
|
|
// final permission = await Geolocator.requestPermission();
|
|
// return permission == LocationPermission.always || permission == LocationPermission.whileInUse;
|
|
print('[LocationService] 请求位置权限(模拟)');
|
|
return true;
|
|
}
|
|
|
|
/// 检查位置权限状态
|
|
Future<bool> hasPermission() async {
|
|
// TODO: 使用 geolocator 检查权限
|
|
return true;
|
|
}
|
|
|
|
/// 检查 GPS 是否开启
|
|
Future<bool> isGpsEnabled() async {
|
|
// TODO: 使用 geolocator 检查 GPS 状态
|
|
// return await Geolocator.isLocationServiceEnabled();
|
|
return true;
|
|
}
|
|
|
|
/// 获取当前位置
|
|
Future<LocationData?> getCurrentLocation() async {
|
|
try {
|
|
final hasPermission = await requestPermission();
|
|
if (!hasPermission) return null;
|
|
|
|
// TODO: 使用 geolocator 获取位置
|
|
// final position = await Geolocator.getCurrentPosition(
|
|
// desiredAccuracy: LocationAccuracy.high,
|
|
// );
|
|
// return LocationData(
|
|
// latitude: position.latitude,
|
|
// longitude: position.longitude,
|
|
// accuracy: position.accuracy,
|
|
// );
|
|
|
|
// 模拟位置数据(杭州市中心)
|
|
return LocationData(
|
|
latitude: 30.2741,
|
|
longitude: 120.1551,
|
|
accuracy: 10.0,
|
|
altitude: 15.0,
|
|
timestamp: DateTime.now(),
|
|
);
|
|
} catch (e) {
|
|
print('[LocationService] 获取位置失败: $e');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// 持续监听位置变化
|
|
Stream<LocationData> watchLocation() async* {
|
|
// TODO: 使用 geolocator 的位置流
|
|
// final positionStream = Geolocator.getPositionStream(
|
|
// locationSettings: LocationSettings(accuracy: LocationAccuracy.high),
|
|
// );
|
|
// await for (final position in positionStream) {
|
|
// yield LocationData.fromPosition(position);
|
|
// }
|
|
|
|
// 模拟位置流
|
|
while (true) {
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
yield LocationData(
|
|
latitude: 30.2741 + (DateTime.now().millisecondsSinceEpoch % 100) / 10000,
|
|
longitude: 120.1551 + (DateTime.now().millisecondsSinceEpoch % 100) / 10000,
|
|
accuracy: 10.0,
|
|
timestamp: DateTime.now(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 计算两点之间的距离(米)
|
|
double distanceBetween(
|
|
double startLatitude,
|
|
double startLongitude,
|
|
double endLatitude,
|
|
double endLongitude,
|
|
) {
|
|
// TODO: 使用 geolocator 计算距离
|
|
// return Geolocator.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude);
|
|
// 简单估算
|
|
const earthRadius = 6371000.0;
|
|
final dLat = (endLatitude - startLatitude) * 3.14159 / 180;
|
|
final dLon = (endLongitude - startLongitude) * 3.14159 / 180;
|
|
final a = dLat * dLat + dLon * dLon * 0.25;
|
|
return earthRadius * 2 * a * 1000;
|
|
}
|
|
}
|
|
|
|
/// 位置数据模型
|
|
class LocationData {
|
|
final double latitude;
|
|
final double longitude;
|
|
final double accuracy;
|
|
final double? altitude;
|
|
final DateTime timestamp;
|
|
|
|
LocationData({
|
|
required this.latitude,
|
|
required this.longitude,
|
|
required this.accuracy,
|
|
this.altitude,
|
|
required this.timestamp,
|
|
});
|
|
|
|
@override
|
|
String toString() => 'LocationData(lat: $latitude, lng: $longitude, accuracy: $accuracy)';
|
|
}
|