修改位置交互,修改代码逻辑
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user