地址路径修改

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

View File

@@ -1,4 +1,5 @@
import { WarehouseInfo, UserInfo, DeliveryPerson, Order, EmployeeInfo } from '../types';
import { Role } from '../utils/roleUtils';
import locationTrackingService from './locationTrackingService';
@@ -9,7 +10,7 @@ import locationTrackingService from './locationTrackingService';
// API基础URL配置
const IS_LOCAL_DEV = false; // true: 本地开发环境, false: 生产环境
const API_BASE_URL = IS_LOCAL_DEV ? 'http://localhost:8080' : 'https://www.doubleyin.cn';
export const API_BASE_URL = IS_LOCAL_DEV ? 'http://localhost:8080' : 'https://www.doubleyin.cn';
console.log(`当前API地址: ${API_BASE_URL} (${IS_LOCAL_DEV ? '本地开发环境' : '生产环境'})`);
@@ -158,7 +159,7 @@ async ServerLogin(code: string) {
id: response.userInfo.id,
name: response.userInfo.name,
phone: response.userInfo.phone,
role: response.userInfo.role || 'DELIVERY_PERSON'
role: response.userInfo.role || Role.DELIVERY_PERSON
},
message: response.message
};
@@ -187,7 +188,7 @@ async ServerLogin(code: string) {
id: response.id,
name: response.name || userInfo.name,
phone: response.phone || userInfo.phone,
role: response.role || 'DELIVERY_PERSON'
role: response.role || Role.DELIVERY_PERSON
},
message: '绑定成功'
};
@@ -199,7 +200,7 @@ async ServerLogin(code: string) {
id: response.userInfo.id,
name: response.userInfo.name || userInfo.name,
phone: response.userInfo.phone || userInfo.phone,
role: response.userInfo.role || 'DELIVERY_PERSON'
role: response.userInfo.role || Role.DELIVERY_PERSON
},
message: response.message
};
@@ -212,7 +213,7 @@ async ServerLogin(code: string) {
id: 0,
name: userInfo.name,
phone: userInfo.phone,
role: 'DELIVERY_PERSON'
role: Role.DELIVERY_PERSON
},
message: '绑定响应格式错误'
};
@@ -430,6 +431,63 @@ async ServerLogin(code: string) {
});
}
/**
* 上传员工头像
* @param employeeId 员工ID
* @param filePath 头像文件路径
* @returns 上传结果
*/
async uploadEmployeeAvatar(employeeId: number, filePath: string): Promise<{ success: boolean; message?: string; avatarUrl?: string }> {
return new Promise((resolve, reject) => {
// 使用微信小程序的文件上传API
wx.uploadFile({
url: `${API_BASE_URL}/employees/${employeeId}/avatar`,
filePath: filePath,
name: 'avatar',
header: {
'Authorization': `Bearer ${getApp<any>().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: number): Promise<string> {
try {
// 尝试获取头像信息
const response = await this.request<{ avatarUrl: string }>(`/employees/${employeeId}/avatar`);
return response.avatarUrl || `${API_BASE_URL}/avatars/${employeeId}.jpg`;
} catch (error) {
// 如果获取失败返回默认头像URL
return `${API_BASE_URL}/avatars/${employeeId}.jpg`;
}
}
// ==================== 仓库相关接口 ====================
/**
@@ -458,6 +516,42 @@ async ServerLogin(code: string) {
return await this.request<Order[]>(`/warehouses/${warehouseId}/orders`);
}
/**
* 创建仓库
* @param warehouseData 仓库数据
* @returns 创建结果
*/
async createWarehouse(warehouseData: Omit<WarehouseInfo, 'id' | 'createdAt' | 'updatedAt'>): Promise<{ success: boolean; message?: string; data?: WarehouseInfo }> {
return await this.request<{ success: boolean; message?: string; data?: WarehouseInfo }>('/warehouses', {
method: 'POST',
data: warehouseData
});
}
/**
* 更新仓库信息
* @param warehouseId 仓库ID
* @param warehouseInfo 仓库信息
* @returns 更新结果
*/
async updateWarehouse(warehouseId: number, warehouseInfo: { name?: string; address?: string; contact?: string; phone?: string; description?: string; capacity?: number; longitude?: number; latitude?: number; status?: 'open' | 'closed' | 'maintenance' }): Promise<{ success: boolean; message?: string; data?: WarehouseInfo }> {
return await this.request<{ success: boolean; message?: string; data?: WarehouseInfo }>(`/warehouses/${warehouseId}`, {
method: 'PUT',
data: warehouseInfo
});
}
/**
* 删除仓库
* @param warehouseId 仓库ID
* @returns 删除结果
*/
async deleteWarehouse(warehouseId: number): Promise<{ success: boolean; message?: string }> {
return await this.request<{ success: boolean; message?: string }>(`/warehouses/${warehouseId}`, {
method: 'DELETE',
});
}
// ==================== 货运人员接口 ====================
/**

View File

@@ -1,6 +1,7 @@
// 货运人员服务 - 处理货运人员相关的数据操作
import { DeliveryPerson } from '../types';
import apiService from './apiService';
import { API_BASE_URL } from './apiService';
/**
* 货运人员服务类
@@ -79,6 +80,27 @@ class DeliveryPersonService {
}>> {
return apiService.getDeliveryPersonOrders(deliveryPersonId);
}
/**
* 获取货运人员头像URL
* @param deliveryPersonId 货运人员ID
* @returns 头像URL
*/
async getAvatarUrl(deliveryPersonId: number): Promise<string> {
try {
// 首先尝试获取货运人员详细信息
const deliveryPerson = await this.getDeliveryPersonById(deliveryPersonId);
if (deliveryPerson && deliveryPerson.avatarPath) {
return `${API_BASE_URL}${deliveryPerson.avatarPath}`;
}
// 如果货运人员信息中没有头像路径,返回默认头像
return '/images/truck.png';
} catch (error) {
console.error('获取货运人员头像失败:', error);
return '/images/truck.png';
}
}
}
/**

View File

@@ -109,6 +109,38 @@ class EmployeeService {
};
}
}
/**
* 上传员工头像
* @param employeeId 员工ID
* @param filePath 头像文件路径
* @returns 上传结果
*/
async uploadAvatar(employeeId: number, filePath: string): Promise<{ success: boolean; message?: string; avatarUrl?: string }> {
try {
return await apiService.uploadEmployeeAvatar(employeeId, filePath);
} catch (error) {
console.error('上传头像失败:', error);
return {
success: false,
message: '上传头像失败,请稍后重试'
};
}
}
/**
* 获取员工头像URL
* @param employeeId 员工ID
* @returns 头像URL
*/
async getAvatarUrl(employeeId: number): Promise<string> {
try {
return await apiService.getEmployeeAvatar(employeeId);
} catch (error) {
console.error('获取头像失败:', error);
return '';
}
}
}
/**

View File

@@ -3,18 +3,20 @@ import { LocationData } from '../types';
import apiService from './apiService';
import userService from './userService';
import mapService from './mapService';
import { API_BASE_URL } from './apiService';
// import { avatarCache } from '../utils/avatarCache';
/**
* 在线用户信息接口
*/
export interface OnlineUserInfo {
userId: number;
userId: string;
name: string;
avatarUrl: string;
role: string; // 用户角色:'admin' | 'delivery_person'
avatarPath?: string; // 头像相对路径(服务器下发)
role: string;
lastLocation: LocationData;
lastUpdateTime: number;
status: 'online' | 'offline' | 'timeout';
status: 'online' | 'offline'| 'timeout';
}
/**
@@ -196,6 +198,25 @@ class LocationTrackingService {
/**
* 获取完整的头像URL
* @param avatarPath 头像相对路径
* @returns 完整的头像URL
*/
getFullAvatarUrl(avatarPath: string | undefined): string | undefined {
if (!avatarPath) {
return undefined;
}
// 如果已经是完整URL直接返回
if (avatarPath.startsWith('http')) {
return avatarPath;
}
// 将相对路径转换为完整URL
return `${API_BASE_URL}${avatarPath}`;
}
/**
* 获取当前位置
*/
@@ -406,7 +427,9 @@ class LocationTrackingService {
lastUpdateTime: user.lastUpdateTime,
latitude: user.locationData?.latitude || user.latitude,
longitude: user.locationData?.longitude || user.longitude,
timestamp: user.locationData?.timestamp || user.timestamp
timestamp: user.locationData?.timestamp || user.timestamp,
avatarPath: user.avatarPath,
address: user.address
}))
});
}else {
@@ -446,7 +469,8 @@ class LocationTrackingService {
lastUpdateTime: user.lastUpdateTime || locationData.timestamp || Date.now(),
latitude: locationData.latitude,
longitude: locationData.longitude,
timestamp: locationData.timestamp || user.timestamp || Date.now()
timestamp: locationData.timestamp || user.timestamp || Date.now(),
avatarPath: user.avatarPath || (existingUser ? existingUser.avatarPath : undefined),
};
// 验证必需字段
@@ -456,7 +480,7 @@ class LocationTrackingService {
}
return formattedUser;
}).filter(user => user !== null); // 过滤掉无效数据
}).filter((user: any) => user !== null); // 过滤掉无效数据
console.log('📊 转换后的用户位置数据:', formattedUsers);
@@ -530,7 +554,7 @@ class LocationTrackingService {
this.onlineUsers.set(user.userId, {
userId: user.userId,
name: user.name || user.userName || (existingUser ? existingUser.name : `用户${user.userId}`),
avatarUrl: '/images/user-avatar.png',
avatarPath: user.avatarPath || (existingUser ? existingUser.avatarPath : undefined),
role: user.role || (existingUser ? existingUser.role : 'DRIVER'),
lastLocation: {
userId: user.userId,
@@ -539,7 +563,12 @@ class LocationTrackingService {
timestamp: timestamp
},
lastUpdateTime: timestamp,
status: user.userStatus === false ? 'offline' : 'online'
status: user.userStatus === false ? 'offline' : 'online',
// currentLocation: {
// address: user.address || (existingUser ? existingUser.currentLocation?.address : '位置信息获取中...'),
// longitude: longitude,
// latitude: latitude
// }
});
console.log(`[LocationTrackingService] 更新用户 ${user.userId} 位置: (${latitude}, ${longitude})`);

View File

@@ -0,0 +1,158 @@
// 统计服务 - 处理系统统计数据获取和缓存
import apiService from './apiService';
/**
* 统计数据接口
*/
export interface StatisticsData {
employeeCount: number; // 员工总数
orderCount: number; // 订单总数
warehouseCount: number; // 仓库总数
pendingOrders: number; // 待处理订单数
activeOrders: number; // 进行中订单数
completedOrders: number; // 已完成订单数
timestamp: number; // 数据时间戳
}
/**
* 统计服务类
* 提供系统统计数据的获取和缓存功能
*/
class StatisticsService {
// 数据缓存
private cache: StatisticsData | null = null;
// 缓存超时时间5分钟
private readonly cacheTimeout = 5 * 60 * 1000;
/**
* 获取系统统计数据
* 采用一个API请求获取三个统计数据后续操作客户端自行统计
* @param forceRefresh 是否强制刷新,不使用缓存
*/
async getSystemStats(forceRefresh: boolean = false): Promise<StatisticsData> {
// 检查缓存是否有效,且不强制刷新
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获取系统统计数据
*/
private async getSystemStatsFromAPI(): Promise<StatisticsData> {
try {
// 调用系统统计API
const response = await apiService.getSystemStats();
console.log('API返回的统计数据:', response);
// API返回的数据结构是 { data: { ... }, success: true }
// 需要提取data字段中的数据
const stats = (response as any).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(): void {
this.cache = null;
console.log('统计数据缓存已清除');
}
/**
* 获取缓存状态
*/
getCacheStatus(): { hasCache: boolean; isExpired: boolean; age: number } {
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: 'employee' | 'order' | 'warehouse', count: number): void {
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}`);
}
}
/**
* 统计服务单例实例
* 导出供应用程序全局使用
*/
export default new StatisticsService();

View File

@@ -4,6 +4,7 @@
import { UserInfo, EmployeeInfo } from '../types';
import { Role } from '../utils/roleUtils';
import apiService from './apiService';
import { API_BASE_URL } from './apiService';
/**
* 用户服务类
@@ -174,8 +175,14 @@ class UserService {
//TODO: 登录成功的基础数据:服务器下发的公共游客可看的数据
const result = await apiService.ServerLogin(code);
// 确保用户信息包含头像URL使用avatarPath拼接服务器地址最后使用默认头像
const userInfoWithAvatar = {
...result.user,
avatarUrl: result.user.avatarPath ? `${API_BASE_URL}${result.user.avatarPath}` : '/images/truck.png'
};
// 保存到本地存储
wx.setStorageSync('userInfo', result.user);
wx.setStorageSync('userInfo', userInfoWithAvatar);
wx.setStorageSync('token', result.token);
wx.setStorageSync('openid', result.openid);
wx.setStorageSync('session_key', result.session_key);
@@ -188,7 +195,7 @@ class UserService {
success: true,
openid: result.openid,
token: result.token,
userInfo: result.user
userInfo: userInfoWithAvatar
};
} catch (error) {
console.error('微信登录失败:', error);

View File

@@ -42,44 +42,51 @@ class WarehouseService {
}
/**
* 创建仓库
* 创建仓库
*/
async createWarehouse(warehouseData: Partial<WarehouseInfo>): Promise<WarehouseInfo> {
async createWarehouse(warehouseData: Omit<WarehouseInfo, 'id' | 'createdAt' | 'updatedAt'>): Promise<WarehouseInfo> {
try {
// 模拟API请求延迟
await new Promise(resolve => setTimeout(resolve, 600));
console.log('创建新仓库:', warehouseData);
// 实际应用中这里应该调用后端API
// 这里我们创建一个模拟的仓库对象返回
const newWarehouse: WarehouseInfo = {
id: Date.now(), // 使用时间戳作为临时ID
name: warehouseData.name || '新建仓库',
address: warehouseData.address || '',
contact: warehouseData.contact,
phone: warehouseData.phone,
description: warehouseData.description,
status: 'open',
capacity: warehouseData.capacity || 500,
longitude: warehouseData.longitude || 0,
latitude: warehouseData.latitude || 0
};
return newWarehouse;
const result = await apiService.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: number, warehouseInfo: { name?: string; address?: string; contact?: string; phone?: string; description?: string; capacity?: number; longitude?: number; latitude?: number; status?: 'open' | 'closed' | 'maintenance' }): Promise<WarehouseInfo> {
try {
const result = await apiService.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: number): Promise<boolean> {
try {
// 模拟API请求延迟
await new Promise(resolve => setTimeout(resolve, 400));
console.log(`删除仓库 ${warehouseId}`);
// 实际应用中这里应该调用后端API
return true;
const result = await apiService.deleteWarehouse(warehouseId);
console.log(`删除仓库 ${warehouseId} 结果:`, result);
return result.success;
} catch (error) {
console.error('删除仓库失败:', error);
throw new Error('删除仓库失败');