first commit
This commit is contained in:
916
miniprogram/services/apiService.ts
Normal file
916
miniprogram/services/apiService.ts
Normal file
@@ -0,0 +1,916 @@
|
||||
import { WarehouseInfo, UserInfo, DeliveryPerson, Order, EmployeeInfo } from '../types';
|
||||
|
||||
|
||||
/**
|
||||
* API服务基类
|
||||
* 提供与后端API交互的核心功能
|
||||
*/
|
||||
|
||||
// API基础URL配置
|
||||
const IS_LOCAL_DEV = false; // true: 本地开发环境, false: 生产环境
|
||||
const API_BASE_URL = IS_LOCAL_DEV ? 'http://localhost:8080' : 'https://www.doubleyin.cn';
|
||||
|
||||
console.log(`当前API地址: ${API_BASE_URL} (${IS_LOCAL_DEV ? '本地开发环境' : '生产环境'})`);
|
||||
|
||||
/**
|
||||
* 是否启用模拟模式
|
||||
* 该配置控制是否使用模拟数据进行开发测试
|
||||
*/
|
||||
export const isMockMode = false;
|
||||
|
||||
/**
|
||||
* API服务类
|
||||
* 封装了所有与后端API交互的方法,并按照功能模块进行组织
|
||||
*/
|
||||
class ApiService {
|
||||
/**
|
||||
* 位置更新回调函数集合
|
||||
*/
|
||||
private locationUpdateCallbacks: Set<(location: any) => void> | null;
|
||||
|
||||
/**
|
||||
* 位置更新WebSocket连接
|
||||
*/
|
||||
private locationWebSocket: any | null;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
constructor() {
|
||||
this.locationUpdateCallbacks = null;
|
||||
this.locationWebSocket = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础请求方法
|
||||
* @param endpoint API端点路径
|
||||
* @param options 请求配置选项
|
||||
* @returns Promise<T> 返回泛型类型的响应数据
|
||||
*/
|
||||
private async request<T>(endpoint: string, options: {
|
||||
method?: string;
|
||||
data?: any;
|
||||
headers?: Record<string, string>
|
||||
} = {}): Promise<T> {
|
||||
const requestUrl = `${API_BASE_URL}${endpoint}`;
|
||||
|
||||
// 获取全局token
|
||||
const app = getApp<any>();
|
||||
const token = app.globalData.token;
|
||||
|
||||
// 构建请求头,自动添加Authorization头(如果存在token)
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const requestOptions = {
|
||||
method: options.method || 'GET',
|
||||
data: options.data,
|
||||
header: headers,
|
||||
};
|
||||
|
||||
// 打印请求信息
|
||||
console.log('\n========== API Request ==========');
|
||||
console.log(`Method: ${requestOptions.method}`);
|
||||
console.log(`URL: ${requestUrl}`);
|
||||
console.log(`Headers:`, requestOptions.header);
|
||||
console.log(`Data:`, requestOptions.data);
|
||||
console.log('================================');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url: requestUrl,
|
||||
method: requestOptions.method as any,
|
||||
data: requestOptions.data,
|
||||
header: requestOptions.header,
|
||||
success: (res: any) => {
|
||||
// 打印响应信息
|
||||
console.log('\n========== API Response ==========');
|
||||
console.log(`URL: ${requestUrl}`);
|
||||
console.log(`Status: ${res.statusCode}`);
|
||||
console.log(`Response Data:`, res.data);
|
||||
console.log('==================================');
|
||||
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
resolve(res.data);
|
||||
} else {
|
||||
console.error(`API Error: HTTP ${res.statusCode}: ${res.errMsg}`);
|
||||
reject(new Error(`HTTP ${res.statusCode}: ${res.errMsg}`));
|
||||
}
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error('\n========== API Request Failed ==========');
|
||||
console.error(`URL: ${requestUrl}`);
|
||||
console.error(`Error: ${err.errMsg}`);
|
||||
console.error('=======================================');
|
||||
reject(new Error(`Request failed: ${err.errMsg}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 用户模块 ====================
|
||||
|
||||
// ====== 认证相关 ======
|
||||
|
||||
/**
|
||||
* 微信登录接口
|
||||
* @param code 微信登录授权码
|
||||
* @returns 用户信息及认证令牌
|
||||
*/
|
||||
async ServerLogin(code: string) {
|
||||
console.log('API wxLogin调用,参数code:', code);
|
||||
return await this.request<{ user: UserInfo; token: string; openid: string; session_key: string }>('/user/wxlogin', {
|
||||
method: 'POST',
|
||||
data: { code: code },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到接口
|
||||
* @param userId 用户ID
|
||||
* @returns 签到结果和员工信息
|
||||
*/
|
||||
async userSignIn(userId: number): Promise<{ success: boolean; employeeInfo: EmployeeInfo; message?: string }> {
|
||||
console.log('API userSignIn调用,参数userId:', userId);
|
||||
|
||||
// 服务器返回的是用户对象,需要转换为前端期望的格式
|
||||
const response = await this.request<any>('/user/signin', {
|
||||
method: 'POST',
|
||||
data: { userId },
|
||||
});
|
||||
|
||||
// 转换响应格式
|
||||
return {
|
||||
success: true,
|
||||
employeeInfo: {
|
||||
id: response.id,
|
||||
name: response.name,
|
||||
phone: response.phone,
|
||||
role: response.role || 'DELIVERY_PERSON'
|
||||
},
|
||||
message: '签到成功'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册接口
|
||||
* @param userInfo 注册用户信息
|
||||
* @returns 注册结果和员工信息
|
||||
*/
|
||||
async userRegister(userInfo: { name: string; phone: string }): Promise<{ success: boolean; employeeInfo: EmployeeInfo; message?: string }> {
|
||||
console.log('API userRegister调用,参数userInfo:', userInfo);
|
||||
|
||||
// 服务器返回的是用户对象,需要转换为前端期望的格式
|
||||
const response = await this.request<any>('/user/register', {
|
||||
method: 'POST',
|
||||
data: userInfo,
|
||||
});
|
||||
|
||||
// 转换响应格式
|
||||
return {
|
||||
success: true,
|
||||
employeeInfo: {
|
||||
id: response.id,
|
||||
name: response.name || userInfo.name, // 如果服务器返回null,使用用户输入的值
|
||||
phone: response.phone || userInfo.phone, // 如果服务器返回null,使用用户输入的值
|
||||
role: response.role || 'DELIVERY_PERSON'
|
||||
},
|
||||
message: '注册成功'
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
*/
|
||||
async logout(): Promise<void> {
|
||||
return await this.request('/user/logout', { method: 'POST' });
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户签到状态
|
||||
* @returns 用户状态信息
|
||||
*/
|
||||
async getUserStatus(): Promise<{ status: 'signed_in' | 'signed_out' | 'registered' | 'unregistered'; lastSignInTime?: string; lastSignOutTime?: string }> {
|
||||
return await this.request('/user/status', { method: 'GET' });
|
||||
}
|
||||
|
||||
// ====== 信息相关 ======
|
||||
|
||||
/**
|
||||
* 获取当前用户信息
|
||||
* @returns 用户详细信息
|
||||
*/
|
||||
async getUserInfo() {
|
||||
return await this.request<UserInfo>('/user/info');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
* @param userInfo 待更新的用户信息
|
||||
* @returns 更新后的用户信息
|
||||
*/
|
||||
async updateUserInfo(userInfo: Partial<UserInfo>): Promise<UserInfo> {
|
||||
return await this.request<UserInfo>('/user/update', {
|
||||
method: 'PUT',
|
||||
data: userInfo,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户权限列表
|
||||
* @returns 权限字符串数组
|
||||
*/
|
||||
async getUserPermissions(): Promise<string[]> {
|
||||
return await this.request<string[]>('/user/permissions');
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否在线
|
||||
* @returns 在线状态
|
||||
*/
|
||||
async checkUserOnline(): Promise<boolean> {
|
||||
return await this.request<boolean>('/user/online');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户会话信息
|
||||
* @returns 会话详细信息
|
||||
*/
|
||||
async getSessionInfo(): Promise<{
|
||||
userId: number;
|
||||
sessionId: string;
|
||||
expiresAt: number;
|
||||
permissions: string[];
|
||||
}> {
|
||||
return await this.request<{
|
||||
userId: number;
|
||||
sessionId: string;
|
||||
expiresAt: number;
|
||||
permissions: string[];
|
||||
}>('/user/session');
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新用户令牌
|
||||
* @param oldToken 旧令牌
|
||||
* @returns 新令牌及过期时间
|
||||
*/
|
||||
async refreshToken(oldToken: string): Promise<{ token: string; expiresAt: number }> {
|
||||
return await this.request<{ token: string; expiresAt: number }>('/user/refresh-token', {
|
||||
method: 'POST',
|
||||
data: { token: oldToken },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户权限
|
||||
* @param permission 待验证的权限
|
||||
* @returns 是否拥有该权限
|
||||
*/
|
||||
async verifyPermission(permission: string): Promise<boolean> {
|
||||
return await this.request<boolean>(`/user/verify-permission?permission=${permission}`);
|
||||
}
|
||||
|
||||
// ====== 管理相关 ======
|
||||
|
||||
/**
|
||||
* 搜索用户
|
||||
* @param query 搜索关键词
|
||||
* @param page 页码
|
||||
* @param pageSize 每页数量
|
||||
* @returns 用户列表及分页信息
|
||||
*/
|
||||
async searchUsers(query: string, page: number = 1, pageSize: number = 20): Promise<{
|
||||
users: UserInfo[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}> {
|
||||
return await this.request<{ users: UserInfo[]; total: number; page: number; pageSize: number }>(
|
||||
`/user/search?query=${query}&page=${page}&pageSize=${pageSize}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作用户状态
|
||||
* @param userIds 用户ID列表
|
||||
* @param status 目标状态
|
||||
*/
|
||||
async batchUpdateUserStatus(userIds: number[], status: 'active' | 'inactive' | 'suspended'): Promise<void> {
|
||||
return await this.request('/user/batch-update-status', {
|
||||
method: 'POST',
|
||||
data: { userIds, status },
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 仓库相关接口 ====================
|
||||
|
||||
/**
|
||||
* 获取所有仓库列表
|
||||
* @returns 仓库信息数组
|
||||
*/
|
||||
async getWarehouses(): Promise<WarehouseInfo[]> {
|
||||
return await this.request<WarehouseInfo[]>('/warehouses');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定仓库详情
|
||||
* @param id 仓库ID
|
||||
* @returns 仓库详细信息
|
||||
*/
|
||||
async getWarehouseById(id: number): Promise<WarehouseInfo> {
|
||||
return await this.request<WarehouseInfo>(`/warehouses/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库相关订单
|
||||
* @param warehouseId 仓库ID
|
||||
* @returns 订单列表
|
||||
*/
|
||||
async getWarehouseOrders(warehouseId: number): Promise<Order[]> {
|
||||
return await this.request<Order[]>(`/warehouses/${warehouseId}/orders`);
|
||||
}
|
||||
|
||||
// ==================== 货运人员接口 ====================
|
||||
|
||||
/**
|
||||
* 获取所有货运人员
|
||||
* @returns 货运人员列表
|
||||
*/
|
||||
async getDeliveryPersons(): Promise<DeliveryPerson[]> {
|
||||
return await this.request<DeliveryPerson[]>('/delivery-persons');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有配送员实时位置
|
||||
* @returns 所有配送员实时位置信息
|
||||
*/
|
||||
async getAllDeliveryPersonLocations(): Promise<Array<{
|
||||
deliveryPersonId: number;
|
||||
name: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
status: string;
|
||||
}>> {
|
||||
return await this.request<Array<{
|
||||
deliveryPersonId: number;
|
||||
name: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
status: string;
|
||||
}>>('/location-sync/delivery-persons/locations');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定货运人员详情
|
||||
* @param id 货运人员ID
|
||||
* @returns 货运人员详细信息
|
||||
*/
|
||||
async getDeliveryPersonById(id: number): Promise<DeliveryPerson> {
|
||||
return await this.request<DeliveryPerson>(`/delivery-persons/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新货运人员位置
|
||||
* @param id 货运人员ID
|
||||
* @param location 位置信息
|
||||
*/
|
||||
async updateDeliveryPersonLocation(id: number, location: { longitude: number; latitude: number }): Promise<void> {
|
||||
return await this.request(`/delivery-persons/${id}/location`, {
|
||||
method: 'PUT',
|
||||
data: location,
|
||||
});
|
||||
}
|
||||
|
||||
// 地图相关接口支持
|
||||
/**
|
||||
* 批量更新货运人员位置(兼容mapService参数)
|
||||
* @param locations 位置信息数组
|
||||
*/
|
||||
async batchUpdateDeliveryPersonLocations(locations: Array<{
|
||||
userId: number;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
timestamp: number;
|
||||
}>): Promise<void> {
|
||||
// 转换参数格式以匹配原有API
|
||||
const formattedLocations = locations.map(loc => ({
|
||||
deliveryPersonId: loc.userId,
|
||||
longitude: loc.longitude,
|
||||
latitude: loc.latitude,
|
||||
timestamp: loc.timestamp
|
||||
}));
|
||||
|
||||
await this.request('/delivery-persons/locations/batch', {
|
||||
method: 'POST',
|
||||
data: { locations: formattedLocations }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取空闲的货运人员
|
||||
* @returns 空闲货运人员列表
|
||||
*/
|
||||
async getIdleDeliveryPersons(): Promise<DeliveryPerson[]> {
|
||||
return await this.request<DeliveryPerson[]>('/delivery-persons/idle');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取忙碌的货运人员
|
||||
* @returns 忙碌货运人员列表
|
||||
*/
|
||||
async getBusyDeliveryPersons(): Promise<DeliveryPerson[]> {
|
||||
return await this.request<DeliveryPerson[]>('/delivery-persons/busy');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取位置历史记录
|
||||
* @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;
|
||||
}>> {
|
||||
return await this.request<Array<{
|
||||
timestamp: number;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
speed?: number;
|
||||
accuracy?: number;
|
||||
}>>(`/delivery-persons/${deliveryPersonId}/location-history?limit=${limit}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅实时位置更新(接收货运人员ID列表)
|
||||
* @param deliveryPersonIds 货运人员ID列表
|
||||
* @returns 订阅信息
|
||||
*/
|
||||
async subscribeToRealTimeLocations(deliveryPersonIds: number[]): Promise<{
|
||||
subscriptionId: string;
|
||||
expiresAt: number;
|
||||
}> {
|
||||
if (isMockMode) {
|
||||
// 模拟数据 - 返回模拟的订阅信息
|
||||
console.log('[MOCK] 订阅实时位置更新,货运人员ID列表:', deliveryPersonIds);
|
||||
return {
|
||||
subscriptionId: `mock-subscription-${Date.now()}`,
|
||||
expiresAt: Date.now() + 3600000 // 1小时后过期
|
||||
};
|
||||
}
|
||||
|
||||
// 真实环境中调用API
|
||||
try {
|
||||
return await this.request<{
|
||||
subscriptionId: string;
|
||||
expiresAt: number;
|
||||
}>('/locations/subscribe', {
|
||||
method: 'POST',
|
||||
data: { deliveryPersonIds }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('订阅实时位置更新失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订阅实时位置更新
|
||||
* @param subscriptionId 订阅ID
|
||||
*/
|
||||
async unsubscribeFromRealTimeLocations(subscriptionId: string): Promise<void> {
|
||||
if (isMockMode) {
|
||||
// 模拟数据 - 记录取消订阅操作
|
||||
console.log('[MOCK] 取消订阅实时位置更新,订阅ID:', subscriptionId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 真实环境中调用API
|
||||
try {
|
||||
await this.request<void>('/locations/unsubscribe', {
|
||||
method: 'POST',
|
||||
data: { subscriptionId }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('取消订阅实时位置更新失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册位置更新回调函数
|
||||
* @param callback 位置更新回调函数
|
||||
* @returns 取消订阅函数
|
||||
*/
|
||||
onLocationUpdate(callback: (location: any) => void): () => void {
|
||||
// 添加回调到集合
|
||||
if (!this.locationUpdateCallbacks) {
|
||||
this.locationUpdateCallbacks = new Set();
|
||||
}
|
||||
this.locationUpdateCallbacks.add(callback);
|
||||
|
||||
// 返回取消订阅函数
|
||||
return () => {
|
||||
if (this.locationUpdateCallbacks) {
|
||||
this.locationUpdateCallbacks.delete(callback);
|
||||
// 如果没有回调了,可以关闭WebSocket连接
|
||||
if (this.locationUpdateCallbacks.size === 0 && this.locationWebSocket) {
|
||||
this.locationWebSocket.close();
|
||||
this.locationWebSocket = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ===== 私有属性和方法 =====
|
||||
|
||||
/**
|
||||
* 初始化位置更新WebSocket连接
|
||||
*/
|
||||
public async initLocationWebSocket(): Promise<void> {
|
||||
if (this.locationWebSocket) {
|
||||
console.log('WebSocket连接已存在');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof wx !== 'undefined' && typeof wx.connectSocket === 'function') {
|
||||
console.log('初始化位置更新WebSocket连接(小程序环境)');
|
||||
|
||||
// 连接到服务端的WebSocket地址,使用配置的服务器地址
|
||||
const serverUrl = API_BASE_URL.replace('http', 'ws');
|
||||
const wsUrl = `${serverUrl}/ws/location`;
|
||||
|
||||
this.locationWebSocket = wx.connectSocket({
|
||||
url: wsUrl,
|
||||
header: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
// WebSocket连接打开事件
|
||||
wx.onSocketOpen(() => {
|
||||
console.log('WebSocket连接已打开');
|
||||
});
|
||||
|
||||
// WebSocket消息接收事件
|
||||
wx.onSocketMessage((res) => {
|
||||
try {
|
||||
const message = JSON.parse(typeof res.data === 'string' ? res.data : String(res.data));
|
||||
this.handleWebSocketMessage(message);
|
||||
} catch (error) {
|
||||
console.error('解析WebSocket消息失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// WebSocket连接关闭事件
|
||||
wx.onSocketClose(() => {
|
||||
console.log('WebSocket连接已关闭');
|
||||
this.locationWebSocket = null;
|
||||
});
|
||||
|
||||
// WebSocket错误事件
|
||||
wx.onSocketError((error) => {
|
||||
console.error('WebSocket连接错误:', error);
|
||||
this.locationWebSocket = null;
|
||||
});
|
||||
} else {
|
||||
console.warn('当前环境不支持WebSocket连接');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化位置更新WebSocket连接失败:', error);
|
||||
this.locationWebSocket = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭位置更新WebSocket连接
|
||||
*/
|
||||
public async closeLocationWebSocket(): Promise<void> {
|
||||
if (this.locationWebSocket && typeof wx !== 'undefined' && typeof wx.closeSocket === 'function') {
|
||||
wx.closeSocket();
|
||||
this.locationWebSocket = null;
|
||||
console.log('WebSocket连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理WebSocket消息
|
||||
* @param message 接收到的消息
|
||||
*/
|
||||
private handleWebSocketMessage(message: any): void {
|
||||
if (!message || typeof message.type !== 'string') {
|
||||
console.warn('收到无效的WebSocket消息:', message);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.type) {
|
||||
case 'updateLocation':
|
||||
// 处理位置更新消息
|
||||
this.onLocationUpdate(message);
|
||||
break;
|
||||
default:
|
||||
console.warn('收到未知类型的WebSocket消息:', message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送WebSocket消息
|
||||
* @param message 要发送的消息
|
||||
*/
|
||||
private sendWebSocketMessage(message: any): void {
|
||||
if (!this.locationWebSocket) {
|
||||
console.warn('WebSocket连接未建立,无法发送消息');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const messageStr = JSON.stringify(message);
|
||||
if (typeof wx !== 'undefined' && typeof wx.sendSocketMessage === 'function') {
|
||||
wx.sendSocketMessage({
|
||||
data: messageStr
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发送WebSocket消息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅位置更新
|
||||
* @param deliveryPersonId 配送员ID
|
||||
*/
|
||||
async subscribeToLocationUpdates(deliveryPersonId: number): Promise<void> {
|
||||
if (isMockMode) {
|
||||
console.log('[MOCK] 订阅位置更新');
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保WebSocket连接已建立
|
||||
if (!this.locationWebSocket) {
|
||||
this.initLocationWebSocket();
|
||||
}
|
||||
|
||||
// 发送订阅消息
|
||||
const subscribeMessage = {
|
||||
type: 'subscribe',
|
||||
deliveryPersonId: deliveryPersonId,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
this.sendWebSocketMessage(subscribeMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订阅位置更新
|
||||
* @param deliveryPersonId 配送员ID
|
||||
*/
|
||||
async unsubscribeFromLocationUpdates(deliveryPersonId: number): Promise<void> {
|
||||
if (isMockMode) {
|
||||
console.log('[MOCK] 取消订阅位置更新');
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送取消订阅消息
|
||||
const unsubscribeMessage = {
|
||||
type: 'unsubscribe',
|
||||
deliveryPersonId: deliveryPersonId,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
this.sendWebSocketMessage(unsubscribeMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送位置更新
|
||||
* @param deliveryPersonId 配送员ID
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
*/
|
||||
async sendLocationUpdate(deliveryPersonId: number, latitude: number, longitude: number): Promise<void> {
|
||||
if (isMockMode) {
|
||||
console.log('[MOCK] 发送位置更新');
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保WebSocket连接已建立
|
||||
if (!this.locationWebSocket) {
|
||||
this.initLocationWebSocket();
|
||||
}
|
||||
|
||||
// 发送位置更新消息
|
||||
const locationMessage = {
|
||||
type: 'updateLocation',
|
||||
deliveryPersonId: deliveryPersonId,
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
this.sendWebSocketMessage(locationMessage);
|
||||
}
|
||||
|
||||
// ==================== 订单接口 ====================
|
||||
|
||||
/**
|
||||
* 获取待指派订单
|
||||
* @returns 待指派订单列表
|
||||
*/
|
||||
async getPendingOrders(): Promise<Order[]> {
|
||||
return await this.request<Order[]>('/orders/pending');
|
||||
}
|
||||
|
||||
/**
|
||||
* 指派订单给货运人员
|
||||
* @param orderId 订单ID
|
||||
* @param deliveryPersonId 货运人员ID
|
||||
*/
|
||||
async assignOrder(orderId: number, deliveryPersonId: number): Promise<{ success: boolean; message?: string }> {
|
||||
return await this.request<{ success: boolean; message?: string }>(`/orders/${orderId}/assign`, {
|
||||
method: 'POST',
|
||||
data: { deliveryPersonId },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员当前订单
|
||||
* @param deliveryPersonId 货运人员ID
|
||||
* @returns 订单列表
|
||||
*/
|
||||
async getDeliveryPersonOrders(deliveryPersonId: number): Promise<Order[]> {
|
||||
return await this.request<Order[]>(`/delivery-persons/${deliveryPersonId}/orders`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取订单
|
||||
* @param id 订单ID
|
||||
* @returns 订单详细信息
|
||||
*/
|
||||
async getOrderById(id: number): Promise<Order> {
|
||||
return await this.request<Order>(`/orders/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
* @param orderId 订单ID
|
||||
* @param status 目标状态
|
||||
*/
|
||||
async updateOrderStatus(orderId: number, status: Order['status']): Promise<{ success: boolean; message?: string }> {
|
||||
return await this.request<{ success: boolean; message?: string }>(`/orders/${orderId}/status`, {
|
||||
method: 'PUT',
|
||||
data: { status },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新订单
|
||||
* @param orderData 订单数据
|
||||
* @returns 创建的订单信息
|
||||
*/
|
||||
async createOrder(orderData: Omit<Order, 'id' | 'createTime'>): Promise<Order> {
|
||||
return await this.request<Order>('/orders', {
|
||||
method: 'POST',
|
||||
data: orderData,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
* @param orderId 订单ID
|
||||
*/
|
||||
async deleteOrder(orderId: number): Promise<void> {
|
||||
return await this.request(`/orders/${orderId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 统计和日志接口 ====================
|
||||
|
||||
/**
|
||||
* 获取系统统计信息
|
||||
* @returns 系统统计数据
|
||||
*/
|
||||
async getSystemStats(): Promise<{
|
||||
totalWarehouses: number;
|
||||
totalDeliveryPersons: number;
|
||||
pendingOrders: number;
|
||||
activeOrders: number;
|
||||
}> {
|
||||
return await this.request<{
|
||||
totalWarehouses: number;
|
||||
totalDeliveryPersons: number;
|
||||
pendingOrders: number;
|
||||
activeOrders: number;
|
||||
}>('/stats/system');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单统计信息
|
||||
* @param timeRange 时间范围
|
||||
* @returns 订单统计数据
|
||||
*/
|
||||
async getOrderStats(timeRange: 'today' | 'week' | 'month'): Promise<{
|
||||
totalOrders: number;
|
||||
completedOrders: number;
|
||||
inProgressOrders: number;
|
||||
averageDeliveryTime: number;
|
||||
}> {
|
||||
return await this.request<{
|
||||
totalOrders: number;
|
||||
completedOrders: number;
|
||||
inProgressOrders: number;
|
||||
averageDeliveryTime: number;
|
||||
}>(`/stats/orders?timeRange=${timeRange}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户统计信息
|
||||
* @returns 用户统计数据
|
||||
*/
|
||||
async getUserStats(): Promise<{
|
||||
totalUsers: number;
|
||||
activeUsers: number;
|
||||
onlineUsers: number;
|
||||
newUsersToday: number;
|
||||
}> {
|
||||
return await this.request<{
|
||||
totalUsers: number;
|
||||
activeUsers: number;
|
||||
onlineUsers: number;
|
||||
newUsersToday: number;
|
||||
}>('/user/stats');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户活动日志
|
||||
* @param userId 用户ID
|
||||
* @param limit 日志数量
|
||||
* @returns 活动日志列表
|
||||
*/
|
||||
async getUserActivityLogs(userId: number, limit: number = 20): Promise<Array<{
|
||||
id: number;
|
||||
action: string;
|
||||
timestamp: number;
|
||||
details?: any;
|
||||
}>> {
|
||||
return await this.request<Array<{ id: number; action: string; timestamp: number; details?: any }>>(
|
||||
`/user/${userId}/activity-logs?limit=${limit}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传错误日志
|
||||
* @param error 错误信息
|
||||
*/
|
||||
async uploadErrorLog(error: any): Promise<void> {
|
||||
await this.request('/logs/error', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: Date.now(),
|
||||
userAgent: 'miniprogram/' + (typeof wx !== 'undefined' ? wx.getSystemInfoSync().platform : 'unknown')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 系统接口 ====================
|
||||
|
||||
/**
|
||||
* 健康检查
|
||||
* @returns 系统健康状态
|
||||
*/
|
||||
async healthCheck(): Promise<{
|
||||
status: 'ok' | 'degraded' | 'down';
|
||||
message: string;
|
||||
timestamp: number;
|
||||
}> {
|
||||
return await this.request<{
|
||||
status: 'ok' | 'degraded' | 'down';
|
||||
message: string;
|
||||
timestamp: number;
|
||||
}>('/health');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API服务单例实例
|
||||
* 导出供应用程序全局使用
|
||||
*/
|
||||
export default new ApiService();
|
||||
|
Reference in New Issue
Block a user