feat(mobile): #24 Flutter三合一APP骨架搭建
- 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状态管理
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
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)';
|
||||
}
|
||||
Reference in New Issue
Block a user