Files
WXProgram/miniprogram/services/deliveryPersonService.ts
2025-10-16 21:32:16 +08:00

433 lines
13 KiB
TypeScript
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.

// 货运人员服务 - 处理货运人员相关的数据操作
import { DeliveryPerson, LocationData } from '../types';
import apiService from './apiService';
import { isMockMode } from './apiService';
/**
* 货运人员服务类
* 提供货运人员信息管理、位置更新、状态管理等功能
*/
class DeliveryPersonService {
// 模拟货运人员数据
private mockDeliveryPersons: DeliveryPerson[];
/**
* 构造函数
*/
constructor() {
this.mockDeliveryPersons = [
{
id: 101,
name: '张师傅',
phone: '13812345678',
status: 'idle',
currentLocation: {
longitude: 102.714585,
latitude: 25.046321
},
currentOrders: []
},
{
id: 102,
name: '李师傅',
phone: '13912345678',
status: 'busy',
currentLocation: {
longitude: 102.690181,
latitude: 24.994788
},
currentOrders: [
{
id: 1002,
startPoint: {
id: 2,
name: '瓦尔塔蓄电池盘龙区分店',
longitude: 102.728421,
latitude: 25.042498
},
endPoint: {
name: '云南中致远汽车销售有限公司',
longitude: 102.796212,
latitude: 24.936947
},
status: 'assigned',
goodsType: '瓦尔塔EFB蓄电池',
goodsWeight: 120,
createTime: Date.now() - 7200000
}
]
}
];
this.locationUpdateCallbacks = null;
this.locationUpdateTimer = null;
this.unsubscribeFunction = null;
}
/**
* 获取所有货运人员
* @returns 货运人员列表
*/
async getDeliveryPersons(): Promise<DeliveryPerson[]> {
if (isMockMode) {
// 模拟数据 - 返回所有货运人员
console.log('[MOCK] 获取所有货运人员');
return [...this.mockDeliveryPersons];
}
return apiService.getDeliveryPersons();
}
/**
* 根据ID获取货运人员
* @param id 货运人员ID
* @returns 货运人员信息或null
*/
async getDeliveryPersonById(id: number): Promise<DeliveryPerson | null> {
if (isMockMode) {
// 模拟数据 - 根据ID查找货运人员
console.log('[MOCK] 根据ID获取货运人员ID:', id);
const person = this.mockDeliveryPersons.find(p => p.id === id);
return person || null;
}
try {
const result = await apiService.getDeliveryPersonById(id);
return result;
} catch (error) {
console.error('获取货运人员失败:', error);
return null;
}
}
/**
* 更新货运人员位置
* @param id 货运人员ID
* @param location 位置信息
*/
async updateDeliveryPersonLocation(
id: number,
location: { longitude: number; latitude: number }
): Promise<void> {
if (isMockMode) {
// 模拟数据 - 更新货运人员位置
console.log('[MOCK] 更新货运人员位置ID:', id, '位置:', location);
const person = this.mockDeliveryPersons.find(p => p.id === id);
if (person) {
person.currentLocation = location;
}
return;
}
return apiService.updateDeliveryPersonLocation(id, location);
}
/**
* 批量更新货运人员位置
* @param locations 位置信息数组
*/
async batchUpdateDeliveryPersonLocations(locations: Array<{
deliveryPersonId: number;
longitude: number;
latitude: number;
timestamp: number;
}>): Promise<void> {
if (isMockMode) {
// 模拟数据 - 批量更新货运人员位置
console.log('[MOCK] 批量更新货运人员位置');
locations.forEach(item => {
const person = this.mockDeliveryPersons.find(p => p.id === item.deliveryPersonId);
if (person) {
person.currentLocation = { longitude: item.longitude, latitude: item.latitude };
}
});
return;
}
// 修复转换参数格式以匹配apiService的要求
const formattedLocations = locations.map(loc => ({
userId: loc.deliveryPersonId, // 将deliveryPersonId转换为userId
longitude: loc.longitude,
latitude: loc.latitude,
timestamp: loc.timestamp
}));
return apiService.batchUpdateDeliveryPersonLocations(formattedLocations);
}
/**
* 获取空闲的货运人员
* @returns 空闲货运人员列表
*/
async getIdleDeliveryPersons(): Promise<DeliveryPerson[]> {
if (isMockMode) {
// 模拟数据 - 返回空闲的货运人员
console.log('[MOCK] 获取空闲的货运人员');
return this.mockDeliveryPersons.filter(p => p.status === 'idle');
}
return apiService.getIdleDeliveryPersons();
}
/**
* 获取忙碌的货运人员
* @returns 忙碌货运人员列表
*/
async getBusyDeliveryPersons(): Promise<DeliveryPerson[]> {
if (isMockMode) {
// 模拟数据 - 返回忙碌的货运人员
console.log('[MOCK] 获取忙碌的货运人员');
return this.mockDeliveryPersons.filter(p => p.status === 'busy');
}
return apiService.getBusyDeliveryPersons();
}
/**
* 获取位置历史记录
* @param deliveryPersonId 货运人员ID
* @param limit 记录数量
* @returns 位置历史记录
*/
async getLocationHistory(deliveryPersonId: number, limit: number = 50): Promise<Array<{
timestamp: number;
longitude: number;
latitude: number;
speed?: number;
accuracy?: number;
}>> {
if (isMockMode) {
// 模拟数据 - 返回位置历史记录
console.log('[MOCK] 获取货运人员位置历史记录ID:', deliveryPersonId);
const mockHistory = [];
const person = this.mockDeliveryPersons.find(p => p.id === deliveryPersonId);
if (person) {
// 生成一些模拟的位置历史记录
for (let i = 0; i < limit; i++) {
// 在当前位置附近随机生成一些位置点
const baseLongitude = person.currentLocation.longitude;
const baseLatitude = person.currentLocation.latitude;
mockHistory.push({
timestamp: Date.now() - i * 60000, // 每分钟一个点
longitude: baseLongitude + (Math.random() - 0.5) * 0.01,
latitude: baseLatitude + (Math.random() - 0.5) * 0.01,
speed: Math.random() * 60, // 0-60 km/h
accuracy: 5 + Math.random() * 15 // 5-20 meters
});
}
}
return mockHistory;
}
return apiService.getLocationHistory(deliveryPersonId, limit);
}
/**
* 订阅实时位置更新兼容mapService参数
* @param callback 位置更新回调函数
*/
async subscribeToRealTimeLocations(callback: (location: LocationData) => void): Promise<void> {
if (isMockMode) {
// 模拟实时位置更新
console.log('[MOCK] 订阅实时位置更新');
// 保存回调引用,以便在取消订阅时使用
if (!this.locationUpdateCallbacks) {
this.locationUpdateCallbacks = new Set();
}
this.locationUpdateCallbacks.add(callback);
// 如果是首次订阅,启动模拟更新
if (!this.locationUpdateTimer) {
this.startMockLocationUpdates();
}
return;
}
// 真实环境中实现WebSocket连接
try {
// 获取当前用户信息
const userInfo = wx.getStorageSync('userInfo');
if (!userInfo || !userInfo.id) {
throw new Error('用户未登录,无法订阅位置更新');
}
// 初始化WebSocket连接
await apiService.initLocationWebSocket();
// 订阅位置更新
await apiService.subscribeToLocationUpdates(userInfo.id);
// 设置位置更新回调
this.unsubscribeFunction = apiService.onLocationUpdate((location) => {
callback(location as LocationData);
});
console.log('WebSocket位置订阅成功');
} catch (error) {
console.error('订阅实时位置更新失败:', error);
throw error;
}
}
/**
* 取消订阅实时位置更新(兼容无参数调用)
*/
async unsubscribeFromRealTimeLocations(): Promise<void> {
if (isMockMode) {
// 模拟取消订阅
console.log('[MOCK] 取消订阅实时位置更新');
// 清除所有回调
if (this.locationUpdateCallbacks) {
this.locationUpdateCallbacks.clear();
}
// 停止模拟更新定时器
if (this.locationUpdateTimer) {
clearInterval(this.locationUpdateTimer);
this.locationUpdateTimer = null;
}
return;
}
// 真实环境中关闭WebSocket连接
try {
// 获取当前用户信息
const userInfo = wx.getStorageSync('userInfo');
if (userInfo && userInfo.id) {
// 取消订阅
await apiService.unsubscribeFromLocationUpdates(userInfo.id);
}
// 调用取消订阅函数
if (this.unsubscribeFunction) {
this.unsubscribeFunction();
this.unsubscribeFunction = null;
}
// 关闭WebSocket连接
apiService.closeLocationWebSocket();
console.log('WebSocket位置订阅已取消');
} catch (error) {
console.error('取消订阅实时位置更新失败:', error);
throw error;
}
}
/**
* 发送位置更新到服务器
* @param deliveryPersonId 配送员ID
* @param latitude 纬度
* @param longitude 经度
*/
async sendLocationUpdate(deliveryPersonId: number, latitude: number, longitude: number): Promise<void> {
if (isMockMode) {
console.log('[MOCK] 发送位置更新:', { deliveryPersonId, latitude, longitude });
return;
}
try {
await apiService.sendLocationUpdate(deliveryPersonId, latitude, longitude);
console.log('位置更新发送成功');
} catch (error) {
console.error('发送位置更新失败:', error);
throw error;
}
}
// ===== 私有辅助方法 =====
/**
* 存储位置更新回调函数的集合
*/
private locationUpdateCallbacks: Set<(location: LocationData) => void> | null;
/**
* 模拟位置更新的定时器
*/
private locationUpdateTimer: number | null;
/**
* 取消订阅函数引用
*/
private unsubscribeFunction: (() => void) | null;
/**
* 启动模拟位置更新
*/
private startMockLocationUpdates(): void {
// 每5秒发送一次模拟位置更新
this.locationUpdateTimer = setInterval(() => {
if (this.locationUpdateCallbacks && this.locationUpdateCallbacks.size > 0) {
// 为每个货运人员生成模拟位置更新
this.mockDeliveryPersons.forEach(person => {
// 在当前位置附近随机生成新位置
const baseLongitude = person.currentLocation.longitude;
const baseLatitude = person.currentLocation.latitude;
const newLocation: LocationData = {
userId: person.id,
longitude: baseLongitude + (Math.random() - 0.5) * 0.001, // 小范围随机移动
latitude: baseLatitude + (Math.random() - 0.5) * 0.001, // 小范围随机移动
timestamp: Date.now()
};
// 更新模拟数据中的位置
person.currentLocation = {
longitude: newLocation.longitude,
latitude: newLocation.latitude
};
// 通知所有回调函数
this.locationUpdateCallbacks!.forEach(callback => {
try {
callback(newLocation);
} catch (error) {
console.error('位置更新回调执行失败:', error);
}
});
});
}
}, 5000); // 5秒更新一次
}
/**
* 获取货运人员当前订单
* @param deliveryPersonId 货运人员ID
* @returns 订单列表
*/
async getDeliveryPersonOrders(deliveryPersonId: number): Promise<Array<{
id: number;
startPoint: {
id: number;
name: string;
longitude: number;
latitude: number;
};
endPoint: {
name: string;
longitude: number;
latitude: number;
};
status: string;
goodsType: string;
goodsWeight: number;
createTime: number;
}>> {
if (isMockMode) {
// 模拟数据 - 返回货运人员当前订单
console.log('[MOCK] 获取货运人员当前订单ID:', deliveryPersonId);
const person = this.mockDeliveryPersons.find(p => p.id === deliveryPersonId);
return person ? person.currentOrders : [];
}
return apiService.getDeliveryPersonOrders(deliveryPersonId);
}
}
/**
* 货运人员服务单例实例
* 导出供应用程序全局使用
*/
export default new DeliveryPersonService();