first commit

This commit is contained in:
2025-10-16 21:32:16 +08:00
commit c446df73b5
229 changed files with 499497 additions and 0 deletions

View 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();