Files
WXProgram/dist/services/locationTrackingService.js
2025-10-26 13:15:04 +08:00

483 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const apiService_1 = __importDefault(require("./apiService"));
const userService_1 = __importDefault(require("./userService"));
const mapService_1 = __importDefault(require("./mapService"));
/**
* 位置追踪服务类
* 提供用户签到后的位置追踪、状态管理和位置分发功能
*/
class LocationTrackingService {
/**
* 构造函数
*/
constructor() {
// 取消订阅回调函数
this.unsubscribeCallback = null;
this.onlineUsers = new Map();
this.locationUpdateTimer = null;
this.userStatusCallback = null;
this.locationUpdateCallback = null;
this.isSignedIn = false;
this.unsubscribeCallback = null;
}
/**
* 启动位置追踪服务WebSocket连接
*/
async startTracking() {
const userInfo = userService_1.default.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
throw new Error('用户未登录,无法启动位置追踪');
}
this.isSignedIn = true;
// 设置实时位置订阅初始化WebSocket连接
await this.setupRealTimeSubscription();
// 启动位置更新定时器每30秒向服务器发送位置信息
this.startLocationUpdateTimer();
console.log('位置追踪服务已启动');
}
/**
* 初始化位置追踪服务
*/
async initialize() {
}
/**
* 停止位置追踪服务WebSocket断开时调用
*/
async stopTracking() {
const userInfo = userService_1.default.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
return;
}
this.isSignedIn = false;
// 停止位置更新定时器
this.stopLocationUpdateTimer();
// 关闭WebSocket连接
try {
await this.teardownRealTimeSubscription();
console.log('调试信息 - WebSocket连接已关闭');
}
catch (error) {
console.warn('调试信息 - 关闭WebSocket连接失败:', error);
}
// 清空在线用户列表WebSocket断开时清空所有数据
this.onlineUsers.clear();
// 通知所有位置更新回调,清空地图标记点
this.notifyLocationUpdateCallbacks();
console.log('位置追踪服务已停止,在线用户列表已清空');
}
/**
* 向服务器发送位置更新(仅发送,不更新本地缓存)
*/
async updateUserLocation(location) {
const userInfo = userService_1.default.getGlobalUserInfo();
if (!userInfo || !userInfo.id || !this.isSignedIn) {
console.warn('[位置追踪服务] 用户未登录或未签到,无法更新位置');
return;
}
console.log('[位置追踪服务] 向服务器发送位置信息:');
console.log(`- 用户ID: ${userInfo.id}`);
console.log(`- 经度: ${location.longitude}`);
console.log(`- 纬度: ${location.latitude}`);
// 通过WebSocket发送位置更新给服务器
await apiService_1.default.sendLocationUpdate(userInfo.id, location.latitude, location.longitude);
console.log('[位置追踪服务] 位置信息已发送到服务器');
}
/**
* 获取所有在线用户信息
*/
getOnlineUsers() {
return Array.from(this.onlineUsers.values()).filter(user => user.status === 'online');
}
/**
* 订阅用户状态变化(单一方法赋值)
* @param callback 用户状态变化回调函数
* @returns 取消订阅函数
*/
subscribeToUserStatusChanges(callback) {
console.log('📝 [LocationTrackingService] 注册用户状态变化回调函数');
// 直接赋值,覆盖之前的回调
this.userStatusCallback = callback;
console.log('✅ [LocationTrackingService] 用户状态变化回调注册完成');
// 返回取消订阅函数
return () => {
if (this.userStatusCallback === callback) {
this.userStatusCallback = null;
console.log('✅ [LocationTrackingService] 用户状态变化回调已取消');
}
};
}
/**
* 检查用户是否在线
*/
isUserOnline(userId) {
const userInfo = this.onlineUsers.get(userId);
return userInfo ? userInfo.status === 'online' : false;
}
// ===== 私有方法 =====
/**
* 启动位置更新定时器
*/
startLocationUpdateTimer() {
this.stopLocationUpdateTimer();
this.locationUpdateTimer = setInterval(async () => {
if (this.isSignedIn) {
try {
const location = await this.getCurrentLocation();
await this.updateUserLocation(location);
}
catch (error) {
console.error('自动位置更新失败:', error);
}
}
}, 30000); // 每30秒更新一次
}
/**
* 获取当前位置
*/
async getCurrentLocation() {
const userInfo = userService_1.default.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
throw new Error('用户未登录');
}
try {
// 使用mapService获取真实位置保持与项目中其他地方的一致性
const location = await mapService_1.default.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()
};
}
}
/**
* 设置实时位置订阅
*/
async setupRealTimeSubscription() {
// 获取用户信息
const userInfo = userService_1.default.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
console.warn('用户未登录,无法设置实时位置订阅');
return;
}
// 缓存用户信息(已移除)
// 真实环境初始化WebSocket连接服务器会自动处理订阅逻辑
try {
// 初始化WebSocket连接如果尚未连接
await apiService_1.default.initLocationWebSocket();
// 等待WebSocket连接建立最多等待5秒
await new Promise((resolve, reject) => {
let attempts = 0;
const maxAttempts = 50; // 5秒超时
const checkConnection = () => {
if (apiService_1.default.isWebSocketConnected()) {
resolve();
}
else if (attempts < maxAttempts) {
attempts++;
setTimeout(checkConnection, 100);
}
else {
reject(new Error('WebSocket连接建立超时'));
}
};
checkConnection();
});
// 服务器会自动处理订阅逻辑,无需发送订阅消息
console.log('WebSocket连接已建立服务器将自动处理位置订阅逻辑');
}
catch (error) {
console.error('设置实时位置订阅失败:', error);
}
}
/**
* 关闭实时位置订阅
*/
teardownRealTimeSubscription() {
// 真实环境关闭WebSocket连接服务器会自动处理取消订阅逻辑
try {
// 服务器会自动处理取消订阅逻辑,无需发送取消订阅消息
console.log('关闭WebSocket连接服务器将自动处理取消订阅逻辑');
// 移除位置更新回调
if (this.unsubscribeCallback) {
this.unsubscribeCallback();
this.unsubscribeCallback = null;
}
// 关闭WebSocket连接
apiService_1.default.closeLocationWebSocket();
}
catch (error) {
console.error('关闭实时位置订阅失败:', error);
}
}
/**
* 停止位置更新定时器
*/
stopLocationUpdateTimer() {
if (this.locationUpdateTimer) {
clearInterval(this.locationUpdateTimer);
this.locationUpdateTimer = null;
}
}
/**
* 通知位置更新回调
*/
notifyLocationUpdateCallbacks() {
const onlineUsers = this.getOnlineUsers();
console.log('🔔 [LocationTrackingService] 开始通知位置更新回调');
console.log('👥 [LocationTrackingService] 在线用户数量:', onlineUsers.length);
// 触发位置更新回调
if (this.locationUpdateCallback) {
try {
console.log('🔄 [LocationTrackingService] 执行位置更新回调');
this.locationUpdateCallback(onlineUsers);
console.log('✅ [LocationTrackingService] 位置更新回调执行成功');
}
catch (error) {
console.error('❌ [LocationTrackingService] 位置更新回调执行失败:', error);
}
}
else {
console.log('⚠️ [LocationTrackingService] 没有注册位置更新回调');
}
console.log('🏁 [LocationTrackingService] 位置更新回调通知完成');
}
/**
* 手动触发位置更新(公共方法,可从外部调用)
* 用于手动刷新地图上的用户标记
*/
triggerLocationUpdate() {
console.log('🔔 [LocationTrackingService] 手动触发位置更新');
this.notifyLocationUpdateCallbacks();
}
/**
* 订阅位置更新用于locationModule注册回调
* @param callback 位置更新回调函数
* @returns 取消订阅函数
*/
subscribeToLocationUpdates(callback) {
console.log('📝 [LocationTrackingService] 注册位置更新回调函数');
// 直接赋值,覆盖之前的回调
this.locationUpdateCallback = callback;
console.log('✅ [LocationTrackingService] 位置更新回调注册完成');
// 返回取消订阅函数
return () => {
if (this.locationUpdateCallback === callback) {
this.locationUpdateCallback = null;
console.log('✅ [LocationTrackingService] 位置更新回调已取消');
}
};
}
/**
* 通知用户状态变化回调
*/
notifyUserStatusChange(userId, status) {
console.log(`🔔 [LocationTrackingService] 开始通知用户状态变化回调: 用户 ${userId} 状态变为 ${status}`);
if (this.userStatusCallback) {
try {
console.log('🔄 [LocationTrackingService] 执行用户状态变化回调');
this.userStatusCallback(userId, status);
console.log('✅ [LocationTrackingService] 用户状态变化回调执行成功');
}
catch (error) {
console.error('❌ [LocationTrackingService] 用户状态变化回调执行失败:', error);
}
}
else {
console.log('⚠️ [LocationTrackingService] 没有注册用户状态变化回调');
}
console.log('🏁 [LocationTrackingService] 用户状态变化回调通知完成');
}
/**
* 处理WebSocket消息
* @param message 服务器下发的消息
*/
handleWebSocketMessage(message) {
console.log(`📡 收到WebSocket消息类型: ${message.type}`, message);
switch (message.type) {
case 'onlineUserList':
// 处理在线用户列表消息(服务器发送当前在线用户列表)
console.log('👥 处理在线用户列表,用户数量:', message.users ? message.users.length : 0);
if (message.users && Array.isArray(message.users)) {
this.triggerOnlineUserListCallbacks({
type: 'onlineUserList',
users: message.users.map((user) => ({
userId: user.userId,
name: user.name,
role: user.role,
userStatus: user.userStatus,
lastUpdateTime: user.lastUpdateTime,
latitude: user.locationData?.latitude || user.latitude,
longitude: user.locationData?.longitude || user.longitude,
timestamp: user.locationData?.timestamp || user.timestamp
}))
});
}
else {
console.warn('❌ onlineUserList消息格式错误users字段不存在或不是数组');
}
break;
case 'userLocationList':
// 处理用户位置列表消息服务器每30秒发送所有在线用户的位置列表
console.log('👥 处理用户位置列表,用户数量:', message.users ? message.users.length : 0);
// 确保用户列表存在且是数组
if (message.users && Array.isArray(message.users)) {
// 转换用户数据格式,确保与位置追踪服务兼容
const formattedUsers = message.users.map((user) => {
// 支持多种数据格式locationData字段或直接字段
const locationData = user.locationData || user;
// 验证必需字段是否存在
if (!user.userId && !locationData.userId) {
console.error('❌ 用户数据缺少userId字段:', user);
return null;
}
if (locationData.latitude === undefined || locationData.longitude === undefined) {
console.error('❌ 用户数据缺少位置信息:', user);
return null;
}
// 对于位置更新消息允许缺少name和role字段从本地缓存中获取
const existingUser = this.onlineUsers.get(user.userId || locationData.userId);
const formattedUser = {
userId: user.userId || locationData.userId,
name: user.name || user.userName || (existingUser ? existingUser.name : `用户${user.userId || locationData.userId}`),
role: user.role || (existingUser ? existingUser.role : 'DRIVER'),
userStatus: user.userStatus !== false, // 转换为布尔值
lastUpdateTime: user.lastUpdateTime || locationData.timestamp || Date.now(),
latitude: locationData.latitude,
longitude: locationData.longitude,
timestamp: locationData.timestamp || user.timestamp || Date.now()
};
// 验证必需字段
if (!formattedUser.userId) {
console.error('❌ 用户数据缺少userId字段:', formattedUser);
return null;
}
return formattedUser;
}).filter((user) => user !== null); // 过滤掉无效数据
console.log('📊 转换后的用户位置数据:', formattedUsers);
this.triggerOnlineUserListCallbacks({
type: 'userLocationList',
users: formattedUsers
});
}
else {
console.warn('❌ userLocationList消息格式错误users字段不存在或不是数组');
}
break;
default:
console.warn('收到未知类型的WebSocket消息:', message);
break;
}
}
/**
* 触发在线用户列表回调函数
* @param userList 在线用户列表数据
*/
triggerOnlineUserListCallbacks(userList) {
console.log('🔔 [apiService] 开始触发在线用户列表回调,消息类型:', userList.type);
console.log('📊 [apiService] 回调数据内容:', JSON.stringify(userList, null, 2));
try {
console.log('🔄 [apiService] 执行在线用户列表回调函数');
// 传递正确的数据格式只传递users数组而不是整个消息对象
this.handleOnlineUserList(userList.users);
console.log('✅ [apiService] 在线用户列表回调函数执行成功');
}
catch (error) {
console.error('❌ [apiService] 在线用户列表回调函数执行失败:', error);
}
console.log('🏁 [apiService] 在线用户列表回调触发完成');
}
/**
* 处理在线用户列表
* @param userList 服务器下发的在线用户列表
*/
handleOnlineUserList(userList) {
try {
// 验证数据格式
if (!Array.isArray(userList)) {
console.warn('[LocationTrackingService] 无效的在线用户列表数据格式');
return;
}
console.log(`[LocationTrackingService] 开始处理在线用户列表,用户数量: ${userList.length}`);
// 获取当前本地用户列表的userId集合
const currentUserIds = new Set(this.onlineUsers.keys());
// 处理服务器下发的用户列表
const newUserIds = new Set();
userList.forEach(user => {
if (user && user.userId && user.latitude !== undefined && user.longitude !== undefined) {
newUserIds.add(user.userId);
// 提取位置数据(支持多种数据格式)
const latitude = user.latitude;
const longitude = user.longitude;
const timestamp = user.timestamp || user.lastUpdateTime || Date.now();
// 对于位置更新消息允许缺少name和role字段从本地缓存中获取
const existingUser = this.onlineUsers.get(user.userId);
// 更新或添加用户信息
this.onlineUsers.set(user.userId, {
userId: user.userId,
name: user.name || user.userName || (existingUser ? existingUser.name : `用户${user.userId}`),
avatarUrl: '/images/user-avatar.png',
role: user.role || (existingUser ? existingUser.role : 'DRIVER'),
lastLocation: {
userId: user.userId,
longitude: longitude,
latitude: latitude,
timestamp: timestamp
},
lastUpdateTime: timestamp,
status: user.userStatus === false ? 'offline' : 'online'
});
console.log(`[LocationTrackingService] 更新用户 ${user.userId} 位置: (${latitude}, ${longitude})`);
// 如果用户是新上线的,触发用户状态回调
if (!currentUserIds.has(user.userId)) {
this.notifyUserStatusChange(user.userId, 'online');
console.log(`[LocationTrackingService] 新用户上线: ${user.userId}`);
}
}
else {
console.warn(`[LocationTrackingService] 跳过无效用户数据:`, user);
}
});
// 删除本地列表中不在服务器列表中的用户
let removedCount = 0;
currentUserIds.forEach(userId => {
if (!newUserIds.has(userId)) {
// 删除离线用户
this.onlineUsers.delete(userId);
removedCount++;
// 触发用户状态回调(离线)
this.notifyUserStatusChange(userId, 'offline');
console.log(`[LocationTrackingService] 用户离线: ${userId}`);
}
});
console.log(`[LocationTrackingService] 在线用户列表更新完成: 新增 ${newUserIds.size - (currentUserIds.size - removedCount)} 个用户,删除 ${removedCount} 个用户`);
// 通知位置模块更新地图标记点(无论是否有变化都通知,确保地图标记点同步)
this.notifyLocationUpdateCallbacks();
console.log('[LocationTrackingService] 已通知位置模块更新地图标记点');
}
catch (error) {
console.error('[LocationTrackingService] 处理在线用户列表失败:', error);
}
}
}
/**
* 位置追踪服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new LocationTrackingService();