first commit
This commit is contained in:
433
miniprogram/services/deliveryPersonService.ts
Normal file
433
miniprogram/services/deliveryPersonService.ts
Normal file
@@ -0,0 +1,433 @@
|
||||
// 货运人员服务 - 处理货运人员相关的数据操作
|
||||
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();
|
Reference in New Issue
Block a user