地址路径修改

This commit is contained in:
2025-10-26 13:15:04 +08:00
parent be2323074b
commit 271b88232c
77 changed files with 13254 additions and 228 deletions

883
dist/services/apiService.js vendored Normal file
View File

@@ -0,0 +1,883 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const roleUtils_1 = require("../utils/roleUtils");
const locationTrackingService_1 = __importDefault(require("./locationTrackingService"));
/**
* API服务基类
* 提供与后端API交互的核心功能
*/
// API基础URL配置
const IS_LOCAL_DEV = true; // 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 ? '本地开发环境' : '生产环境'})`);
/**
* 是否启用模拟模式
* 该配置控制是否使用模拟数据进行开发测试
*/
/**
* API服务类
* 封装了所有与后端API交互的方法并按照功能模块进行组织
*/
class ApiService {
/**
* 构造函数
*/
constructor() {
this.locationWebSocket = null;
}
/**
* 基础请求方法
* @param endpoint API端点路径
* @param options 请求配置选项
* @returns Promise<T> 返回泛型类型的响应数据
*/
async request(endpoint, options = {}) {
const requestUrl = `${API_BASE_URL}${endpoint}`;
// 获取全局token
const app = getApp();
const token = app.globalData.token;
// 构建请求头自动添加Authorization头如果存在token
const headers = {
'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,
data: requestOptions.data,
header: requestOptions.header,
success: (res) => {
// 打印响应信息
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 {
// 优先使用服务器返回的具体错误信息,如果没有则使用默认错误信息
const errorMessage = res.data || res.errMsg || '请求失败';
console.error(`API Error: HTTP ${res.statusCode}: ${errorMessage}`);
reject(new Error(`HTTP ${res.statusCode}: ${errorMessage}`));
}
},
fail: (err) => {
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) {
console.log('API wxLogin调用参数code:', code);
return await this.request('/user/wxlogin', {
method: 'POST',
data: { code: code },
});
}
/**
* 签到接口
* @param userId 用户ID
* @param initialLocation 初始位置数据(必须)
* @returns 签到结果和员工信息
*/
async userSignIn(userId, initialLocation) {
console.log('API userSignIn调用参数userId:', userId, 'initialLocation:', initialLocation);
// 构建请求数据,必须包含位置数据
const requestData = {
latitude: initialLocation.latitude,
longitude: initialLocation.longitude,
timestamp: initialLocation.timestamp
};
// 服务器现在返回统一的DTO格式直接使用
const response = await this.request('/user/signin', {
method: 'POST',
data: requestData,
});
// 服务器返回格式:{ success: boolean, userInfo: UserInfoResponse }
return {
success: response.success,
employeeInfo: {
id: response.userInfo.id,
name: response.userInfo.name,
phone: response.userInfo.phone,
role: response.userInfo.role || roleUtils_1.Role.DELIVERY_PERSON
},
message: response.message
};
}
/**
* 绑定接口
* @param userInfo 绑定用户信息
* @returns 绑定结果和员工信息
*/
async userRegister(userInfo) {
console.log('API userRegister调用参数userInfo:', userInfo);
// 服务器返回直接的用户信息格式:{id, name, phone, role, openid}
const response = await this.request('/user/register', {
method: 'POST',
data: userInfo,
});
// 检查响应格式,兼容不同的返回格式
if (response.id) {
// 直接返回用户信息格式
return {
success: true,
employeeInfo: {
id: response.id,
name: response.name || userInfo.name,
phone: response.phone || userInfo.phone,
role: response.role || roleUtils_1.Role.DELIVERY_PERSON
},
message: '绑定成功'
};
}
else if (response.userInfo && response.userInfo.id) {
// 包装格式:{success, userInfo, message}
return {
success: response.success !== false,
employeeInfo: {
id: response.userInfo.id,
name: response.userInfo.name || userInfo.name,
phone: response.userInfo.phone || userInfo.phone,
role: response.userInfo.role || roleUtils_1.Role.DELIVERY_PERSON
},
message: response.message
};
}
else {
// 未知格式,返回错误
console.error('未知的绑定响应格式:', response);
return {
success: false,
employeeInfo: {
id: 0,
name: userInfo.name,
phone: userInfo.phone,
role: roleUtils_1.Role.DELIVERY_PERSON
},
message: '绑定响应格式错误'
};
}
}
/**
* 用户登出
*/
async logout() {
return await this.request('/user/logout', { method: 'POST' });
}
/**
* 解绑微信接口
* 清除当前用户的openid绑定允许重新注册其他账号
* @returns 解绑结果
*/
async unbindWechat() {
console.log('API unbindWechat调用');
const response = await this.request('/user/unbind', {
method: 'POST',
data: {}
});
return {
success: response.success,
message: response.message
};
}
/**
* 签退接口
* @param userId 用户ID
* @returns 签退结果
*/
async userSignOut(userId) {
console.log('API userSignOut调用参数userId:', userId);
// 服务器现在返回统一的DTO格式{ success: boolean, message: string }
const response = await this.request('/user/signout', {
method: 'POST',
data: { userId },
});
return {
success: response.success,
message: response.message
};
}
/**
* 获取用户签到状态
* @returns 用户状态信息
*/
async getUserStatus() {
return await this.request('/user/status', { method: 'GET' });
}
// ====== 信息相关 ======
/**
* 获取当前用户信息
* @returns 用户详细信息
*/
async getUserInfo() {
return await this.request('/user/info');
}
/**
* 更新用户信息
* @param userInfo 待更新的用户信息
* @returns 更新后的用户信息
*/
async updateUserInfo(userInfo) {
return await this.request('/user/update', {
method: 'PUT',
data: userInfo,
});
}
/**
* 获取用户权限列表
* @returns 权限字符串数组
*/
async getUserPermissions() {
return await this.request('/user/permissions');
}
/**
* 检查用户是否在线
* @returns 在线状态
*/
async checkUserOnline() {
return await this.request('/user/online');
}
/**
* 获取用户会话信息
* @returns 会话详细信息
*/
async getSessionInfo() {
return await this.request('/user/session');
}
/**
* 刷新用户令牌
* @param oldToken 旧令牌
* @returns 新令牌及过期时间
*/
async refreshToken(oldToken) {
return await this.request('/user/refresh-token', {
method: 'POST',
data: { token: oldToken },
});
}
/**
* 验证用户权限
* @param permission 待验证的权限
* @returns 是否拥有该权限
*/
async verifyPermission(permission) {
return await this.request(`/user/verify-permission?permission=${permission}`);
}
// ====== 管理相关 ======
/**
* 搜索用户
* @param query 搜索关键词
* @param page 页码
* @param pageSize 每页数量
* @returns 用户列表及分页信息
*/
async searchUsers(query, page = 1, pageSize = 20) {
return await this.request(`/user/search?query=${query}&page=${page}&pageSize=${pageSize}`);
}
/**
* 批量操作用户状态
* @param userIds 用户ID列表
* @param status 目标状态
*/
async batchUpdateUserStatus(userIds, status) {
return await this.request('/user/batch-update-status', {
method: 'POST',
data: { userIds, status },
});
}
// ====== 员工管理接口 ======
/**
* 获取所有员工列表
* @returns 员工信息数组
*/
async getEmployees() {
return await this.request('/employees');
}
/**
* 添加新员工
* @param employeeInfo 员工信息
* @returns 添加结果
*/
async addEmployee(employeeInfo) {
return await this.request('/employees', {
method: 'POST',
data: employeeInfo,
});
}
/**
* 删除员工
* @param employeeId 员工ID
* @returns 删除结果
*/
async deleteEmployee(employeeId) {
return await this.request(`/employees/${employeeId}`, {
method: 'DELETE',
});
}
/**
* 更新员工信息
* @param employeeId 员工ID
* @param employeeInfo 员工信息
* @returns 更新结果
*/
async updateEmployee(employeeId, employeeInfo) {
return await this.request(`/employees/${employeeId}`, {
method: 'PUT',
data: employeeInfo,
});
}
/**
* 上传员工头像
* @param employeeId 员工ID
* @param filePath 头像文件路径
* @returns 上传结果
*/
async uploadEmployeeAvatar(employeeId, filePath) {
return new Promise((resolve, reject) => {
// 使用微信小程序的文件上传API
wx.uploadFile({
url: `${API_BASE_URL}/employees/${employeeId}/avatar`,
filePath: filePath,
name: 'avatar',
header: {
'Authorization': `Bearer ${getApp().globalData.token}`
},
success: (res) => {
if (res.statusCode >= 200 && res.statusCode < 300) {
try {
const data = JSON.parse(res.data);
resolve({
success: true,
avatarUrl: data.avatarUrl
});
}
catch (error) {
resolve({
success: true,
avatarUrl: `${API_BASE_URL}/avatars/${employeeId}.jpg`
});
}
}
else {
reject(new Error(`上传失败: HTTP ${res.statusCode}`));
}
},
fail: (err) => {
reject(new Error(`上传失败: ${err.errMsg}`));
}
});
});
}
/**
* 获取员工头像
* @param employeeId 员工ID
* @returns 头像URL
*/
async getEmployeeAvatar(employeeId) {
try {
// 尝试获取头像信息
const response = await this.request(`/employees/${employeeId}/avatar`);
return response.avatarUrl || `${API_BASE_URL}/avatars/${employeeId}.jpg`;
}
catch (error) {
// 如果获取失败返回默认头像URL
return `${API_BASE_URL}/avatars/${employeeId}.jpg`;
}
}
// ==================== 仓库相关接口 ====================
/**
* 获取所有仓库列表
* @returns 仓库信息数组
*/
async getWarehouses() {
return await this.request('/warehouses');
}
/**
* 获取指定仓库详情
* @param id 仓库ID
* @returns 仓库详细信息
*/
async getWarehouseById(id) {
return await this.request(`/warehouses/${id}`);
}
/**
* 获取仓库相关订单
* @param warehouseId 仓库ID
* @returns 订单列表
*/
async getWarehouseOrders(warehouseId) {
return await this.request(`/warehouses/${warehouseId}/orders`);
}
/**
* 创建仓库
* @param warehouseData 仓库数据
* @returns 创建结果
*/
async createWarehouse(warehouseData) {
return await this.request('/warehouses', {
method: 'POST',
data: warehouseData
});
}
/**
* 更新仓库信息
* @param warehouseId 仓库ID
* @param warehouseInfo 仓库信息
* @returns 更新结果
*/
async updateWarehouse(warehouseId, warehouseInfo) {
return await this.request(`/warehouses/${warehouseId}`, {
method: 'PUT',
data: warehouseInfo
});
}
/**
* 删除仓库
* @param warehouseId 仓库ID
* @returns 删除结果
*/
async deleteWarehouse(warehouseId) {
return await this.request(`/warehouses/${warehouseId}`, {
method: 'DELETE',
});
}
// ==================== 货运人员接口 ====================
/**
* 获取所有货运人员
* @returns 货运人员列表
*/
async getDeliveryPersons() {
return await this.request('/delivery-persons');
}
/**
* 获取所有配送员实时位置
* @returns 所有配送员实时位置信息
*/
async getAllDeliveryPersonLocations() {
return await this.request('/location-sync/delivery-persons/locations');
}
/**
* 获取指定货运人员详情
* @param id 货运人员ID
* @returns 货运人员详细信息
*/
async getDeliveryPersonById(id) {
return await this.request(`/delivery-persons/${id}`);
}
/**
* 更新货运人员位置
* @param id 货运人员ID
* @param location 位置信息
*/
async updateDeliveryPersonLocation(id, location) {
return await this.request(`/delivery-persons/${id}/location`, {
method: 'PUT',
data: location,
});
}
// 地图相关接口支持
/**
* 批量更新货运人员位置兼容mapService参数
* @param locations 位置信息数组
*/
async batchUpdateDeliveryPersonLocations(locations) {
// 转换参数格式以匹配原有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() {
return await this.request('/delivery-persons/idle');
}
/**
* 获取忙碌的货运人员
* @returns 忙碌货运人员列表
*/
async getBusyDeliveryPersons() {
return await this.request('/delivery-persons/busy');
}
/**
* 获取位置历史记录
* @param deliveryPersonId 货运人员ID
* @param limit 记录数量
* @returns 位置历史记录
*/
async getLocationHistory(deliveryPersonId, limit = 50) {
return await this.request(`/delivery-persons/${deliveryPersonId}/location-history?limit=${limit}`);
}
/**
* 订阅实时位置更新接收货运人员ID列表
* @param deliveryPersonIds 货运人员ID列表
* @returns 订阅信息
*/
async subscribeToRealTimeLocations(deliveryPersonIds) {
// 真实环境中调用API
try {
return await this.request('/locations/subscribe', {
method: 'POST',
data: { deliveryPersonIds }
});
}
catch (error) {
console.error('订阅实时位置更新失败:', error);
throw error;
}
}
/**
* 取消订阅实时位置更新
* @param subscriptionId 订阅ID
*/
async unsubscribeFromRealTimeLocations(subscriptionId) {
// 真实环境中调用API
try {
await this.request('/locations/unsubscribe', {
method: 'POST',
data: { subscriptionId }
});
}
catch (error) {
console.error('取消订阅实时位置更新失败:', error);
throw error;
}
}
// ===== 私有属性和方法 =====
/**
* 初始化位置更新WebSocket连接
*/
async initLocationWebSocket() {
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`;
// 获取当前用户ID从全局应用数据中获取
const app = getApp();
const userInfo = app.globalData.userInfo;
const userId = userInfo?.id;
// 构建带用户ID参数的WebSocket URL
const finalWsUrl = userId ? `${wsUrl}?userId=${userId}` : wsUrl;
console.log(`WebSocket连接URL: ${finalWsUrl}`);
this.locationWebSocket = wx.connectSocket({
url: finalWsUrl,
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((res) => {
console.log('WebSocket连接已关闭', res);
this.locationWebSocket = null;
// 如果是非主动关闭,尝试重连
if (res.code !== 1000) { // 1000表示正常关闭
console.log('WebSocket连接异常关闭将在3秒后尝试重连');
setTimeout(() => {
if (!this.locationWebSocket) {
this.initLocationWebSocket().catch(err => {
console.error('WebSocket重连失败:', err);
});
}
}, 3000);
}
});
// 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连接是否已建立
*/
isWebSocketConnected() {
return this.locationWebSocket !== null && this.locationWebSocket !== undefined;
}
/**
* 关闭位置更新WebSocket连接
*/
async closeLocationWebSocket() {
if (this.locationWebSocket && typeof wx !== 'undefined' && typeof wx.closeSocket === 'function') {
try {
// 先检查WebSocket状态避免在连接过程中关闭
wx.closeSocket();
this.locationWebSocket = null;
console.log('WebSocket连接已关闭');
}
catch (error) {
console.warn('关闭WebSocket连接时出现异常:', error);
// 即使关闭失败,也重置连接状态
this.locationWebSocket = null;
}
}
}
/**
* 处理WebSocket消息
* @param message 接收到的消息
*/
handleWebSocketMessage(message) {
if (!message || typeof message.type !== 'string') {
console.warn('收到无效的WebSocket消息:', message);
return;
}
locationTrackingService_1.default.handleWebSocketMessage(message);
}
/**
* 发送WebSocket消息
* @param message 要发送的消息对象
*/
sendWebSocketMessage(message) {
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 userId 用户ID
*/
async subscribeToLocationUpdates() {
// 确保WebSocket连接已建立
if (!this.locationWebSocket) {
this.initLocationWebSocket();
}
// 服务器会自动处理订阅逻辑,无需发送订阅消息
console.log('位置订阅已初始化,服务器将自动处理订阅逻辑');
}
/**
* 取消订阅位置更新(服务器自动处理,无需发送消息)
* @param userId 用户ID
*/
async unsubscribeFromLocationUpdates(_userId) {
// 服务器会自动处理取消订阅逻辑,无需发送取消订阅消息
console.log('位置取消订阅已初始化,服务器将自动处理取消订阅逻辑');
}
/**
* 发送位置更新
* @param userId 用户ID
* @param latitude 纬度
* @param longitude 经度
*/
async sendLocationUpdate(userId, latitude, longitude) {
// 确保WebSocket连接已建立
if (!this.locationWebSocket) {
this.initLocationWebSocket();
}
// 发送位置更新消息
const locationMessage = {
type: 'updateLocation',
userId: userId,
latitude: latitude,
longitude: longitude,
timestamp: Date.now()
};
this.sendWebSocketMessage(locationMessage);
}
// ==================== 订单接口 ====================
/**
* 获取待指派订单
* @returns 待指派订单列表
*/
async getPendingOrders() {
return await this.request('/orders/pending');
}
/**
* 指派订单给货运人员
* @param orderId 订单ID
* @param deliveryPersonId 货运人员ID
*/
async assignOrder(orderId, deliveryPersonId) {
return await this.request(`/orders/${orderId}/assign`, {
method: 'POST',
data: { deliveryPersonId },
});
}
/**
* 获取货运人员当前订单
* @param deliveryPersonId 货运人员ID
* @returns 订单列表
*/
async getDeliveryPersonOrders(deliveryPersonId) {
return await this.request(`/delivery-persons/${deliveryPersonId}/orders`);
}
/**
* 根据ID获取订单
* @param id 订单ID
* @returns 订单详细信息
*/
async getOrderById(id) {
return await this.request(`/orders/${id}`);
}
/**
* 更新订单状态
* @param orderId 订单ID
* @param status 目标状态
*/
async updateOrderStatus(orderId, status) {
return await this.request(`/orders/${orderId}/status`, {
method: 'PUT',
data: { status },
});
}
/**
* 创建新订单
* @param orderData 订单数据
* @returns 创建的订单信息
*/
async createOrder(orderData) {
return await this.request('/orders', {
method: 'POST',
data: orderData,
});
}
/**
* 删除订单
* @param orderId 订单ID
*/
async deleteOrder(orderId) {
return await this.request(`/orders/${orderId}`, {
method: 'DELETE',
});
}
// ==================== 统计和日志接口 ====================
/**
* 获取系统统计信息
* @returns 系统统计数据
*/
async getSystemStats() {
return await this.request('/stats/system');
}
/**
* 获取订单统计信息
* @param timeRange 时间范围
* @returns 订单统计数据
*/
async getOrderStats(timeRange) {
return await this.request(`/stats/orders?timeRange=${timeRange}`);
}
/**
* 获取用户统计信息
* @returns 用户统计数据
*/
async getUserStats() {
return await this.request('/user/stats');
}
/**
* 获取用户活动日志
* @param userId 用户ID
* @param limit 日志数量
* @returns 活动日志列表
*/
async getUserActivityLogs(userId, limit = 20) {
return await this.request(`/user/${userId}/activity-logs?limit=${limit}`);
}
/**
* 上传错误日志
* @param error 错误信息
*/
async uploadErrorLog(error) {
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() {
return await this.request('/health');
}
}
/**
* API服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new ApiService();

88
dist/services/deliveryPersonService.js vendored Normal file
View File

@@ -0,0 +1,88 @@
"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"));
/**
* 货运人员服务类
* 提供货运人员信息管理、状态管理等功能
*/
class DeliveryPersonService {
/**
* 构造函数
*/
constructor() {
// 不再使用模拟数据
}
/**
* 获取所有货运人员
* @returns 货运人员列表
*/
async getDeliveryPersons() {
return apiService_1.default.getDeliveryPersons();
}
/**
* 根据ID获取货运人员
* @param id 货运人员ID
* @returns 货运人员信息或null
*/
async getDeliveryPersonById(id) {
try {
const result = await apiService_1.default.getDeliveryPersonById(id);
return result;
}
catch (error) {
console.error('获取货运人员失败:', error);
return null;
}
}
/**
* 获取空闲的货运人员
* @returns 空闲货运人员列表
*/
async getIdleDeliveryPersons() {
return apiService_1.default.getIdleDeliveryPersons();
}
/**
* 获取忙碌的货运人员
* @returns 忙碌货运人员列表
*/
async getBusyDeliveryPersons() {
return apiService_1.default.getBusyDeliveryPersons();
}
/**
* 获取货运人员当前订单
* @param deliveryPersonId 货运人员ID
* @returns 订单列表
*/
async getDeliveryPersonOrders(deliveryPersonId) {
return apiService_1.default.getDeliveryPersonOrders(deliveryPersonId);
}
/**
* 获取货运人员头像URL
* @param deliveryPersonId 货运人员ID
* @returns 头像URL
*/
async getAvatarUrl(deliveryPersonId) {
try {
// 首先尝试获取货运人员详细信息
const deliveryPerson = await this.getDeliveryPersonById(deliveryPersonId);
if (deliveryPerson && deliveryPerson.avatarUrl) {
return deliveryPerson.avatarUrl;
}
// 如果货运人员信息中没有头像URL尝试使用员工服务获取
const employeeService = require('./employeeService').default;
return await employeeService.getAvatarUrl(deliveryPersonId);
}
catch (error) {
console.error('获取货运人员头像失败:', error);
return '';
}
}
}
/**
* 货运人员服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new DeliveryPersonService();

147
dist/services/employeeService.js vendored Normal file
View File

@@ -0,0 +1,147 @@
"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"));
/**
* 员工管理服务类
* 提供员工信息的增删改查功能
*/
class EmployeeService {
/**
* 构造函数
*/
constructor() {
// 不再使用模拟数据
}
/**
* 获取所有员工列表
* @returns 员工信息数组
*/
async getEmployees() {
try {
return await apiService_1.default.getEmployees();
}
catch (error) {
console.error('获取员工列表失败:', error);
// API调用失败时返回空数组
return [];
}
}
/**
* 添加新员工
* @param employeeInfo 员工信息
* @returns 添加的员工信息
*/
async addEmployee(employeeInfo) {
try {
return await apiService_1.default.addEmployee(employeeInfo);
}
catch (error) {
console.error('添加员工失败:', error);
throw new Error('添加员工失败,请稍后重试');
}
}
/**
* 删除员工
* @param employeeId 员工ID
* @returns 删除结果
*/
async deleteEmployee(employeeId) {
try {
return await apiService_1.default.deleteEmployee(employeeId);
}
catch (error) {
console.error('删除员工失败:', error);
return {
success: false,
message: '删除员工失败,请稍后重试'
};
}
}
/**
* 更新员工信息
* @param employeeId 员工ID
* @param employeeInfo 员工信息
* @returns 更新后的员工信息
*/
async updateEmployee(employeeId, employeeInfo) {
try {
return await apiService_1.default.updateEmployee(employeeId, employeeInfo);
}
catch (error) {
console.error('更新员工信息失败:', error);
throw new Error('更新员工信息失败,请稍后重试');
}
}
/**
* 根据工号查找员工
* @param phone 工号
* @returns 员工信息或null
*/
async findEmployeeByPhone(phone) {
const employees = await this.getEmployees();
return employees.find(emp => emp.phone === phone) || null;
}
/**
* 验证员工信息(用于绑定时检查)
* @param name 姓名
* @param phone 工号
* @returns 验证结果
*/
async validateEmployee(name, phone) {
const employees = await this.getEmployees();
const employee = employees.find(emp => emp.name === name && emp.phone === phone);
if (employee) {
return {
success: true,
message: '员工信息验证成功',
employee
};
}
else {
return {
success: false,
message: '员工信息不存在,请联系管理员添加'
};
}
}
/**
* 上传员工头像
* @param employeeId 员工ID
* @param filePath 头像文件路径
* @returns 上传结果
*/
async uploadAvatar(employeeId, filePath) {
try {
return await apiService_1.default.uploadEmployeeAvatar(employeeId, filePath);
}
catch (error) {
console.error('上传头像失败:', error);
return {
success: false,
message: '上传头像失败,请稍后重试'
};
}
}
/**
* 获取员工头像URL
* @param employeeId 员工ID
* @returns 头像URL
*/
async getAvatarUrl(employeeId) {
try {
return await apiService_1.default.getEmployeeAvatar(employeeId);
}
catch (error) {
console.error('获取头像失败:', error);
return '';
}
}
}
/**
* 员工管理服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new EmployeeService();

482
dist/services/locationTrackingService.js vendored Normal file
View File

@@ -0,0 +1,482 @@
"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();

350
dist/services/mapService.js vendored Normal file
View File

@@ -0,0 +1,350 @@
"use strict";
// 地图服务 - 处理地图相关的功能,包括定位、路线规划、地理编码等
Object.defineProperty(exports, "__esModule", { value: true });
/**
* 地图服务类
* 提供地图相关功能,包括定位、路线规划、地理编码等
*/
class MapService {
/**
* 构造函数,初始化地图实例
*/
constructor() {
this.amapFile = require('../libs/amap-wx.js');
this.MAP_KEY = '1fc5cafd570d9fbfd14c39359d41823d';
this.KUNMING_CENTER = {
longitude: 102.833722,
latitude: 24.880095
};
this.amapInstance = new this.amapFile.AMapWX({ key: this.MAP_KEY });
}
/**
* 获取用户位置信息
* @returns 用户位置坐标
*/
async getLocation() {
return new Promise((resolve, reject) => {
console.log('开始调用高德地图SDK获取位置...');
// 添加超时机制
const timeout = setTimeout(() => {
console.error('高德地图SDK调用超时使用模拟位置');
resolve({
longitude: 102.7123,
latitude: 25.0409
});
}, 10000); // 10秒超时
try {
// 高德地图SDK的getWxLocation方法需要两个参数配置对象和回调函数
this.amapInstance.getWxLocation({
type: 'gcj02', // 使用国测局坐标系
success: (res) => {
clearTimeout(timeout);
console.log('高德地图SDK定位成功:', res);
resolve(res);
},
fail: (err) => {
clearTimeout(timeout);
console.error('高德地图SDK定位失败:', err);
// 注释高德SDK失败后直接使用模拟位置不调用微信原生API
// 原因:微信小程序可能没有位置权限,避免权限错误
console.log('高德地图SDK定位失败使用模拟位置');
resolve({
longitude: 102.7123,
latitude: 25.0409
});
}
}, (locationString) => {
// 这是高德地图SDK的回调函数参数是格式化的位置字符串
console.log('高德地图SDK格式化位置:', locationString);
// 如果格式化位置回调被调用说明SDK已经获取到位置
// 尝试从格式化字符串中解析经纬度
if (locationString) {
const coords = locationString.split(',');
if (coords.length === 2) {
const longitude = parseFloat(coords[0]);
const latitude = parseFloat(coords[1]);
if (!isNaN(longitude) && !isNaN(latitude)) {
clearTimeout(timeout);
console.log('从格式化位置解析成功,使用解析的位置:', { longitude, latitude });
resolve({ longitude, latitude });
return;
}
}
}
// 如果无法解析继续等待success回调
console.log('格式化位置回调被调用但无法解析位置继续等待success回调...');
});
}
catch (error) {
clearTimeout(timeout);
console.error('高德地图SDK调用异常:', error);
reject(error);
}
});
}
/**
* 获取当前位置信息(兼容格式)
* @returns 当前位置的详细信息
*/
async getCurrentLocation() {
const location = await this.getLocation();
return {
latitude: location.latitude,
longitude: location.longitude,
accuracy: 50,
speed: 0,
altitude: 1891
};
}
/**
* 获取位置详细信息(逆地理编码)
* @param longitude 经度
* @param latitude 纬度
* @returns 逆地理编码结果
*/
async getLocationInfo(longitude, latitude) {
return new Promise((resolve, reject) => {
this.amapInstance.getRegeo({
location: `${longitude.toFixed(6)},${latitude.toFixed(6)}`,
success: (res) => {
console.log('逆地理编码成功:', res);
resolve(res);
},
fail: (err) => {
console.log('逆地理编码失败:', err);
reject(err);
}
});
});
}
/**
* 获取昆明中心点坐标
* @returns 昆明中心点坐标
*/
getKunmingCenter() {
return this.KUNMING_CENTER;
}
/**
* 搜索地点
* @param keyword 搜索关键词
* @param city 城市名称
* @returns 搜索结果列表
*/
async searchPoi(keyword, city) {
return new Promise((resolve, reject) => {
this.amapInstance.getPoiAround({
querykeywords: keyword,
city: city,
radius: 50000, // 搜索半径50公里
offset: 20, // 返回20条结果
success: (res) => {
console.log('搜索POI成功:', res);
if (res.pois && res.pois.length > 0) {
const results = res.pois.map((poi) => ({
id: poi.id,
name: poi.name,
address: poi.address,
longitude: parseFloat(poi.location.split(',')[0]),
latitude: parseFloat(poi.location.split(',')[1]),
phone: poi.tel || ''
}));
resolve(results);
}
else {
resolve([]);
}
},
fail: (err) => {
console.error('搜索POI失败:', err);
reject(err);
}
});
});
}
/**
* 规划驾车路线
* @param origin 起点坐标字符串 (经度,纬度)
* @param destination 终点坐标字符串 (经度,纬度)
* @returns 路线规划结果
*/
async getDrivingRoute(origin, destination) {
return new Promise((resolve, reject) => {
this.amapInstance.getDrivingRoute({
origin,
destination,
strategy: '0', // 推荐路线策略
showtraffic: false, // 不显示交通状况
success: (res) => {
console.log('高德地图路线规划API调用成功');
if (res.paths && res.paths.length > 0) {
const path = res.paths[0];
const result = {
polyline: path.polyline || '',
distance: path.distance || 0,
duration: path.duration || 0
};
console.log(`路线规划完成: 距离${result.distance}米, 预计${result.duration}`);
resolve(result);
}
else {
resolve({
polyline: '',
distance: 0,
duration: 0
});
}
},
fail: (err) => {
console.error('高德地图路线规划API调用失败:', err);
reject(err);
}
});
});
}
/**
* 计算两点之间的距离(米)
* @param lat1 第一个点的纬度
* @param lng1 第一个点的经度
* @param lat2 第二个点的纬度
* @param lng2 第二个点的经度
* @returns 两点之间的距离(米)
*/
calculateDistance(lat1, lng1, lat2, lng2) {
const R = 6371000; // 地球半径(米)
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLng = (lng2 - lng1) * Math.PI / 180;
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
/**
* 获取路线规划(通用版本)
* @param origin 起点坐标
* @param destination 终点坐标
* @returns 路线规划结果
*/
async getRoute(origin, destination) {
// 对于真实模式,目前只支持驾车路线
const originStr = `${origin.longitude},${origin.latitude}`;
const destStr = `${destination.longitude},${destination.latitude}`;
const result = await this.getDrivingRoute(originStr, destStr);
// 转换polyline格式
const polylinePoints = [];
if (result.polyline) {
const points = result.polyline.split(';');
for (const point of points) {
const [lng, lat] = point.split(',');
if (lng && lat) {
polylinePoints.push({
latitude: parseFloat(lat),
longitude: parseFloat(lng)
});
}
}
}
return {
distance: result.distance,
duration: result.duration,
polyline: polylinePoints
};
}
/**
* 地理编码 - 地址转坐标
* @param address 地址字符串
* @returns 坐标信息
*/
async geocode(address) {
// 对于真实模式使用搜索API来模拟地理编码
const results = await this.searchPoi(address, '昆明');
if (results.length > 0) {
return {
latitude: results[0].latitude,
longitude: results[0].longitude,
formattedAddress: results[0].address
};
}
// 如果没有找到结果,返回默认位置
return {
latitude: 25.0409,
longitude: 102.7123,
formattedAddress: '云南省昆明市'
};
}
/**
* 逆地理编码 - 坐标转地址
* @param latitude 纬度
* @param longitude 经度
* @returns 地址信息
*/
async reverseGeocode(latitude, longitude) {
const result = await this.getLocationInfo(longitude, latitude);
return {
// 修复不再使用不存在的formatted_address字段而是根据已有的addressComponent字段构建格式化地址
formattedAddress: `${(result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.province) || '云南省'}${(result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.city) || '昆明市'}${(result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.district) || '五华区'}` || '未知地址',
country: '中国',
province: (result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.province) || '云南省',
city: (result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.city) || '昆明市',
district: (result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.district) || '五华区',
street: (result.regeocode && result.regeocode.addressComponent && result.regeocode.addressComponent.township) || ''
};
}
/**
* 获取附近的地点
* @param latitude 纬度
* @param longitude 经度
* @param radius 搜索半径
* @param type 地点类型
* @returns 附近地点列表
*/
async getNearbyPlaces(latitude, longitude, radius, type) {
// 对于真实模式使用搜索API
const keyword = type ? type : '';
const results = await this.searchPoi(keyword, '昆明');
return results.map(place => ({
id: place.id,
name: place.name,
latitude: place.latitude,
longitude: place.longitude,
address: place.address,
distance: this.calculateDistance(latitude, longitude, place.latitude, place.longitude)
})).filter(place => place.distance <= radius);
}
/**
* 格式化路线距离
* @param distance 距离(米)
* @returns 格式化后的距离字符串
*/
formatRouteDistance(distance) {
if (distance < 1000) {
return `${distance}`;
}
else {
return `${(distance / 1000).toFixed(1)}公里`;
}
}
/**
* 格式化路线时间
* @param duration 时间(秒)
* @returns 格式化后的时间字符串
*/
formatRouteDuration(duration) {
if (duration < 60) {
return `${Math.round(duration)}`;
}
else if (duration < 3600) {
return `${Math.round(duration / 60)} 分钟`;
}
else {
const hours = Math.floor(duration / 3600);
const minutes = Math.round((duration % 3600) / 60);
return `${hours}小时${minutes}分钟`;
}
}
}
/**
* 地图服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new MapService();

78
dist/services/orderService.js vendored Normal file
View File

@@ -0,0 +1,78 @@
"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"));
class OrderService {
/**
* 构造函数
*/
constructor() {
// 不再使用模拟数据
}
/**
* 获取所有待处理订单
*/
async getPendingOrders() {
return apiService_1.default.getPendingOrders();
}
/**
* 根据ID获取订单
*/
async getOrderById(id) {
return apiService_1.default.getOrderById(id);
}
/**
* 指派订单给货运人员
* @param orderId 订单ID
* @param deliveryPersonId 货运人员ID
* @returns 指派结果包含success状态和可选消息
*/
async assignOrder(orderId, deliveryPersonId) {
// 真实环境中调用API
try {
return await apiService_1.default.assignOrder(orderId, deliveryPersonId);
}
catch (error) {
console.error('指派订单失败:', error);
return { success: false, message: error instanceof Error ? error.message : '指派失败' };
}
}
/**
* 更新订单状态
*/
async updateOrderStatus(orderId, status) {
return apiService_1.default.updateOrderStatus(orderId, status).then(result => ({
success: result.success,
message: result.message || '状态更新成功'
}));
}
/**
* 创建新订单
*/
async createOrder(orderData) {
return apiService_1.default.createOrder(orderData);
}
/**
* 获取货运人员的订单列表
*/
async getDeliveryPersonOrders(deliveryPersonId) {
return apiService_1.default.getDeliveryPersonOrders(deliveryPersonId);
}
/**
* 删除订单
* @param orderId 订单ID
*/
async deleteOrder(orderId) {
try {
await apiService_1.default.deleteOrder(orderId);
return { success: true, message: '删除成功' };
}
catch (error) {
console.error('删除订单失败:', error);
return { success: false, message: error instanceof Error ? error.message : '删除失败' };
}
}
}
exports.default = new OrderService();

133
dist/services/statisticsService.js vendored Normal file
View File

@@ -0,0 +1,133 @@
"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"));
/**
* 统计服务类
* 提供系统统计数据的获取和缓存功能
*/
class StatisticsService {
constructor() {
// 数据缓存
this.cache = null;
// 缓存超时时间5分钟
this.cacheTimeout = 5 * 60 * 1000;
}
/**
* 获取系统统计数据
* 采用一个API请求获取三个统计数据后续操作客户端自行统计
* @param forceRefresh 是否强制刷新,不使用缓存
*/
async getSystemStats(forceRefresh = false) {
// 检查缓存是否有效,且不强制刷新
if (!forceRefresh && this.cache && Date.now() - this.cache.timestamp < this.cacheTimeout) {
console.log('使用缓存的统计数据');
return this.cache;
}
console.log('重新获取统计数据');
try {
// 使用系统统计API获取三个统计数据
const systemStats = await this.getSystemStatsFromAPI();
this.cache = {
...systemStats,
timestamp: Date.now()
};
return this.cache;
}
catch (error) {
console.warn('系统统计API不可用使用默认值:', error);
// 如果API不可用返回默认值
this.cache = {
employeeCount: 0,
orderCount: 0,
warehouseCount: 0,
pendingOrders: 0,
activeOrders: 0,
completedOrders: 0,
timestamp: Date.now()
};
return this.cache;
}
}
/**
* 从API获取系统统计数据
*/
async getSystemStatsFromAPI() {
try {
// 调用系统统计API
const response = await apiService_1.default.getSystemStats();
console.log('API返回的统计数据:', response);
// API返回的数据结构是 { data: { ... }, success: true }
// 需要提取data字段中的数据
const stats = response.data || response;
console.log('提取的统计数据:', stats);
// 转换API响应格式为StatisticsData格式
// 根据API实际返回的字段进行映射
const result = {
employeeCount: stats.totalEmployees || stats.totalDeliveryPersons || 0,
orderCount: stats.totalOrders || (stats.pendingOrders || 0) + (stats.activeOrders || 0),
warehouseCount: stats.totalWarehouses || 0,
pendingOrders: stats.pendingOrders || 0,
activeOrders: stats.activeOrders || 0,
completedOrders: 0, // 需要从其他接口获取
timestamp: Date.now()
};
console.log('转换后的统计数据:', result);
return result;
}
catch (error) {
console.error('获取系统统计数据失败:', error);
throw error;
}
}
/**
* 手动刷新统计数据(清除缓存)
*/
refreshStats() {
this.cache = null;
console.log('统计数据缓存已清除');
}
/**
* 获取缓存状态
*/
getCacheStatus() {
if (!this.cache) {
return { hasCache: false, isExpired: true, age: 0 };
}
const age = Date.now() - this.cache.timestamp;
const isExpired = age > this.cacheTimeout;
return { hasCache: true, isExpired, age };
}
/**
* 客户端更新统计数据(直接传值更新)
* @param type 数据类型:'employee' | 'order' | 'warehouse'
* @param count 对应的数量值
*/
updateStats(type, count) {
if (!this.cache) {
console.warn('没有缓存数据,无法更新统计');
return;
}
switch (type) {
case 'employee':
this.cache.employeeCount = Math.max(0, count);
break;
case 'order':
this.cache.orderCount = Math.max(0, count);
break;
case 'warehouse':
this.cache.warehouseCount = Math.max(0, count);
break;
}
this.cache.timestamp = Date.now();
console.log(`统计数据已更新: ${type} = ${count}`);
}
}
/**
* 统计服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new StatisticsService();

357
dist/services/userService.js vendored Normal file
View File

@@ -0,0 +1,357 @@
"use strict";
// 用户服务文件
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const roleUtils_1 = require("../utils/roleUtils");
const apiService_1 = __importDefault(require("./apiService"));
/**
* 用户服务类
* 提供用户认证、信息管理、权限验证等功能
*/
class UserService {
/**
* 构造函数
*/
constructor() {
// 不再使用模拟数据
}
/**
* 获取用户信息
* @returns 用户信息
*/
async getUserInfo() {
return apiService_1.default.getUserInfo();
}
/**
* 用户退出登录
*/
async logout() {
return apiService_1.default.logout();
}
/**
* 检查用户是否已登录
* @returns 是否已登录
*/
isLoggedIn() {
const app = getApp();
return app.globalData.isLoggedIn && !!app.globalData.userInfo;
}
/**
* 获取用户角色
* @returns 用户角色或null
*/
getUserRole() {
const app = getApp();
return app.globalData.userInfo && app.globalData.userInfo.role || null;
}
/**
* 检查用户是否为管理员
* @returns 是否为管理员
*/
isAdmin() {
return this.getUserRole() === roleUtils_1.Role.ADMIN;
}
/**
* 检查用户是否为货运人员
* @returns 是否为货运人员
*/
isDeliveryPerson() {
return this.getUserRole() === roleUtils_1.Role.DELIVERY_PERSON;
}
/**
* 检查位置权限
* @returns 是否拥有位置权限
*/
checkLocationPermission() {
return new Promise((resolve) => {
wx.getSetting({
success: (res) => {
const hasPermission = res.authSetting && res.authSetting['scope.userLocation'];
resolve(!!hasPermission);
},
fail: () => {
resolve(false);
}
});
});
}
/**
* 请求位置权限
* @returns 请求是否成功
*/
requestLocationPermission() {
return new Promise((resolve) => {
wx.authorize({
scope: 'scope.userLocation',
success: () => {
resolve(true);
},
fail: () => {
resolve(false);
}
});
});
}
/**
* 获取全局用户信息
* @returns 全局用户信息或null
*/
getGlobalUserInfo() {
const app = getApp();
return app.globalData.userInfo;
}
/**
* 执行静默登录流程:微信登录->个人服务器登录->进入基础界面->签到/绑定
* @returns 登录结果
*/
async wxLogin() {
try {
// 获取微信登录code
console.log('步骤1: 获取微信登录code');
const code = await this.getWxLoginCode();
if (!code) {
console.error('步骤1失败: 获取微信登录code失败');
throw new Error('获取微信登录code失败');
}
console.log('步骤1成功: 获取到微信登录code');
// 调用微信登录API
console.log('步骤2: 调用微信登录API');
const wxLoginResult = await this.ServerLogin(code);
if (wxLoginResult.success) {
console.log('步骤2成功: 微信登录API调用成功');
// 静默登录模式下,不主动获取用户信息
let userInfo = wxLoginResult.userInfo;
return {
success: true,
userInfo,
openid: wxLoginResult.openid,
session_key: wx.getStorageSync('session_key'), //TODO:服务器已经下发
token: wxLoginResult.token
};
}
else {
console.error('步骤2失败: 微信登录API返回失败');
return {
success: false,
openid: wxLoginResult.openid
};
}
}
catch (error) {
console.error('登录流程异常:', error);
return { success: false };
}
}
/**
* 微信登录成功后调用个人服务器登录消息
* @param code 微信登录授权码
* @returns 登录结果
*/
async ServerLogin(code) {
try {
// 真实API模式
//TODO: 登录成功的基础数据:服务器下发的公共游客可看的数据
const result = await apiService_1.default.ServerLogin(code);
// 确保用户信息包含头像URL如果为空则设置默认头像
const userInfoWithAvatar = {
...result.user,
avatarUrl: result.user.avatarUrl || '/images/truck.png'
};
// 保存到本地存储
wx.setStorageSync('userInfo', userInfoWithAvatar);
wx.setStorageSync('token', result.token);
wx.setStorageSync('openid', result.openid);
wx.setStorageSync('session_key', result.session_key);
// 同时保存到全局数据确保后续API调用能正确获取token
const app = getApp();
app.globalData.token = result.token;
return {
success: true,
openid: result.openid,
token: result.token,
userInfo: userInfoWithAvatar
};
}
catch (error) {
console.error('微信登录失败:', error);
return { success: false };
}
}
/**
* 获取微信登录code
*/
async getWxLoginCode() {
return new Promise((resolve) => {
wx.login({
success: (res) => {
if (res.code) {
console.log('成功获取到登录code');
resolve(res.code);
}
else {
console.error('获取登录code失败返回值为空');
resolve(null);
}
},
fail: (error) => {
console.error('wx.login调用失败:', error);
resolve(null);
}
});
});
}
/**
* 更新用户信息
* @param userInfo 待更新的用户信息
* @returns 更新后的用户信息
*/
async updateUserInfo(userInfo) {
return apiService_1.default.updateUserInfo(userInfo);
}
/**
* 获取用户签到状态
* @returns 用户状态信息
*/
async getUserStatus() {
try {
// 调用服务器接口获取用户状态
const response = await apiService_1.default.getUserStatus();
return response;
}
catch (error) {
console.error('获取用户状态失败:', error);
// 如果是404错误接口不存在返回null让前端使用本地逻辑
if (error.message && error.message.includes('404')) {
console.log('服务器状态接口不存在,使用本地逻辑');
return null; // 返回null表示服务器接口不可用
}
// 其他网络错误时返回默认状态
return {
status: 'registered'
};
}
}
/**
* 用户签到
* @param initialLocation 初始位置数据(必须)
* @returns 签到结果和更新后的用户信息
*/
async signIn(initialLocation) {
const userInfo = this.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
throw new Error('用户未登录,无法签到');
}
// 检查是否有有效的token防止后端空指针异常
const app = getApp();
if (!app.globalData.token) {
throw new Error('用户认证信息缺失,请重新登录');
}
return apiService_1.default.userSignIn(userInfo.id, initialLocation);
}
/**
* 用户签退
* @returns 签退结果
*/
async signOut() {
const userInfo = this.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
throw new Error('用户未登录,无法签退');
}
// 检查是否有有效的token防止后端空指针异常
const app = getApp();
if (!app.globalData.token) {
throw new Error('用户认证信息缺失,请重新登录');
}
return apiService_1.default.userSignOut(userInfo.id);
}
/**
* 用户绑定
* @param registerInfo 绑定信息
* @returns 绑定结果和员工信息
*/
async register(registerInfo) {
return apiService_1.default.userRegister(registerInfo);
}
/**
* 解绑微信
* 清除当前用户的openid绑定允许重新注册其他账号
* @returns 解绑结果
*/
async unbindWechat() {
try {
console.log('开始解绑微信流程');
// 调用API解绑
const result = await apiService_1.default.unbindWechat();
if (result.success) {
console.log('微信解绑成功');
// 清除本地存储的登录信息
wx.removeStorageSync('userInfo');
wx.removeStorageSync('token');
wx.removeStorageSync('openid');
wx.removeStorageSync('session_key');
// 清除全局数据
const app = getApp();
app.globalData.userInfo = null;
app.globalData.token = null;
app.globalData.openid = null;
app.globalData.isLoggedIn = false;
console.log('本地登录信息已清除');
// 解绑成功后跳转到主界面
setTimeout(() => {
wx.reLaunch({
url: '/pages/index/index'
});
}, 500);
}
return result;
}
catch (error) {
console.error('解绑微信失败:', error);
return { success: false, message: '解绑微信失败,请重试' };
}
}
/**
* 获取用户权限列表
* @returns 权限列表
*/
async getUserPermissions() {
return apiService_1.default.getUserPermissions();
}
/**
* 检查用户是否在线
* @returns 是否在线
*/
async checkUserOnline() {
return apiService_1.default.checkUserOnline();
}
/**
* 获取用户会话信息
* @returns 会话信息
*/
async getSessionInfo() {
return apiService_1.default.getSessionInfo();
}
/**
* 刷新用户令牌
* @param oldToken 旧令牌
* @returns 新令牌及过期时间
*/
async refreshToken(oldToken) {
return apiService_1.default.refreshToken(oldToken);
}
/**
* 验证用户权限
* @param permission 待验证的权限
* @returns 是否拥有该权限
*/
async verifyPermission(permission) {
return apiService_1.default.verifyPermission(permission);
}
}
/**
* 用户服务单例实例
* 导出供应用程序全局使用
*/
exports.default = new UserService();

95
dist/services/warehouseService.js vendored Normal file
View File

@@ -0,0 +1,95 @@
"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"));
/**
* 仓库服务类
* 封装了所有仓库相关的操作
*/
class WarehouseService {
/**
* 构造函数
*/
constructor() {
// 真实API模式下不需要模拟数据
}
/**
* 获取仓库状态的中文描述
*/
getWarehouseStatusText(status) {
const statusMap = {
'open': '营业中',
'closed': '已关闭',
'maintenance': '维护中'
};
return statusMap[status || 'open'] || '未知状态';
}
/**
* 获取所有仓库信息
*/
async getWarehouses() {
return apiService_1.default.getWarehouses();
}
/**
* 根据ID获取仓库信息
*/
async getWarehouseById(id) {
return apiService_1.default.getWarehouseById(id);
}
/**
* 创建仓库
*/
async createWarehouse(warehouseData) {
try {
const result = await apiService_1.default.createWarehouse(warehouseData);
console.log('创建仓库结果:', result);
if (result.success && result.data) {
return result.data;
}
else {
throw new Error(result.message || '创建仓库失败');
}
}
catch (error) {
console.error('创建仓库失败:', error);
throw new Error('创建仓库失败');
}
}
/**
* 更新仓库信息
*/
async updateWarehouse(warehouseId, warehouseInfo) {
try {
const result = await apiService_1.default.updateWarehouse(warehouseId, warehouseInfo);
console.log(`更新仓库 ${warehouseId} 结果:`, result);
if (result.success && result.data) {
return result.data;
}
else {
throw new Error(result.message || '更新仓库失败');
}
}
catch (error) {
console.error('更新仓库失败:', error);
throw new Error('更新仓库失败');
}
}
/**
* 删除仓库
*/
async deleteWarehouse(warehouseId) {
try {
const result = await apiService_1.default.deleteWarehouse(warehouseId);
console.log(`删除仓库 ${warehouseId} 结果:`, result);
return result.success;
}
catch (error) {
console.error('删除仓库失败:', error);
throw new Error('删除仓库失败');
}
}
}
// 导出单例实例
exports.default = new WarehouseService();