修改位置交互,修改代码逻辑

This commit is contained in:
2025-10-18 22:21:04 +08:00
parent c446df73b5
commit 39fa0b2d04
36 changed files with 2743 additions and 1995 deletions

View File

@@ -1,8 +1,8 @@
// 位置追踪服务 - 处理用户签到后的位置追踪和状态管理
import { UserInfo, LocationData } from '../types';
import apiService from './apiService';
import { isMockMode } from './apiService';
import userService from './userService';
import mapService from './mapService';
/**
* 在线用户信息接口
@@ -11,6 +11,7 @@ export interface OnlineUserInfo {
userId: number;
name: string;
avatarUrl: string;
role: string; // 用户角色:'admin' | 'delivery_person'
lastLocation: LocationData;
lastUpdateTime: number;
status: 'online' | 'offline' | 'timeout';
@@ -73,17 +74,50 @@ class LocationTrackingService {
// 将当前用户添加到在线列表
await this.addUserToOnlineList(userInfo);
// 签到消息已通过REST API处理服务器会自动处理订阅逻辑
// 设置实时位置订阅初始化WebSocket连接
await this.setupRealTimeSubscription();
// WebSocket连接成功后立即发送第一次位置信息
try {
const location = await this.getCurrentLocation();
await this.updateUserLocation(location);
console.log('WebSocket连接成功后立即发送第一次位置信息');
} catch (error) {
console.error('立即发送位置信息失败:', error);
}
// 启动位置更新定时器每30秒更新一次
this.startLocationUpdateTimer();
// 启动状态检查定时器每60秒检查一次
this.startStatusCheckTimer();
// 订阅其他用户的位置更新
await this.subscribeToOtherUsersLocations();
console.log('位置追踪服务已启动');
}
/**
* 初始化位置追踪服务
*/
public async initialize(): Promise<void> {
try {
// 注册位置更新回调
apiService.onLocationUpdate((locationUpdate) => {
this.handleLocationUpdate(locationUpdate);
});
// 注册在线用户列表回调
apiService.onOnlineUserList((userList) => {
this.handleOnlineUserList(userList);
});
console.log('[LocationTrackingService] 位置追踪服务初始化完成');
} catch (error) {
console.error('[LocationTrackingService] 初始化失败:', error);
throw error;
}
}
/**
* 用户签退后停止位置追踪
@@ -96,14 +130,16 @@ class LocationTrackingService {
this.isSignedIn = false;
// 签退消息已通过REST API处理服务器会自动处理取消订阅逻辑
// 从在线列表中移除用户
this.removeUserFromOnlineList(userInfo.id);
// 停止定时器
this.stopTimers();
// 取消订阅
await this.unsubscribeFromLocations();
// 关闭实时位置订阅(服务器会自动处理取消订阅
this.teardownRealTimeSubscription();
console.log('位置追踪服务已停止');
}
@@ -131,18 +167,12 @@ class LocationTrackingService {
timestamp: Date.now()
};
if (isMockMode) {
// 模拟模式:更新本地在线用户列表
console.log('[位置追踪服务] 模拟模式:更新本地位置');
this.updateLocalUserLocation(userInfo.id, locationData);
} else {
// 真实模式调用API更新位置
console.log('[位置追踪服务] 真实模式调用API更新位置');
await apiService.updateDeliveryPersonLocation(userInfo.id, location);
// 同时更新本地缓存
this.updateLocalUserLocation(userInfo.id, locationData);
}
// 真实模式通过WebSocket发送位置更新
console.log('[位置追踪服务] 真实模式通过WebSocket发送位置更新');
await apiService.sendLocationUpdate(userInfo.id, location.latitude, location.longitude);
// 同时更新本地缓存
this.updateLocalUserLocation(userInfo.id, locationData);
// 通知所有回调
this.notifyLocationUpdateCallbacks();
@@ -206,6 +236,7 @@ class LocationTrackingService {
userId: userInfo.id,
name: userInfo.name || '未知用户',
avatarUrl: '/images/user-avatar.png',
role: userInfo.role || 'delivery_person', // 用户角色
lastLocation: currentLocation,
lastUpdateTime: Date.now(),
status: 'online'
@@ -213,7 +244,7 @@ class LocationTrackingService {
this.onlineUsers.set(userInfo.id, onlineUser);
console.log(`用户 ${userInfo.id} 已添加到在线列表`);
}
@@ -305,101 +336,49 @@ class LocationTrackingService {
throw new Error('用户未登录');
}
// 这里应该调用地图服务获取当前位置
// 暂时返回一个默认位置
return {
userId: userInfo.id,
longitude: 102.833722,
latitude: 24.880095,
timestamp: Date.now()
};
}
/**
* 订阅其他用户的位置更新
*/
private async subscribeToOtherUsersLocations(): Promise<void> {
if (isMockMode) {
// 模拟模式:定时生成其他用户的位置更新
this.startMockOtherUsersUpdates();
} else {
// 真实模式通过WebSocket订阅
await this.setupRealTimeSubscription();
try {
// 使用mapService获取真实位置保持与项目中其他地方的一致性
const location = await mapService.getLocation();
console.log('[位置追踪服务] 获取真实位置成功:', location);
return {
userId: userInfo.id,
longitude: location.longitude,
latitude: location.latitude,
timestamp: Date.now()
};
} catch (error) {
console.error('[位置追踪服务] 获取真实位置失败,使用默认位置:', error);
// 定位失败时返回默认位置作为降级方案
return {
userId: userInfo.id,
longitude: 102.833722,
latitude: 24.880095,
timestamp: Date.now()
};
}
}
/**
* 取消订阅位置更新
*/
private async unsubscribeFromLocations(): Promise<void> {
if (!isMockMode) {
// 真实模式取消WebSocket订阅
await this.teardownRealTimeSubscription();
}
// 真实模式取消WebSocket订阅
await this.teardownRealTimeSubscription();
}
/**
* 启动模拟的其他用户位置更新
*/
private startMockOtherUsersUpdates(): void {
// 模拟其他用户的位置更新每45秒一次
setInterval(() => {
if (this.isSignedIn) {
this.generateMockOtherUsersLocations();
this.notifyLocationUpdateCallbacks();
}
}, 45000);
}
/**
* 生成模拟的其他用户位置
*/
private generateMockOtherUsersLocations(): void {
const currentUserInfo = userService.getGlobalUserInfo();
if (!currentUserInfo) return;
// 模拟2个其他在线用户
const mockUserIds = [101, 102]; // 模拟用户ID
mockUserIds.forEach(userId => {
if (userId !== currentUserInfo.id) {
const existingUser = this.onlineUsers.get(userId);
if (existingUser) {
// 更新现有用户位置
existingUser.lastLocation.longitude += (Math.random() - 0.5) * 0.001;
existingUser.lastLocation.latitude += (Math.random() - 0.5) * 0.001;
existingUser.lastUpdateTime = Date.now();
existingUser.status = 'online';
this.onlineUsers.set(userId, existingUser);
} else {
// 添加新用户
const newUser: OnlineUserInfo = {
userId,
name: `用户${userId}`,
avatarUrl: '/images/user-avatar.png',
lastLocation: {
userId,
longitude: 102.833722 + (Math.random() - 0.5) * 0.01,
latitude: 24.880095 + (Math.random() - 0.5) * 0.01,
timestamp: Date.now()
},
lastUpdateTime: Date.now(),
status: 'online'
};
this.onlineUsers.set(userId, newUser);
this.notifyUserStatusChange(userId, 'online');
}
}
});
}
/**
* 设置实时位置订阅
*/
private setupRealTimeSubscription(): void {
private async setupRealTimeSubscription(): Promise<void> {
// 获取用户信息
const userInfo = userService.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
@@ -410,25 +389,31 @@ class LocationTrackingService {
// 缓存用户信息
this.userInfo = userInfo;
if (isMockMode) {
console.log('[MOCK] 设置实时位置订阅');
this.startMockLocationGeneration();
return;
}
// 真实环境初始化WebSocket连接并订阅位置更新
// 真实环境初始化WebSocket连接服务器会自动处理订阅逻辑
try {
// 使用新的API接口
apiService.initLocationWebSocket();
// 初始化WebSocket连接如果尚未连接
await apiService.initLocationWebSocket();
// 订阅当前用户的位置更新
apiService.subscribeToLocationUpdates(this.userInfo.id)
.then(() => {
console.log('成功订阅位置更新');
})
.catch((error) => {
console.error('订阅位置更新失败:', error);
});
// 等待WebSocket连接建立最多等待5秒
await new Promise<void>((resolve, reject) => {
let attempts = 0;
const maxAttempts = 50; // 5秒超时
const checkConnection = () => {
if (apiService.isWebSocketConnected()) {
resolve();
} else if (attempts < maxAttempts) {
attempts++;
setTimeout(checkConnection, 100);
} else {
reject(new Error('WebSocket连接建立超时'));
}
};
checkConnection();
});
// 服务器会自动处理订阅逻辑,无需发送订阅消息
console.log('WebSocket连接已建立服务器将自动处理位置订阅逻辑');
// 设置位置更新回调
this.unsubscribeCallback = apiService.onLocationUpdate((locationUpdate) => {
@@ -444,24 +429,10 @@ class LocationTrackingService {
* 关闭实时位置订阅
*/
private teardownRealTimeSubscription(): void {
if (isMockMode) {
console.log('[MOCK] 关闭实时位置订阅');
this.stopMockLocationGeneration();
return;
}
// 真实环境取消订阅并关闭WebSocket连接
// 真实环境关闭WebSocket连接服务器会自动处理取消订阅逻辑
try {
if (this.userInfo) {
// 使用新的API接口取消订阅
apiService.unsubscribeFromLocationUpdates(this.userInfo.id)
.then(() => {
console.log('成功取消订阅位置更新');
})
.catch((error) => {
console.error('取消订阅位置更新失败:', error);
});
}
// 服务器会自动处理取消订阅逻辑,无需发送取消订阅消息
console.log('关闭WebSocket连接服务器将自动处理取消订阅逻辑');
// 移除位置更新回调
if (this.unsubscribeCallback) {
@@ -532,28 +503,88 @@ class LocationTrackingService {
});
}
/**
* 启动模拟位置生成
*/
private startMockLocationGeneration(): void {
console.log('[MOCK] 启动模拟位置生成');
// 这里可以添加模拟位置生成的逻辑
}
/**
* 停止模拟位置生成
*/
private stopMockLocationGeneration(): void {
console.log('[MOCK] 停止模拟位置生成');
// 这里可以添加停止模拟位置生成的逻辑
}
/**
* 处理位置更新
*/
private handleLocationUpdate(locationUpdate: any): void {
console.log('收到位置更新:', locationUpdate);
// 这里可以添加处理位置更新的逻辑
// 验证位置更新消息格式
if (!locationUpdate || typeof locationUpdate !== 'object') {
console.warn('无效的位置更新消息格式');
return;
}
// 提取关键信息
const { deliveryPersonId, latitude, longitude, timestamp } = locationUpdate;
if (!deliveryPersonId || latitude === undefined || longitude === undefined) {
console.warn('位置更新消息缺少必要字段:', locationUpdate);
return;
}
console.log(`处理员工 ${deliveryPersonId} 的位置更新: (${longitude}, ${latitude})`);
// 更新本地缓存中的员工位置
this.updateLocalUserLocation(deliveryPersonId, {
userId: deliveryPersonId,
longitude: longitude,
latitude: latitude,
timestamp: timestamp || Date.now()
});
// 通知所有位置更新回调UI层会监听这些回调来更新地图标记点
this.notifyLocationUpdateCallbacks();
console.log(`员工 ${deliveryPersonId} 位置更新处理完成`);
}
/**
* 处理在线用户列表消息
* @param userList 在线用户列表消息
*/
private handleOnlineUserList(userList: any): void {
try {
console.log('[LocationTrackingService] 收到在线用户列表:', userList);
if (!userList || !userList.users) {
console.warn('[LocationTrackingService] 无效的在线用户列表消息');
return;
}
// 清空当前在线用户列表
this.onlineUsers.clear();
// 更新在线用户列表
userList.users.forEach((userInfo: any) => {
if (userInfo && userInfo.userId) {
this.onlineUsers.set(userInfo.userId, {
userId: userInfo.userId,
name: userInfo.userName || '未知用户',
avatarUrl: '/images/user-avatar.png',
role: userInfo.role || 'delivery_person', // 用户角色,默认为配送员
lastLocation: {
userId: userInfo.userId,
longitude: userInfo.longitude || 0,
latitude: userInfo.latitude || 0,
timestamp: userInfo.lastUpdateTime || Date.now()
},
lastUpdateTime: userInfo.lastUpdateTime || Date.now(),
status: 'online'
});
}
});
console.log('[LocationTrackingService] 在线用户列表已更新,当前在线用户数:', this.onlineUsers.size);
// 通知位置模块更新地图标记点
this.notifyLocationUpdateCallbacks();
} catch (error) {
console.error('[LocationTrackingService] 处理在线用户列表失败:', error);
}
}
}