308 lines
8.9 KiB
TypeScript
308 lines
8.9 KiB
TypeScript
// 地图模块 - 处理地图显示、定位、标记点管理
|
||
import mapService from '../../../services/mapService';
|
||
import userService from '../../../services/userService';
|
||
import { showToast } from '../../../utils/helpers';
|
||
import { Marker } from '../../../types';
|
||
import { DataModule } from './dataModule';
|
||
|
||
export class MapModule {
|
||
private pageContext: any;
|
||
private dataModule: DataModule;
|
||
|
||
constructor(pageContext: any, dataModule: DataModule) {
|
||
this.pageContext = pageContext;
|
||
this.dataModule = dataModule;
|
||
}
|
||
|
||
/**
|
||
* 初始化地图数据
|
||
*/
|
||
async initMap(): Promise<void> {
|
||
try {
|
||
// 检查并请求位置权限
|
||
await this.checkAndRequestLocationPermission();
|
||
|
||
// 加载地图数据
|
||
this.loadMapData();
|
||
|
||
} catch (error) {
|
||
console.error('初始化地图失败:', error);
|
||
showToast('地图初始化失败,请重试');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查并请求位置权限
|
||
*/
|
||
async checkAndRequestLocationPermission(): Promise<void> {
|
||
try {
|
||
// 检查位置权限
|
||
const hasPermission = await userService.checkLocationPermission();
|
||
|
||
if (hasPermission) {
|
||
// 已授权,开始定位
|
||
await this.startLocation();
|
||
} else {
|
||
// 未授权,请求权限
|
||
const permissionGranted = await userService.requestLocationPermission();
|
||
|
||
if (permissionGranted) {
|
||
await this.startLocation();
|
||
} else {
|
||
// 授权失败,使用默认位置
|
||
this.setDefaultLocation();
|
||
showToast('已使用默认位置');
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('检查位置权限失败:', error);
|
||
this.setDefaultLocation();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 开始定位
|
||
*/
|
||
async startLocation(): Promise<void> {
|
||
try {
|
||
console.log('[MAP MODULE] 开始获取用户位置...');
|
||
const location = await mapService.getCurrentLocation();
|
||
|
||
console.log('[MAP MODULE] 获取位置成功,原始坐标:', location);
|
||
console.log('[MAP MODULE] 详细位置信息:');
|
||
console.log(`- 经度: ${location.longitude}`);
|
||
console.log(`- 纬度: ${location.latitude}`);
|
||
console.log(`- 精度: ${location.accuracy}`);
|
||
console.log(`- 速度: ${location.speed}`);
|
||
|
||
// 验证获取的坐标是否有效
|
||
if (isNaN(location.latitude) || isNaN(location.longitude)) {
|
||
console.error('[MAP MODULE] 获取的位置坐标无效:', location);
|
||
this.setDefaultLocation();
|
||
showToast('获取的位置无效,已使用默认位置');
|
||
return;
|
||
}
|
||
|
||
// 强制重置地图视角到用户位置
|
||
// 1. 更新用户位置
|
||
this.dataModule.updateUserLocation(location.latitude, location.longitude);
|
||
// 2. 重置地图缩放级别到15(详细级别)
|
||
this.dataModule.setMapScale(15);
|
||
// 3. 添加地图动画效果,让视角平滑回到用户位置
|
||
this.animateMapToUserLocation(location.latitude, location.longitude);
|
||
|
||
console.log('[MAP MODULE] 定位成功,坐标已更新,视角已重置:', location);
|
||
showToast('已定位到您的位置');
|
||
} catch (error) {
|
||
console.error('[MAP MODULE] 定位失败:', error);
|
||
this.setDefaultLocation();
|
||
showToast('定位失败,已使用默认位置');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 设置默认位置
|
||
*/
|
||
setDefaultLocation(): void {
|
||
const defaultLatitude = 24.880095;
|
||
const defaultLongitude = 102.833722;
|
||
|
||
// 更新数据模块中的位置信息和缩放级别
|
||
this.dataModule.updateUserLocation(defaultLatitude, defaultLongitude);
|
||
this.dataModule.setMapScale(13);
|
||
// 动画效果回到默认位置
|
||
this.animateMapToUserLocation(defaultLatitude, defaultLongitude);
|
||
|
||
console.log('[MAP MODULE] 默认位置设置完成');
|
||
}
|
||
|
||
/**
|
||
* 动画效果将地图视角平滑移动到用户位置
|
||
*/
|
||
private animateMapToUserLocation(latitude: number, longitude: number): void {
|
||
// 使用微信小程序的MapContext.moveToLocation方法实现地图移动
|
||
const mapContext = wx.createMapContext('myMap', this.pageContext);
|
||
|
||
// 先设置地图中心点
|
||
this.pageContext.setData({
|
||
latitude: latitude,
|
||
longitude: longitude
|
||
});
|
||
|
||
// 使用moveToLocation方法平滑移动地图视角
|
||
mapContext.moveToLocation({
|
||
latitude: latitude,
|
||
longitude: longitude,
|
||
success: () => {
|
||
console.log('[MAP MODULE] 地图视角移动成功,位置:', { latitude, longitude });
|
||
},
|
||
fail: (err: any) => {
|
||
console.error('[MAP MODULE] 地图视角移动失败:', err);
|
||
// 如果moveToLocation失败,直接设置中心点
|
||
this.pageContext.setData({
|
||
latitude: latitude,
|
||
longitude: longitude
|
||
});
|
||
}
|
||
});
|
||
|
||
console.log('[MAP MODULE] 地图视角动画已启动,移动到位置:', { latitude, longitude });
|
||
}
|
||
|
||
/**
|
||
* 加载地图数据(仓库和货运人员)
|
||
*/
|
||
loadMapData(): void {
|
||
// 这里会调用具体的服务来获取数据
|
||
// 目前使用模拟数据
|
||
const markers = this.generateInitialMarkers();
|
||
|
||
// 更新数据模块中的标记点
|
||
this.dataModule.updateMarkers(markers);
|
||
|
||
console.log('地图数据加载完成');
|
||
}
|
||
|
||
/**
|
||
* 生成初始标记点
|
||
*/
|
||
public generateInitialMarkers(): Marker[] {
|
||
console.log('生成初始标记点');
|
||
|
||
const markers: Marker[] = [];
|
||
|
||
// 获取用户位置
|
||
const userLocation = this.pageContext.data.userLocation;
|
||
if (userLocation && userLocation.longitude && userLocation.latitude) {
|
||
// 添加用户位置标记点
|
||
markers.push({
|
||
id: -1,
|
||
title: '用户位置',
|
||
longitude: userLocation.longitude,
|
||
latitude: userLocation.latitude,
|
||
iconPath: '/images/trucks.png',
|
||
width: 40,
|
||
height: 40,
|
||
zIndex: 99
|
||
});
|
||
|
||
console.log('已添加用户位置标记点');
|
||
}
|
||
|
||
return markers;
|
||
}
|
||
|
||
/**
|
||
* 更新用户标记图标为用户头像
|
||
*/
|
||
updateUserMarkerIcon(): void {
|
||
const { authStatus, userInfo, markers } = this.pageContext.data;
|
||
|
||
if (!authStatus.hasWxCode || !userInfo) {
|
||
console.warn('未登录或用户信息为空,无法更新头像');
|
||
return;
|
||
}
|
||
|
||
// 使用默认头像
|
||
const avatarUrl = '/images/trucks.png';
|
||
|
||
const updatedMarkers = markers.map((marker: Marker) => {
|
||
if (marker.id === -1) {
|
||
return {
|
||
...marker,
|
||
iconPath: avatarUrl
|
||
};
|
||
}
|
||
return marker;
|
||
});
|
||
|
||
// 更新数据模块中的标记点
|
||
this.dataModule.updateMarkers(updatedMarkers);
|
||
|
||
console.log('用户头像已更新');
|
||
}
|
||
|
||
/**
|
||
* 更新员工标记点
|
||
*/
|
||
updateEmployeeMarkers(employeeMarkers: Marker[]): void {
|
||
console.log('开始更新员工标记点,数量:', employeeMarkers.length);
|
||
|
||
const { markers } = this.pageContext.data;
|
||
|
||
// 过滤掉现有的员工标记点
|
||
const filteredMarkers = markers.filter((marker: any) =>
|
||
marker.type !== 'employee'
|
||
);
|
||
|
||
// 合并标记点
|
||
const updatedMarkers = [...filteredMarkers, ...employeeMarkers];
|
||
|
||
// 更新数据模块中的标记点
|
||
this.dataModule.updateMarkers(updatedMarkers);
|
||
|
||
console.log('员工标记点更新完成,总标记点数量:', updatedMarkers.length);
|
||
}
|
||
|
||
/**
|
||
* 更新单个员工标记点
|
||
*/
|
||
updateSingleEmployeeMarker(employeeMarker: Marker): void {
|
||
console.log('更新单个员工标记点:', employeeMarker.id);
|
||
|
||
const { markers } = this.pageContext.data;
|
||
|
||
// 查找现有的员工标记点
|
||
const markerIndex = markers.findIndex((marker: any) =>
|
||
marker.type === 'employee' && marker.id === employeeMarker.id
|
||
);
|
||
|
||
let updatedMarkers;
|
||
if (markerIndex !== -1) {
|
||
// 更新现有的标记点
|
||
updatedMarkers = [...markers];
|
||
updatedMarkers[markerIndex] = employeeMarker;
|
||
} else {
|
||
// 添加新的标记点
|
||
updatedMarkers = [...markers, employeeMarker];
|
||
}
|
||
|
||
// 更新数据模块中的标记点
|
||
this.dataModule.updateMarkers(updatedMarkers);
|
||
|
||
console.log('单个员工标记点更新完成');
|
||
}
|
||
|
||
/**
|
||
* 处理地图点击事件
|
||
*/
|
||
onMapTap(e: any): void {
|
||
console.log('地图被点击:', e);
|
||
// 可以在这里添加地图点击的处理逻辑
|
||
}
|
||
|
||
/**
|
||
* 处理标记点点击事件
|
||
*/
|
||
onMarkerTap(e: any): void {
|
||
const markerId = e.markerId;
|
||
console.log('标记点被点击:', markerId);
|
||
|
||
// 根据标记点ID处理不同的点击逻辑
|
||
this.handleMarkerClick(markerId);
|
||
}
|
||
|
||
/**
|
||
* 处理标记点点击
|
||
*/
|
||
private handleMarkerClick(markerId: number): void {
|
||
// 这里可以根据标记点ID进行不同的处理
|
||
// 例如:显示订单详情、货运人员信息等
|
||
|
||
if (markerId === -1) {
|
||
// 用户位置标记
|
||
this.pageContext.showUserPanel();
|
||
}
|
||
// 可以添加其他标记点的处理逻辑
|
||
}
|
||
} |