first commit
This commit is contained in:
286
miniprogram/pages/index/modules/dataModule.ts
Normal file
286
miniprogram/pages/index/modules/dataModule.ts
Normal file
@@ -0,0 +1,286 @@
|
||||
import { UserInfo, Marker } from '../../../types';
|
||||
|
||||
/**
|
||||
* 页面数据管理模块
|
||||
* 负责管理index页面的所有数据状态
|
||||
*/
|
||||
export class DataModule {
|
||||
private pageContext: any;
|
||||
|
||||
constructor(pageContext: any) {
|
||||
this.pageContext = pageContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化页面数据
|
||||
*/
|
||||
public initializeData(): void {
|
||||
this.pageContext.setData({
|
||||
// 地图相关数据
|
||||
longitude: 102.833722,
|
||||
latitude: 24.880095,
|
||||
scale: 13,
|
||||
markers: [] as Marker[],
|
||||
polyline: null,
|
||||
showRoute: false,
|
||||
routeDistance: 0,
|
||||
routeDuration: 0,
|
||||
currentRoute: null,
|
||||
|
||||
// 用户相关数据
|
||||
userInfo: null as UserInfo | null,
|
||||
isLoggedIn: false,
|
||||
showUserPanel: false,
|
||||
|
||||
// 订单相关数据
|
||||
pendingOrders: [] as any[],
|
||||
showOrderPanel: false,
|
||||
currentOrder: null,
|
||||
|
||||
// 货运人员相关数据
|
||||
showDeliveryPersonModal: false,
|
||||
deliveryPersonModalState: 'bottom',
|
||||
currentDeliveryPerson: null,
|
||||
|
||||
// 仓库相关数据
|
||||
showWarehouseModal: false,
|
||||
warehouseModalState: 'bottom',
|
||||
currentWarehouse: null,
|
||||
|
||||
// 面板位置数据
|
||||
currentPanelPosition: { x: 0, y: 0 },
|
||||
|
||||
// 对话框相关数据
|
||||
showNickNameDialog: false,
|
||||
tempNickName: ''
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
*/
|
||||
public updateUserInfo(userInfo: UserInfo | null): void {
|
||||
this.pageContext.setData({
|
||||
userInfo,
|
||||
isLoggedIn: !!userInfo
|
||||
});
|
||||
|
||||
// 更新按钮显示状态
|
||||
if (this.pageContext.updateButtonDisplayStatus) {
|
||||
this.pageContext.updateButtonDisplayStatus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置登录状态
|
||||
*/
|
||||
public setLoginStatus(isLoggedIn: boolean): void {
|
||||
this.pageContext.setData({
|
||||
isLoggedIn
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置地图缩放级别
|
||||
*/
|
||||
public setMapScale(scale: number): void {
|
||||
this.pageContext.setData({
|
||||
scale
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户位置信息
|
||||
*/
|
||||
public updateUserLocation(latitude: number, longitude: number): void {
|
||||
this.pageContext.setData({
|
||||
latitude,
|
||||
longitude
|
||||
});
|
||||
|
||||
// 同时更新地图上的用户标记点
|
||||
this.updateUserMarkerPosition(longitude, latitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户标记点位置
|
||||
*/
|
||||
public updateUserMarkerPosition(longitude: number, latitude: number, userId?: number): void {
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 如果没有指定用户ID,默认使用-1(当前用户)
|
||||
const targetUserId = userId !== undefined ? userId : -1;
|
||||
const markerTitle = targetUserId === -1 ? '用户位置' : `用户${targetUserId}`;
|
||||
|
||||
// 查找用户标记点
|
||||
const userMarkerIndex = markers.findIndex((marker: any) => marker.id === targetUserId);
|
||||
|
||||
if (userMarkerIndex !== -1) {
|
||||
// 更新用户标记点位置
|
||||
const updatedMarkers = [...markers];
|
||||
updatedMarkers[userMarkerIndex] = {
|
||||
...updatedMarkers[userMarkerIndex],
|
||||
latitude,
|
||||
longitude
|
||||
};
|
||||
|
||||
this.updateMarkers(updatedMarkers);
|
||||
} else {
|
||||
// 创建新的用户标记点
|
||||
const newUserMarker = {
|
||||
id: targetUserId,
|
||||
title: markerTitle,
|
||||
longitude: longitude,
|
||||
latitude: latitude,
|
||||
iconPath: '/images/trucks.png',
|
||||
width: 40,
|
||||
height: 40,
|
||||
zIndex: targetUserId === -1 ? 99 : 98 // 当前用户层级更高
|
||||
};
|
||||
|
||||
const updatedMarkers = [...markers, newUserMarker];
|
||||
this.updateMarkers(updatedMarkers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新地图标记点
|
||||
*/
|
||||
public updateMarkers(markers: Marker[]): void {
|
||||
// 验证每个标记点的坐标
|
||||
const validatedMarkers = markers.map((marker, index) => {
|
||||
// 检查经纬度是否为有效数字
|
||||
if (isNaN(marker.longitude) || isNaN(marker.latitude)) {
|
||||
// 为无效坐标设置默认值
|
||||
return {
|
||||
...marker,
|
||||
longitude: 102.833722, // 默认经度
|
||||
latitude: 24.880095 // 默认纬度
|
||||
};
|
||||
} else {
|
||||
return marker;
|
||||
}
|
||||
});
|
||||
|
||||
// 执行更新
|
||||
this.pageContext.setData({ markers: validatedMarkers });
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新待分配订单列表
|
||||
*/
|
||||
public updatePendingOrders(orders: any[]): void {
|
||||
this.pageContext.setData({ pendingOrders: orders });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中订单
|
||||
*/
|
||||
public setCurrentOrder(order: any): void {
|
||||
this.pageContext.setData({ currentOrder: order });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中货运人员
|
||||
*/
|
||||
public setCurrentDeliveryPerson(person: any): void {
|
||||
this.pageContext.setData({ currentDeliveryPerson: person });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中仓库
|
||||
*/
|
||||
public setCurrentWarehouse(warehouse: any): void {
|
||||
this.pageContext.setData({ currentWarehouse: warehouse });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置面板位置
|
||||
*/
|
||||
public setPanelPosition(position: { x: number; y: number }): void {
|
||||
this.pageContext.setData({ currentPanelPosition: position });
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示/隐藏用户面板
|
||||
*/
|
||||
public toggleUserPanel(show: boolean): void {
|
||||
this.pageContext.setData({ showUserPanel: show });
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示/隐藏订单面板
|
||||
*/
|
||||
public toggleOrderPanel(show: boolean): void {
|
||||
this.pageContext.setData({ showOrderPanel: show });
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示/隐藏仓库弹窗
|
||||
*/
|
||||
public toggleWarehouseModal(show: boolean, state: 'bottom' | 'full' = 'bottom'): void {
|
||||
this.pageContext.setData({
|
||||
showWarehouseModal: show,
|
||||
warehouseModalState: state
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示/隐藏货运人员弹窗
|
||||
*/
|
||||
public toggleDeliveryPersonModal(show: boolean, state: 'bottom' | 'full' = 'bottom'): void {
|
||||
this.pageContext.setData({
|
||||
showDeliveryPersonModal: show,
|
||||
deliveryPersonModalState: state
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示/隐藏昵称修改对话框
|
||||
*/
|
||||
public toggleNickNameDialog(show: boolean, tempNickName: string = ''): void {
|
||||
this.pageContext.setData({
|
||||
showNickNameDialog: show,
|
||||
tempNickName
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新路线信息
|
||||
*/
|
||||
public updateRouteInfo(polyline: any, distance: number, duration: number): void {
|
||||
this.pageContext.setData({
|
||||
polyline,
|
||||
routeDistance: distance,
|
||||
routeDuration: duration,
|
||||
showRoute: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除路线信息
|
||||
*/
|
||||
public clearRouteInfo(): void {
|
||||
this.pageContext.setData({
|
||||
polyline: null,
|
||||
showRoute: false,
|
||||
routeDistance: 0,
|
||||
routeDuration: 0,
|
||||
currentRoute: null
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前数据状态
|
||||
*/
|
||||
public getData(): any {
|
||||
return this.pageContext.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置所有数据到初始状态
|
||||
*/
|
||||
public resetAllData(): void {
|
||||
this.initializeData();
|
||||
}
|
||||
}
|
||||
326
miniprogram/pages/index/modules/deliveryPersonModule.ts
Normal file
326
miniprogram/pages/index/modules/deliveryPersonModule.ts
Normal file
@@ -0,0 +1,326 @@
|
||||
// 货运人员模块 - 处理货运人员管理、位置跟踪、交互
|
||||
import deliveryPersonService from '../../../services/deliveryPersonService';
|
||||
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import { DataModule } from './dataModule';
|
||||
|
||||
export class DeliveryPersonModule {
|
||||
private pageContext: any;
|
||||
private dataModule: DataModule;
|
||||
|
||||
constructor(pageContext: any, dataModule: DataModule) {
|
||||
this.pageContext = pageContext;
|
||||
this.dataModule = dataModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载货运人员数据
|
||||
*/
|
||||
async loadDeliveryPersons(): Promise<void> {
|
||||
try {
|
||||
const deliveryPersons = await deliveryPersonService.getDeliveryPersons();
|
||||
|
||||
// 更新地图标记点
|
||||
this.updateDeliveryPersonMarkers(deliveryPersons);
|
||||
|
||||
console.log('货运人员数据加载完成,数量:', deliveryPersons.length);
|
||||
} catch (error) {
|
||||
console.error('加载货运人员数据失败:', error);
|
||||
showToast('加载货运人员数据失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新货运人员位置
|
||||
*/
|
||||
async updateDeliveryPersonLocation(personId: number, location: { longitude: number, latitude: number }): Promise<void> {
|
||||
try {
|
||||
await deliveryPersonService.updateDeliveryPersonLocation(personId, location);
|
||||
|
||||
console.log(`货运人员 ${personId} 位置更新:`, location);
|
||||
|
||||
// 重新加载货运人员数据
|
||||
await this.loadDeliveryPersons();
|
||||
|
||||
} catch (error) {
|
||||
console.error('更新货运人员位置失败:', error);
|
||||
showToast('更新位置失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 开始实时位置跟踪
|
||||
*/
|
||||
async startRealTimeTracking(): Promise<void> {
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (!userInfo || !userInfo.id) {
|
||||
throw new Error('用户信息获取失败');
|
||||
}
|
||||
|
||||
// 使用新的WebSocket接口订阅位置更新
|
||||
await deliveryPersonService.subscribeToRealTimeLocations(userInfo.id);
|
||||
|
||||
// 设置位置更新回调
|
||||
deliveryPersonService.subscribeToRealTimeLocations(this.handleRealTimeLocationUpdate.bind(this));
|
||||
|
||||
showToast('开始实时跟踪');
|
||||
console.log('开始实时跟踪货运人员位置');
|
||||
} catch (error) {
|
||||
console.error('开始实时跟踪失败:', error);
|
||||
showToast('开始实时跟踪失败');
|
||||
}
|
||||
}
|
||||
|
||||
handleRealTimeLocationUpdate(location: any): void {
|
||||
console.log('收到实时位置更新:', location);
|
||||
// 这里可以添加更新地图标记点的逻辑
|
||||
// 根据位置更新信息更新对应的货运人员标记点
|
||||
if (location && location.deliveryPersonId) {
|
||||
this.updateSingleDeliveryPersonMarker(location);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个货运人员标记点
|
||||
*/
|
||||
private updateSingleDeliveryPersonMarker(location: any): void {
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 查找并更新对应的货运人员标记点
|
||||
const updatedMarkers = markers.map((marker: any) => {
|
||||
if (marker.type === 'delivery_person' && marker.data && marker.data.id === location.deliveryPersonId) {
|
||||
// 更新标记点位置
|
||||
return {
|
||||
...marker,
|
||||
longitude: location.longitude,
|
||||
latitude: location.latitude,
|
||||
data: {
|
||||
...marker.data,
|
||||
currentLocation: {
|
||||
longitude: location.longitude,
|
||||
latitude: location.latitude
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return marker;
|
||||
});
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
this.dataModule.updateMarkers(updatedMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止实时跟踪货运人员位置
|
||||
*/
|
||||
async stopRealTimeTracking(): Promise<void> {
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (!userInfo || !userInfo.id) {
|
||||
throw new Error('用户信息获取失败');
|
||||
}
|
||||
|
||||
// 使用新的WebSocket接口取消订阅
|
||||
await deliveryPersonService.unsubscribeFromRealTimeLocations();
|
||||
|
||||
showToast('已停止实时跟踪');
|
||||
console.log('停止实时跟踪货运人员位置');
|
||||
} catch (error) {
|
||||
console.error('停止实时跟踪失败:', error);
|
||||
showToast('停止实时跟踪失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新货运人员标记点
|
||||
*/
|
||||
private updateDeliveryPersonMarkers(deliveryPersons: any[]): void {
|
||||
console.log(`[DELIVERY PERSON MODULE] 开始更新货运人员标记点,货运人员总数: ${deliveryPersons.length}`);
|
||||
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 移除现有的货运人员标记点
|
||||
const filteredMarkers = markers.filter((marker: any) => marker.type !== 'delivery_person');
|
||||
console.log(`[DELIVERY PERSON MODULE] 移除现有货运人员标记点后,剩余标记点数量: ${filteredMarkers.length}`);
|
||||
|
||||
// 添加新的货运人员标记点
|
||||
const deliveryPersonMarkers = deliveryPersons.map((person, index) => {
|
||||
// 验证货运人员坐标是否有效
|
||||
// 注意:坐标信息嵌套在currentLocation对象中
|
||||
let validLongitude = person.currentLocation?.longitude;
|
||||
let validLatitude = person.currentLocation?.latitude;
|
||||
|
||||
if (isNaN(validLongitude) || isNaN(validLatitude)) {
|
||||
console.error(`[DELIVERY PERSON MODULE] 货运人员${index} (ID: ${person.id}) 坐标无效: (${validLongitude}, ${validLatitude}),使用默认坐标`);
|
||||
validLongitude = 102.833722; // 默认经度
|
||||
validLatitude = 24.880095; // 默认纬度
|
||||
} else {
|
||||
console.log(`[DELIVERY PERSON MODULE] 货运人员${index} (ID: ${person.id}) 坐标有效: (${validLongitude}, ${validLatitude})`);
|
||||
}
|
||||
|
||||
const iconPath = this.getDeliveryPersonIcon(person.status);
|
||||
|
||||
return {
|
||||
id: 2000 + index, // 货运人员标记点ID从2000开始
|
||||
longitude: validLongitude,
|
||||
latitude: validLatitude,
|
||||
iconPath: iconPath,
|
||||
width: 26,
|
||||
height: 26,
|
||||
zIndex: 20,
|
||||
type: 'delivery_person',
|
||||
data: person
|
||||
};
|
||||
});
|
||||
|
||||
console.log(`[DELIVERY PERSON MODULE] 生成新货运人员标记点数量: ${deliveryPersonMarkers.length}`);
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
const allMarkers = [...filteredMarkers, ...deliveryPersonMarkers];
|
||||
console.log(`[DELIVERY PERSON MODULE] 准备更新所有标记点,总数: ${allMarkers.length}`);
|
||||
this.dataModule.updateMarkers(allMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员状态对应的图标
|
||||
*/
|
||||
private getDeliveryPersonIcon(status: string): string {
|
||||
console.log(`获取货运人员图标,状态: ${status}`);
|
||||
|
||||
// 根据报错信息,直接使用已知存在的备用图片路径
|
||||
// 实际项目中,应确保相关图片资源正确放置在指定路径
|
||||
const fallbackIconPath = '/images/trucks.png';
|
||||
|
||||
// 根据不同状态使用不同的图片路径
|
||||
let iconPath = '';
|
||||
|
||||
switch (status) {
|
||||
case 'idle':
|
||||
// 为避免图片加载失败,暂时使用备用图片
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(idle状态)');
|
||||
break;
|
||||
case 'busy':
|
||||
// 为避免图片加载失败,暂时使用备用图片
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(busy状态)');
|
||||
break;
|
||||
case 'offline':
|
||||
// 为避免图片加载失败,暂时使用备用图片
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(offline状态)');
|
||||
break;
|
||||
default:
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(默认状态)');
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(`最终使用图标路径: ${iconPath}`);
|
||||
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示货运人员详情面板
|
||||
*/
|
||||
showDeliveryPersonPanel(person: any, position: { x: number, y: number }): void {
|
||||
// 关闭其他面板
|
||||
this.pageContext.hideAllPanels();
|
||||
|
||||
this.dataModule.setCurrentDeliveryPerson(person);
|
||||
this.dataModule.setPanelPosition(position);
|
||||
this.dataModule.toggleDeliveryPersonModal(true, 'bottom');
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏货运人员详情面板
|
||||
*/
|
||||
hideDeliveryPersonPanel(): void {
|
||||
this.dataModule.toggleDeliveryPersonModal(false);
|
||||
this.dataModule.setCurrentDeliveryPerson(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开货运人员详情面板
|
||||
*/
|
||||
expandDeliveryPersonPanel(): void {
|
||||
this.dataModule.toggleDeliveryPersonModal(true, 'full');
|
||||
}
|
||||
|
||||
/**
|
||||
* 收起货运人员详情面板
|
||||
*/
|
||||
collapseDeliveryPersonPanel(): void {
|
||||
this.dataModule.toggleDeliveryPersonModal(true, 'bottom');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理货运人员标记点点击
|
||||
*/
|
||||
onDeliveryPersonMarkerClick(person: any, position: { x: number, y: number }): void {
|
||||
console.log('货运人员被点击:', person);
|
||||
|
||||
// 显示货运人员详情面板
|
||||
this.showDeliveryPersonPanel(person, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员状态文本
|
||||
*/
|
||||
getDeliveryPersonStatusText(status: string): string {
|
||||
const statusMap: Record<string, string> = {
|
||||
'idle': '空闲',
|
||||
'busy': '忙碌',
|
||||
'offline': '离线'
|
||||
};
|
||||
return statusMap[status] || status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员状态颜色
|
||||
*/
|
||||
getDeliveryPersonStatusColor(status: string): string {
|
||||
switch (status) {
|
||||
case 'idle':
|
||||
return '#52c41a'; // 绿色
|
||||
case 'busy':
|
||||
return '#faad14'; // 橙色
|
||||
case 'offline':
|
||||
return '#d9d9d9'; // 灰色
|
||||
default:
|
||||
return '#d9d9d9'; // 灰色
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员当前订单信息
|
||||
*/
|
||||
getCurrentOrderInfo(person: any): string {
|
||||
if (!person.currentOrder) {
|
||||
return '暂无订单';
|
||||
}
|
||||
|
||||
const order = person.currentOrder;
|
||||
return `订单 #${order.id} - ${this.getOrderStatusText(order.status)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单状态文本
|
||||
*/
|
||||
private getOrderStatusText(status: string): string {
|
||||
const statusMap: Record<string, string> = {
|
||||
'pending': '未分配',
|
||||
'assigned': '已分配',
|
||||
'in_transit': '配送中',
|
||||
'delivered': '已完成',
|
||||
'cancelled': '已取消'
|
||||
};
|
||||
return statusMap[status] || status;
|
||||
}
|
||||
}
|
||||
455
miniprogram/pages/index/modules/loginModule.ts
Normal file
455
miniprogram/pages/index/modules/loginModule.ts
Normal file
@@ -0,0 +1,455 @@
|
||||
// 登录模块 - 处理用户登录、授权、用户信息管理
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import { UserInfo } from '../../../types';
|
||||
import userService from '../../../services/userService';
|
||||
import locationTrackingService from '../../../services/locationTrackingService';
|
||||
import { DataModule } from './dataModule';
|
||||
|
||||
export class LoginModule {
|
||||
private dataModule: DataModule;
|
||||
private pageContext: any;
|
||||
|
||||
constructor(pageContext: any, dataModule: DataModule) {
|
||||
this.pageContext = pageContext;
|
||||
this.dataModule = dataModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理用户信息
|
||||
*/
|
||||
public async processUserInfo(userInfo: UserInfo): Promise<UserInfo> {
|
||||
// 直接返回用户信息,不进行额外处理
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功后更新页面状态
|
||||
*/
|
||||
public updatePageAfterLogin(userInfo: UserInfo): void {
|
||||
this.dataModule.updateUserInfo(userInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查登录状态
|
||||
*/
|
||||
public checkLoginStatus(): boolean {
|
||||
const globalUserInfo = userService.getGlobalUserInfo();
|
||||
|
||||
if (globalUserInfo) {
|
||||
this.dataModule.updateUserInfo(globalUserInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户退出登录
|
||||
*/
|
||||
public async logout(): Promise<void> {
|
||||
try {
|
||||
// 停止位置追踪服务
|
||||
try {
|
||||
await locationTrackingService.stopTracking();
|
||||
console.log('位置追踪服务已停止');
|
||||
} catch (trackingError) {
|
||||
console.warn('停止位置追踪失败,但不影响退出登录:', trackingError);
|
||||
}
|
||||
|
||||
// 注意:这里不调用userService.logout(),因为服务器端的logout接口会删除token
|
||||
// 而用户只是签退不接单,不是完全退出应用,需要保持token有效
|
||||
console.log('用户已退出登录(本地签退,保持token有效)');
|
||||
showToast('已退出登录');
|
||||
} catch (error) {
|
||||
console.error('退出登录失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示手动登录模态框:如果静默登录失败后,让用户尝试手动登录
|
||||
*/
|
||||
public async showManualLoginModal(): Promise<boolean> {
|
||||
console.log('显示手动登录模态框');
|
||||
return new Promise((resolve) => {
|
||||
wx.showModal({
|
||||
title: '手动登录',
|
||||
content: '静默登录失败,请手动登录以使用完整功能',
|
||||
confirmText: '手动登录',
|
||||
cancelText: '暂不',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
// 用户点击确定,执行手动登录
|
||||
console.log('用户选择手动登录');
|
||||
const success = await this.performLogin();
|
||||
if (!success) {
|
||||
// 登录失败,再次提供选项
|
||||
this.handleLoginFailure(resolve);
|
||||
} else {
|
||||
resolve(success);
|
||||
}
|
||||
} else {
|
||||
// 用户取消登录,显示关闭小程序选项
|
||||
console.log('用户选择暂不登录');
|
||||
this.showCloseAppOption(resolve);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行登录流程 - 调用userService的登录方法
|
||||
* 静默登录失败后,只专注于登录本身,不涉及注册、签到等复杂逻辑
|
||||
*/
|
||||
private async performLogin(): Promise<boolean> {
|
||||
try {
|
||||
// 执行微信登录
|
||||
const result = await userService.wxLogin();
|
||||
if (result.success && result.userInfo) {
|
||||
// 登录成功,更新页面状态
|
||||
this.updatePageAfterLogin(result.userInfo);
|
||||
console.log('手动登录成功');
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log('手动登录失败');
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('执行登录流程失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登录失败的情况
|
||||
*/
|
||||
public async handleLoginFailure(resolve: (value: boolean) => void) {
|
||||
console.log('登录失败,显示重试选项');
|
||||
wx.showModal({
|
||||
title: '登录失败',
|
||||
content: '登录遇到问题,是否重试?',
|
||||
confirmText: '重新登录',
|
||||
cancelText: '取消并关闭',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
console.log('用户选择重新登录');
|
||||
const success = await this.performLogin();
|
||||
if (!success) {
|
||||
// 再次登录失败,递归调用以避免嵌套过深
|
||||
this.handleLoginFailure(resolve);
|
||||
} else {
|
||||
resolve(success);
|
||||
}
|
||||
} else {
|
||||
console.log('用户选择取消并关闭小程序');
|
||||
wx.showToast({
|
||||
title: '即将退出小程序',
|
||||
icon: 'none',
|
||||
duration: 1500,
|
||||
complete: () => {
|
||||
setTimeout(() => {
|
||||
// 使用类型断言解决类型问题
|
||||
(wx as any).exitMiniProgram();
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示关闭小程序选项
|
||||
*/
|
||||
public showCloseAppOption(resolve: (value: boolean) => void) {
|
||||
console.log('显示关闭小程序选项');
|
||||
wx.showModal({
|
||||
title: '确认退出',
|
||||
content: '不登录将无法使用完整功能,是否退出小程序?',
|
||||
confirmText: '退出小程序',
|
||||
cancelText: '留在页面',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
console.log('用户确认退出小程序');
|
||||
// 使用类型断言解决类型问题
|
||||
(wx as any).exitMiniProgram();
|
||||
resolve(false);
|
||||
} else {
|
||||
console.log('用户选择留在页面');
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理签到流程
|
||||
*/
|
||||
public async handleSignIn(): Promise<boolean> {
|
||||
try {
|
||||
// 显示加载中提示
|
||||
wx.showLoading({
|
||||
title: '签到中...',
|
||||
});
|
||||
|
||||
// 调用实际的签到接口
|
||||
const signInResult = await userService.signIn();
|
||||
|
||||
wx.hideLoading();
|
||||
|
||||
if (signInResult.success) {
|
||||
console.log('签到成功:', signInResult);
|
||||
wx.showToast({
|
||||
title: '签到成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
|
||||
// 更新用户信息
|
||||
if (signInResult.employeeInfo) {
|
||||
// 将员工信息合并到用户信息中
|
||||
const app = getApp<any>();
|
||||
if (app.globalData.userInfo) {
|
||||
app.globalData.userInfo = {
|
||||
...app.globalData.userInfo,
|
||||
name: signInResult.employeeInfo.name,
|
||||
phone: signInResult.employeeInfo.phone
|
||||
};
|
||||
this.updatePageAfterLogin(app.globalData.userInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置用户状态为已签到
|
||||
if (this.pageContext && this.pageContext.setData) {
|
||||
this.pageContext.setData({
|
||||
'authStatus.userStatus': 'signed_in'
|
||||
});
|
||||
|
||||
// 更新按钮显示状态
|
||||
if (this.pageContext.updateButtonDisplayStatus) {
|
||||
this.pageContext.updateButtonDisplayStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// 启动位置追踪服务
|
||||
try {
|
||||
await locationTrackingService.startTrackingAfterSignIn();
|
||||
console.log('位置追踪服务已启动');
|
||||
|
||||
// 订阅位置更新回调,采用统一方式更新所有用户位置
|
||||
locationTrackingService.subscribeToLocationUpdates((onlineUsers) => {
|
||||
console.log('🚚 位置更新回调 - 在线用户列表已更新,用户数量:', onlineUsers.length);
|
||||
|
||||
// 统一更新所有在线用户的位置标记点
|
||||
onlineUsers.forEach(user => {
|
||||
if (user.lastLocation) {
|
||||
console.log(`📍 更新用户 ${user.userId} 标记点位置:`, user.lastLocation);
|
||||
// 统一调用数据模块更新用户标记点位置
|
||||
this.dataModule.updateUserMarkerPosition(
|
||||
user.lastLocation.longitude,
|
||||
user.lastLocation.latitude,
|
||||
user.userId
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
} catch (trackingError) {
|
||||
console.warn('启动位置追踪失败,但不影响签到:', trackingError);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
console.warn('签到失败:', signInResult.message);
|
||||
wx.showToast({
|
||||
title: signInResult.message || '签到失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('签到过程中发生错误:', error);
|
||||
wx.hideLoading();
|
||||
wx.showToast({
|
||||
title: '签到失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理授权登录流程
|
||||
*/
|
||||
public async handleAuthLogin(): Promise<boolean> {
|
||||
try {
|
||||
const success = await this.showManualLoginModal();
|
||||
|
||||
if (success) {
|
||||
console.log('手动登录成功');
|
||||
return true;
|
||||
} else {
|
||||
console.log('用户取消手动登录');
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('手动登录过程中发生错误:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否为游客(已登录但信息不完整)
|
||||
*/
|
||||
public isTourist(): boolean {
|
||||
const app = getApp<any>();
|
||||
// 游客定义:已登录但没有完善基本信息(姓名和电话)的用户
|
||||
if (app.globalData.isLoggedIn && app.globalData.userInfo) {
|
||||
const userInfo = app.globalData.userInfo;
|
||||
return !userInfo.name || !userInfo.phone;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算是否显示签到按钮(基于用户状态和角色)
|
||||
*/
|
||||
public shouldShowSignInButton(): boolean {
|
||||
// 从页面上下文中获取数据
|
||||
const pageData = this.dataModule.getData();
|
||||
const authStatus = pageData.authStatus || {};
|
||||
const userInfo = pageData.userInfo;
|
||||
|
||||
// 显示条件:已获取微信code、用户状态不是已签到、且用户不是游客(已注册用户)
|
||||
const result = (
|
||||
authStatus.hasWxCode &&
|
||||
(authStatus.userStatus === 'registered' || authStatus.userStatus === 'signed_out') &&
|
||||
userInfo !== null &&
|
||||
userInfo.role !== 'GUEST'
|
||||
);
|
||||
|
||||
// 调试信息:打印不满足条件的原因
|
||||
if (!result) {
|
||||
console.log('签到按钮不显示原因:');
|
||||
if (!authStatus.hasWxCode) console.log(' - 未获取微信code');
|
||||
if (authStatus.userStatus === 'signed_in') console.log(' - 用户状态为已签到');
|
||||
if (authStatus.userStatus === 'unregistered') console.log(' - 用户状态为未注册');
|
||||
if (userInfo === null) console.log(' - 用户信息为空');
|
||||
if (userInfo && userInfo.role === 'GUEST') console.log(' - 用户角色为游客');
|
||||
console.log('当前状态:', {
|
||||
hasWxCode: authStatus.hasWxCode,
|
||||
userStatus: authStatus.userStatus,
|
||||
userInfo: userInfo ? { role: userInfo.role } : null
|
||||
});
|
||||
} else {
|
||||
console.log('签到按钮显示条件满足');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算是否显示注册按钮(基于用户状态和角色)
|
||||
*/
|
||||
public shouldShowRegisterButton(): boolean {
|
||||
// 从页面上下文中获取数据
|
||||
const pageData = this.dataModule.getData();
|
||||
const authStatus = pageData.authStatus || {};
|
||||
const userInfo = pageData.userInfo;
|
||||
|
||||
// 显示条件:已获取微信code、用户状态为未注册、且用户是游客
|
||||
const result = (
|
||||
authStatus.hasWxCode &&
|
||||
authStatus.userStatus === 'unregistered' &&
|
||||
userInfo !== null &&
|
||||
userInfo.role === 'GUEST'
|
||||
);
|
||||
|
||||
// 调试信息:打印不满足条件的原因
|
||||
if (!result) {
|
||||
console.log('注册按钮不显示原因:');
|
||||
if (!authStatus.hasWxCode) console.log(' - 未获取微信code');
|
||||
if (authStatus.userStatus !== 'unregistered') console.log(` - 用户状态为${authStatus.userStatus},不是未注册`);
|
||||
if (userInfo === null) console.log(' - 用户信息为空');
|
||||
if (userInfo && userInfo.role !== 'GUEST') console.log(` - 用户角色为${userInfo.role},不是游客`);
|
||||
console.log('当前状态:', {
|
||||
hasWxCode: authStatus.hasWxCode,
|
||||
userStatus: authStatus.userStatus,
|
||||
userInfo: userInfo ? { role: userInfo.role } : null
|
||||
});
|
||||
} else {
|
||||
console.log('注册按钮显示条件满足');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户信息确定用户状态(从服务器获取真实状态)
|
||||
*/
|
||||
public async determineUserStatus(userInfo: any): Promise<'registered' | 'unregistered' | 'signed_in' | 'signed_out'> {
|
||||
if (!userInfo) return 'signed_out';
|
||||
|
||||
try {
|
||||
// 从服务器获取用户真实状态
|
||||
const serverStatus = await this.getUserStatusFromServer();
|
||||
|
||||
if (serverStatus) {
|
||||
console.log('从服务器获取的用户状态:', serverStatus);
|
||||
return serverStatus;
|
||||
}
|
||||
|
||||
// 如果服务器获取失败,使用本地逻辑作为降级方案
|
||||
console.warn('服务器状态获取失败,使用本地逻辑判断');
|
||||
const isRegistered = userInfo.name && userInfo.phone;
|
||||
return isRegistered ? 'registered' : 'unregistered';
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取用户状态失败:', error);
|
||||
// 网络错误时使用本地逻辑
|
||||
const isRegistered = userInfo.name && userInfo.phone;
|
||||
return isRegistered ? 'registered' : 'unregistered';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从服务器获取用户签到状态
|
||||
*/
|
||||
private async getUserStatusFromServer(): Promise<'registered' | 'unregistered' | 'signed_in' | 'signed_out' | null> {
|
||||
try {
|
||||
// 调用服务器接口获取用户状态
|
||||
const response = await userService.getUserStatus();
|
||||
|
||||
// 如果返回null,表示服务器接口不存在
|
||||
if (response === null) {
|
||||
console.log('服务器状态接口不存在,跳过服务器状态获取');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response && response.status) {
|
||||
// 根据服务器返回的状态映射到前端状态
|
||||
switch (response.status) {
|
||||
case 'signed_in':
|
||||
case 'online':
|
||||
return 'signed_in';
|
||||
case 'signed_out':
|
||||
case 'offline':
|
||||
return 'signed_out';
|
||||
case 'registered':
|
||||
return 'registered';
|
||||
case 'unregistered':
|
||||
return 'unregistered';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('获取服务器状态失败:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
308
miniprogram/pages/index/modules/mainPageModule.ts
Normal file
308
miniprogram/pages/index/modules/mainPageModule.ts
Normal file
@@ -0,0 +1,308 @@
|
||||
// 主页面模块 - 协调各个子模块,处理页面生命周期和事件分发
|
||||
import { LoginModule } from './loginModule';
|
||||
import { MapModule } from './mapModule';
|
||||
import { OrderModule } from './orderModule';
|
||||
import { WarehouseModule } from './warehouseModule';
|
||||
import { DeliveryPersonModule } from './deliveryPersonModule';
|
||||
import { DataModule } from './dataModule';
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
|
||||
export class MainPageModule {
|
||||
private pageContext: any;
|
||||
private loginModule: LoginModule;
|
||||
private mapModule: MapModule;
|
||||
private orderModule: OrderModule;
|
||||
private warehouseModule: WarehouseModule;
|
||||
private deliveryPersonModule: DeliveryPersonModule;
|
||||
private dataModule: DataModule;
|
||||
|
||||
constructor(pageContext: any) {
|
||||
this.pageContext = pageContext;
|
||||
|
||||
// 初始化各个子模块
|
||||
this.dataModule = new DataModule(pageContext);
|
||||
this.loginModule = new LoginModule(pageContext, this.dataModule);
|
||||
this.mapModule = new MapModule(pageContext, this.dataModule);
|
||||
this.orderModule = new OrderModule(pageContext, this.dataModule);
|
||||
this.warehouseModule = new WarehouseModule(pageContext, this.dataModule);
|
||||
this.deliveryPersonModule = new DeliveryPersonModule(pageContext, this.dataModule);
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面初始化
|
||||
*/
|
||||
async onLoad(): Promise<void> {
|
||||
console.log('主页面模块初始化');
|
||||
|
||||
try {
|
||||
// 初始化应用
|
||||
await this.initApp();
|
||||
|
||||
// 加载地图数据
|
||||
await this.loadAllData();
|
||||
|
||||
console.log('主页面初始化完成');
|
||||
} catch (error) {
|
||||
console.error('页面初始化失败:', error);
|
||||
showToast('页面初始化失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面显示
|
||||
*/
|
||||
onShow(): void {
|
||||
console.log('主页面显示');
|
||||
|
||||
// 检查是否需要刷新数据
|
||||
this.refreshDataIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化应用
|
||||
*/
|
||||
private async initApp(): Promise<void> {
|
||||
// 初始化数据
|
||||
this.dataModule.initializeData();
|
||||
console.log('应用初始化');
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载所有数据
|
||||
*/
|
||||
private async loadAllData(): Promise<void> {
|
||||
try {
|
||||
// 初始化地图
|
||||
await this.mapModule.initMap();
|
||||
|
||||
// 加载公开数据(不需要登录)
|
||||
await this.loadPublicData();
|
||||
|
||||
// 检查是否已登录,只有已登录用户才能加载业务数据
|
||||
const app = getApp<any>();
|
||||
if (app.globalData.isLoggedIn) {
|
||||
await this.loadBusinessData();
|
||||
} else {
|
||||
console.log('用户未登录,不加载业务数据');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
showToast('数据加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载公开数据(不需要登录)
|
||||
*/
|
||||
private async loadPublicData(): Promise<void> {
|
||||
console.log('加载公开数据');
|
||||
|
||||
try {
|
||||
// 加载仓库数据(公开数据,不需要登录)
|
||||
await this.warehouseModule.loadWarehouses();
|
||||
|
||||
console.log('公开数据加载完成');
|
||||
} catch (error) {
|
||||
console.error('加载公开数据失败:', error);
|
||||
// 公开数据加载失败不影响主要功能,只记录日志
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载业务数据
|
||||
*/
|
||||
private async loadBusinessData(): Promise<void> {
|
||||
console.log('加载业务数据');
|
||||
|
||||
try {
|
||||
// 并行加载各种业务数据(需要登录)
|
||||
await Promise.all([
|
||||
this.orderModule.loadPendingOrders(),
|
||||
this.deliveryPersonModule.loadDeliveryPersons()
|
||||
]);
|
||||
|
||||
console.log('所有业务数据加载完成');
|
||||
} catch (error) {
|
||||
console.error('加载业务数据失败:', error);
|
||||
showToast('业务数据加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否需要刷新数据
|
||||
*/
|
||||
private refreshDataIfNeeded(): void {
|
||||
// 这里可以添加数据刷新逻辑
|
||||
// 例如:检查上次刷新时间,如果超过一定时间则重新加载数据
|
||||
console.log('检查数据刷新');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登出
|
||||
*/
|
||||
onLogout(): void {
|
||||
console.log('用户登出');
|
||||
|
||||
// 清除业务数据
|
||||
this.clearBusinessData();
|
||||
|
||||
// 重置用户标记点图标
|
||||
this.resetUserMarker();
|
||||
|
||||
showToast('已登出');
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除业务数据
|
||||
*/
|
||||
private clearBusinessData(): void {
|
||||
this.dataModule.updatePendingOrders([]);
|
||||
|
||||
const filteredMarkers = this.pageContext.data.markers.filter((marker: any) =>
|
||||
marker.type !== 'warehouse' && marker.type !== 'delivery_person'
|
||||
);
|
||||
this.dataModule.updateMarkers(filteredMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户标记点
|
||||
*/
|
||||
private resetUserMarker(): void {
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
const updatedMarkers = markers.map((marker: any) => {
|
||||
if (marker.id === -1) {
|
||||
return {
|
||||
...marker,
|
||||
iconPath: '/images/trucks.png'
|
||||
};
|
||||
}
|
||||
return marker;
|
||||
});
|
||||
|
||||
this.dataModule.updateMarkers(updatedMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏所有面板
|
||||
*/
|
||||
hideAllPanels(): void {
|
||||
this.dataModule.toggleUserPanel(false);
|
||||
this.dataModule.toggleOrderPanel(false);
|
||||
this.dataModule.toggleWarehouseModal(false);
|
||||
this.dataModule.toggleDeliveryPersonModal(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置标记点状态
|
||||
*/
|
||||
resetMarkers(): void {
|
||||
// 这里可以添加标记点状态重置逻辑
|
||||
console.log('重置标记点状态');
|
||||
}
|
||||
|
||||
/**
|
||||
* 分发地图点击事件
|
||||
*/
|
||||
onMapTap(e: any): void {
|
||||
this.mapModule.onMapTap(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分发标记点点击事件
|
||||
*/
|
||||
onMarkerTap(e: any): void {
|
||||
const markerId = e.markerId;
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 找到被点击的标记点
|
||||
const marker = markers.find((m: any) => m.id === markerId);
|
||||
|
||||
if (!marker) {
|
||||
console.warn('未找到标记点:', markerId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据标记点类型分发到不同的模块
|
||||
switch (marker.type) {
|
||||
case 'warehouse':
|
||||
this.warehouseModule.onWarehouseMarkerClick(marker.data, e);
|
||||
break;
|
||||
case 'delivery_person':
|
||||
this.deliveryPersonModule.onDeliveryPersonMarkerClick(marker.data, e);
|
||||
break;
|
||||
default:
|
||||
this.mapModule.onMarkerTap(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录模块
|
||||
*/
|
||||
getLoginModule(): LoginModule {
|
||||
return this.loginModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地图模块
|
||||
*/
|
||||
getMapModule(): MapModule {
|
||||
return this.mapModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单模块
|
||||
*/
|
||||
getOrderModule(): OrderModule {
|
||||
return this.orderModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库模块
|
||||
*/
|
||||
getWarehouseModule(): WarehouseModule {
|
||||
return this.warehouseModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员模块
|
||||
*/
|
||||
getDeliveryPersonModule(): DeliveryPersonModule {
|
||||
return this.deliveryPersonModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新所有数据
|
||||
*/
|
||||
async refreshAllData(): Promise<void> {
|
||||
console.log('刷新所有数据');
|
||||
|
||||
try {
|
||||
// 刷新公开数据(不需要登录)
|
||||
await this.loadPublicData();
|
||||
|
||||
// 检查是否已登录,只有已登录用户才能刷新业务数据
|
||||
const app = getApp<any>();
|
||||
if (app.globalData.isLoggedIn) {
|
||||
await this.loadBusinessData();
|
||||
showToast('数据刷新成功');
|
||||
} else {
|
||||
console.log('用户未登录,无法刷新业务数据');
|
||||
showToast('公开数据已刷新,请登录以刷新业务数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('刷新数据失败:', error);
|
||||
showToast('刷新数据失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理错误
|
||||
*/
|
||||
handleError(error: any, context: string): void {
|
||||
console.error(`在 ${context} 中发生错误:`, error);
|
||||
showToast(`操作失败: ${context}`);
|
||||
}
|
||||
}
|
||||
226
miniprogram/pages/index/modules/mapModule.ts
Normal file
226
miniprogram/pages/index/modules/mapModule.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
// 地图模块 - 处理地图显示、定位、标记点管理
|
||||
import mapService from '../../../services/mapService';
|
||||
import userService from '../../../services/userService';
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import { Marker } from '../../../types';
|
||||
import { DataModule } from './dataModule';
|
||||
|
||||
export class MapModule {
|
||||
private pageContext: any;
|
||||
private dataModule: DataModule;
|
||||
|
||||
constructor(pageContext: any, dataModule: DataModule) {
|
||||
this.pageContext = pageContext;
|
||||
this.dataModule = dataModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化地图数据
|
||||
*/
|
||||
async initMap(): Promise<void> {
|
||||
try {
|
||||
// 检查并请求位置权限
|
||||
await this.checkAndRequestLocationPermission();
|
||||
|
||||
// 加载地图数据
|
||||
this.loadMapData();
|
||||
|
||||
} catch (error) {
|
||||
console.error('初始化地图失败:', error);
|
||||
showToast('地图初始化失败,请重试');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并请求位置权限
|
||||
*/
|
||||
async checkAndRequestLocationPermission(): Promise<void> {
|
||||
try {
|
||||
// 检查位置权限
|
||||
const hasPermission = await userService.checkLocationPermission();
|
||||
|
||||
if (hasPermission) {
|
||||
// 已授权,开始定位
|
||||
await this.startLocation();
|
||||
} else {
|
||||
// 未授权,请求权限
|
||||
const permissionGranted = await userService.requestLocationPermission();
|
||||
|
||||
if (permissionGranted) {
|
||||
await this.startLocation();
|
||||
} else {
|
||||
// 授权失败,使用默认位置
|
||||
this.setDefaultLocation();
|
||||
showToast('已使用默认位置');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查位置权限失败:', error);
|
||||
this.setDefaultLocation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始定位
|
||||
*/
|
||||
async startLocation(): Promise<void> {
|
||||
try {
|
||||
console.log('[MAP MODULE] 开始获取用户位置...');
|
||||
const location = await mapService.getCurrentLocation();
|
||||
|
||||
console.log('[MAP MODULE] 获取位置成功,原始坐标:', location);
|
||||
console.log('[MAP MODULE] 详细位置信息:');
|
||||
console.log(`- 经度: ${location.longitude}`);
|
||||
console.log(`- 纬度: ${location.latitude}`);
|
||||
console.log(`- 精度: ${location.accuracy}`);
|
||||
console.log(`- 速度: ${location.speed}`);
|
||||
|
||||
// 验证获取的坐标是否有效
|
||||
if (isNaN(location.latitude) || isNaN(location.longitude)) {
|
||||
console.error('[MAP MODULE] 获取的位置坐标无效:', location);
|
||||
this.setDefaultLocation();
|
||||
showToast('获取的位置无效,已使用默认位置');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新数据模块中的位置信息和缩放级别
|
||||
this.dataModule.updateUserLocation(location.latitude, location.longitude);
|
||||
this.dataModule.setMapScale(15); // 定位成功后放大到更详细的级别
|
||||
|
||||
console.log('[MAP MODULE] 定位成功,坐标已更新:', location);
|
||||
} catch (error) {
|
||||
console.error('[MAP MODULE] 定位失败:', error);
|
||||
this.setDefaultLocation();
|
||||
showToast('定位失败,已使用默认位置');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认位置
|
||||
*/
|
||||
setDefaultLocation(): void {
|
||||
const defaultLatitude = 24.880095;
|
||||
const defaultLongitude = 102.833722;
|
||||
|
||||
// 更新数据模块中的位置信息和缩放级别
|
||||
this.dataModule.updateUserLocation(defaultLatitude, defaultLongitude);
|
||||
this.dataModule.setMapScale(13);
|
||||
|
||||
console.log('[MAP MODULE] 默认位置设置完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载地图数据(仓库和货运人员)
|
||||
*/
|
||||
loadMapData(): void {
|
||||
// 这里会调用具体的服务来获取数据
|
||||
// 目前使用模拟数据
|
||||
const markers = this.generateInitialMarkers();
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
this.dataModule.updateMarkers(markers);
|
||||
|
||||
console.log('地图数据加载完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成初始标记点
|
||||
*/
|
||||
private generateInitialMarkers(): Marker[] {
|
||||
// 获取当前坐标
|
||||
const longitude = this.pageContext.data.longitude;
|
||||
const latitude = this.pageContext.data.latitude;
|
||||
|
||||
// 检查坐标是否为有效数字
|
||||
let validLongitude = longitude;
|
||||
let validLatitude = latitude;
|
||||
|
||||
if (isNaN(longitude) || isNaN(latitude)) {
|
||||
console.warn(`无效的坐标值: longitude=${longitude}, latitude=${latitude}, 使用默认坐标`);
|
||||
validLongitude = 102.833722; // 默认经度
|
||||
validLatitude = 24.880095; // 默认纬度
|
||||
|
||||
// 更新页面数据中的坐标
|
||||
this.dataModule.updateUserLocation(validLatitude, validLongitude);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 生成初始标记点
|
||||
return [
|
||||
{
|
||||
id: -1, // 用户位置标记
|
||||
title: '用户位置',
|
||||
longitude: validLongitude,
|
||||
latitude: validLatitude,
|
||||
iconPath: '/images/trucks.png',
|
||||
width: 40,
|
||||
height: 40,
|
||||
zIndex: 99
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户标记图标为用户头像
|
||||
*/
|
||||
updateUserMarkerIcon(): void {
|
||||
const { authStatus, userInfo, markers } = this.pageContext.data;
|
||||
|
||||
if (!authStatus.hasWxCode || !userInfo) {
|
||||
console.warn('未登录或用户信息为空,无法更新头像');
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用默认头像
|
||||
const avatarUrl = '/images/trucks.png';
|
||||
|
||||
const updatedMarkers = markers.map((marker: Marker) => {
|
||||
if (marker.id === -1) {
|
||||
return {
|
||||
...marker,
|
||||
iconPath: avatarUrl
|
||||
};
|
||||
}
|
||||
return marker;
|
||||
});
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
this.dataModule.updateMarkers(updatedMarkers);
|
||||
|
||||
console.log('用户头像已更新');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理地图点击事件
|
||||
*/
|
||||
onMapTap(e: any): void {
|
||||
console.log('地图被点击:', e);
|
||||
// 可以在这里添加地图点击的处理逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理标记点点击事件
|
||||
*/
|
||||
onMarkerTap(e: any): void {
|
||||
const markerId = e.markerId;
|
||||
console.log('标记点被点击:', markerId);
|
||||
|
||||
// 根据标记点ID处理不同的点击逻辑
|
||||
this.handleMarkerClick(markerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理标记点点击
|
||||
*/
|
||||
private handleMarkerClick(markerId: number): void {
|
||||
// 这里可以根据标记点ID进行不同的处理
|
||||
// 例如:显示订单详情、货运人员信息等
|
||||
|
||||
if (markerId === -1) {
|
||||
// 用户位置标记
|
||||
this.pageContext.showUserPanel();
|
||||
}
|
||||
// 可以添加其他标记点的处理逻辑
|
||||
}
|
||||
}
|
||||
252
miniprogram/pages/index/modules/orderModule.ts
Normal file
252
miniprogram/pages/index/modules/orderModule.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
import orderService from '../../../services/orderService';
|
||||
import { Order } from '../../../types';
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import { DataModule } from './dataModule';
|
||||
|
||||
export class OrderModule {
|
||||
private pageContext: any;
|
||||
private dataModule: DataModule;
|
||||
|
||||
constructor(pageContext: any, dataModule: DataModule) {
|
||||
this.pageContext = pageContext;
|
||||
this.dataModule = dataModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载待处理订单
|
||||
*/
|
||||
async loadPendingOrders() {
|
||||
try {
|
||||
this.pageContext.setData({
|
||||
loadingOrders: true
|
||||
});
|
||||
|
||||
const orders = await orderService.getPendingOrders();
|
||||
this.dataModule.updatePendingOrders(orders);
|
||||
|
||||
// 更新地图标记点
|
||||
// this.updateOrderMarkers();
|
||||
} catch (error) {
|
||||
console.error('加载订单失败:', error);
|
||||
showToast('加载订单失败');
|
||||
} finally {
|
||||
this.pageContext.setData({
|
||||
loadingOrders: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示订单详情面板
|
||||
*/
|
||||
showOrderPanel(order: any, position: { x: number, y: number }): void {
|
||||
// 关闭其他面板
|
||||
this.pageContext.hideAllPanels();
|
||||
|
||||
// 更新数据模块中的当前订单和面板状态
|
||||
this.dataModule.setCurrentOrder(order);
|
||||
this.dataModule.setPanelPosition(position);
|
||||
this.dataModule.toggleOrderPanel(true);
|
||||
|
||||
// 规划订单路线
|
||||
this.planOrderRoute(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏订单详情面板
|
||||
*/
|
||||
hideOrderPanel(): void {
|
||||
// 更新数据模块中的面板状态
|
||||
this.dataModule.toggleOrderPanel(false);
|
||||
this.dataModule.setCurrentOrder(null);
|
||||
|
||||
// 同时取消路线显示
|
||||
this.cancelRoute();
|
||||
// 重置标记点状态
|
||||
this.pageContext.resetMarkers();
|
||||
}
|
||||
|
||||
/**
|
||||
* 规划订单路线
|
||||
*/
|
||||
async planOrderRoute(order: any): Promise<void> {
|
||||
try {
|
||||
const origin = `${order.startPoint.longitude},${order.startPoint.latitude}`;
|
||||
const destination = `${order.endPoint.longitude},${order.endPoint.latitude}`;
|
||||
|
||||
console.log(`开始规划路线: 起点=${origin}, 终点=${destination}`);
|
||||
|
||||
// 这里应该调用地图服务的路线规划功能
|
||||
// 目前先模拟一个简单的路线规划结果
|
||||
const routeResult = {
|
||||
distance: 1500, // 1.5公里
|
||||
duration: 300, // 5分钟
|
||||
polyline: null // 路线数据
|
||||
};
|
||||
|
||||
console.log('路线规划结果:', routeResult);
|
||||
|
||||
// 显示距离和时长信息
|
||||
if (routeResult.distance > 0 || routeResult.duration > 0) {
|
||||
const distanceStr = this.formatDistance(routeResult.distance);
|
||||
const durationStr = this.formatDuration(routeResult.duration);
|
||||
showToast(`距离: ${distanceStr}, 预计时间: ${durationStr}`);
|
||||
}
|
||||
|
||||
// 更新数据模块中的路线信息
|
||||
this.dataModule.updateRouteInfo(routeResult.polyline, routeResult.distance, routeResult.duration);
|
||||
|
||||
} catch (error) {
|
||||
console.error('路线规划失败:', error);
|
||||
showToast('路线规划失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消路线显示
|
||||
*/
|
||||
cancelRoute(): void {
|
||||
// 清除数据模块中的路线信息
|
||||
this.dataModule.clearRouteInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分配订单给货运人员
|
||||
*/
|
||||
async assignOrder(orderId: number, deliveryPersonId: number) {
|
||||
try {
|
||||
const result = await orderService.assignOrder(orderId, deliveryPersonId);
|
||||
if (result.success) {
|
||||
showToast('订单分配成功');
|
||||
// 刷新订单列表
|
||||
await this.loadPendingOrders();
|
||||
// 刷新货运人员状态
|
||||
// TODO this.dataModule.notifyDeliveryPersonsUpdated();
|
||||
} else {
|
||||
showToast(result.message || '订单分配失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('分配订单失败:', error);
|
||||
showToast('订单分配失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
*/
|
||||
async updateOrderStatus(orderId: number, status: string) {
|
||||
try {
|
||||
const result = await orderService.updateOrderStatus(orderId, status as Order['status']);
|
||||
if (result.success) {
|
||||
showToast('订单状态已更新');
|
||||
// 刷新订单列表
|
||||
await this.loadPendingOrders();
|
||||
// 刷新货运人员状态
|
||||
// this.dataModule.notifyDeliveryPersonsUpdated();
|
||||
} else {
|
||||
showToast(result.message || '订单状态更新失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新订单状态失败:', error);
|
||||
showToast('订单状态更新失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
*/
|
||||
async deleteOrder(orderId: number) {
|
||||
try {
|
||||
// 确认删除操作
|
||||
const confirmResult = await new Promise<boolean>((resolve) => {
|
||||
wx.showModal({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这个订单吗?此操作不可恢复。',
|
||||
success: (res) => {
|
||||
resolve(res.confirm);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!confirmResult) {
|
||||
return; // 用户取消删除
|
||||
}
|
||||
|
||||
await orderService.deleteOrder(orderId);
|
||||
showToast('订单已删除');
|
||||
|
||||
// 刷新订单列表
|
||||
await this.loadPendingOrders();
|
||||
// 刷新货运人员状态
|
||||
// this.dataModule.notifyDeliveryPersonsUpdated();
|
||||
|
||||
// 如果当前正在查看被删除的订单,关闭订单面板
|
||||
//TODO
|
||||
// const currentOrder = this.dataModule.getCurrentOrder();
|
||||
// if (currentOrder && currentOrder.id === orderId) {
|
||||
// this.hideOrderPanel();
|
||||
// }
|
||||
|
||||
} catch (error) {
|
||||
console.error('删除订单失败:', error);
|
||||
showToast('删除订单失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化距离
|
||||
*/
|
||||
private formatDistance(distance: number): string {
|
||||
if (distance < 1000) {
|
||||
return `${distance}米`;
|
||||
} else {
|
||||
return `${(distance / 1000).toFixed(1)}公里`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时长
|
||||
*/
|
||||
private formatDuration(duration: number): string {
|
||||
const minutes = Math.floor(duration / 60);
|
||||
const seconds = duration % 60;
|
||||
|
||||
if (minutes > 0) {
|
||||
return `${minutes}分${seconds}秒`;
|
||||
} else {
|
||||
return `${seconds}秒`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单状态文本
|
||||
*/
|
||||
getOrderStatusText(status: string): string {
|
||||
const statusMap: Record<string, string> = {
|
||||
'pending': '未分配',
|
||||
'assigned': '已分配',
|
||||
'in_transit': '配送中',
|
||||
'delivered': '已完成',
|
||||
'cancelled': '已取消'
|
||||
};
|
||||
return statusMap[status] || status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单状态对应的图标
|
||||
*/
|
||||
getOrderStatusIcon(status: string): string {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return '/images/order-pending.png';
|
||||
case 'assigned':
|
||||
return '/images/order-assigned.png';
|
||||
case 'in_transit':
|
||||
return '/images/order-transit.png';
|
||||
case 'delivered':
|
||||
return '/images/order-delivered.png';
|
||||
default:
|
||||
return '/images/order-pending.png';
|
||||
}
|
||||
}
|
||||
}
|
||||
239
miniprogram/pages/index/modules/warehouseModule.ts
Normal file
239
miniprogram/pages/index/modules/warehouseModule.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
// 仓库模块 - 处理仓库管理、显示、交互
|
||||
import warehouseService from '../../../services/warehouseService';
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import { DataModule } from './dataModule';
|
||||
|
||||
export class WarehouseModule {
|
||||
private pageContext: any;
|
||||
private dataModule: DataModule;
|
||||
private lastLoadTime: number = 0;
|
||||
private isLoading: boolean = false;
|
||||
private loadPromise: Promise<void> | null = null;
|
||||
|
||||
constructor(pageContext: any, dataModule: DataModule) {
|
||||
this.pageContext = pageContext;
|
||||
this.dataModule = dataModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载仓库数据(带缓存和防抖机制)
|
||||
*/
|
||||
async loadWarehouses(forceRefresh: boolean = false): Promise<void> {
|
||||
// 防抖机制:如果正在加载,返回同一个Promise
|
||||
if (this.isLoading && this.loadPromise && !forceRefresh) {
|
||||
return this.loadPromise;
|
||||
}
|
||||
|
||||
// 缓存机制:5分钟内不重复加载相同数据
|
||||
const now = Date.now();
|
||||
const cacheTime = 5 * 60 * 1000; // 5分钟缓存
|
||||
if (!forceRefresh && now - this.lastLoadTime < cacheTime) {
|
||||
console.log('使用缓存的仓库数据');
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
this.loadPromise = (async () => {
|
||||
try {
|
||||
const warehouses = await warehouseService.getWarehouses();
|
||||
|
||||
// 更新地图标记点
|
||||
this.updateWarehouseMarkers(warehouses);
|
||||
|
||||
this.lastLoadTime = Date.now();
|
||||
console.log('仓库数据加载完成,数量:', warehouses.length);
|
||||
} catch (error) {
|
||||
console.error('加载仓库数据失败:', error);
|
||||
showToast('加载仓库数据失败');
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
this.loadPromise = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return this.loadPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新仓库标记点
|
||||
*/
|
||||
private updateWarehouseMarkers(warehouses: any[]): void {
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 移除现有的仓库标记点
|
||||
const filteredMarkers = markers.filter((marker: any) => marker.type !== 'warehouse');
|
||||
|
||||
// 添加新的仓库标记点
|
||||
const warehouseMarkers = warehouses.map((warehouse, index) => {
|
||||
// 验证仓库坐标是否有效
|
||||
let validLongitude = warehouse.longitude;
|
||||
let validLatitude = warehouse.latitude;
|
||||
|
||||
if (isNaN(validLongitude) || isNaN(validLatitude)) {
|
||||
validLongitude = 102.833722; // 默认经度
|
||||
validLatitude = 24.880095; // 默认纬度
|
||||
}
|
||||
|
||||
return {
|
||||
id: 1000 + index, // 仓库标记点ID从1000开始
|
||||
longitude: validLongitude,
|
||||
latitude: validLatitude,
|
||||
iconPath: '/images/warehouse.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
zIndex: 10,
|
||||
type: 'warehouse',
|
||||
data: warehouse
|
||||
};
|
||||
});
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
const allMarkers = [...filteredMarkers, ...warehouseMarkers];
|
||||
this.dataModule.updateMarkers(allMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示仓库详情面板
|
||||
*/
|
||||
showWarehousePanel(warehouse: any, position: { x: number, y: number }): void {
|
||||
// 关闭其他面板
|
||||
this.pageContext.hideAllPanels();
|
||||
|
||||
// 更新数据模块中的当前仓库和面板状态
|
||||
this.dataModule.setCurrentWarehouse(warehouse);
|
||||
this.dataModule.setPanelPosition(position);
|
||||
this.dataModule.toggleWarehouseModal(true, 'bottom');
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏仓库详情面板
|
||||
*/
|
||||
hideWarehousePanel(): void {
|
||||
// 更新数据模块中的面板状态
|
||||
this.dataModule.toggleWarehouseModal(false);
|
||||
this.dataModule.setCurrentWarehouse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开仓库详情面板
|
||||
*/
|
||||
expandWarehousePanel(): void {
|
||||
this.dataModule.toggleWarehouseModal(true, 'full');
|
||||
}
|
||||
|
||||
/**
|
||||
* 收起仓库详情面板
|
||||
*/
|
||||
collapseWarehousePanel(): void {
|
||||
this.dataModule.toggleWarehouseModal(true, 'bottom');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理仓库标记点点击
|
||||
*/
|
||||
onWarehouseMarkerClick(warehouse: any, position: { x: number, y: number }): void {
|
||||
console.log('仓库被点击:', warehouse);
|
||||
|
||||
// 显示仓库详情面板
|
||||
this.showWarehousePanel(warehouse, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库库存状态
|
||||
*/
|
||||
getWarehouseInventoryStatus(warehouse: any): string {
|
||||
const capacity = warehouse.capacity || 100;
|
||||
const currentStock = warehouse.currentStock || 0;
|
||||
const percentage = (currentStock / capacity) * 100;
|
||||
|
||||
if (percentage >= 80) {
|
||||
return 'high';
|
||||
} else if (percentage >= 50) {
|
||||
return 'medium';
|
||||
} else {
|
||||
return 'low';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库库存状态文本
|
||||
*/
|
||||
getWarehouseInventoryStatusText(warehouse: any): string {
|
||||
const status = this.getWarehouseInventoryStatus(warehouse);
|
||||
|
||||
switch (status) {
|
||||
case 'high':
|
||||
return '库存充足';
|
||||
case 'medium':
|
||||
return '库存适中';
|
||||
case 'low':
|
||||
return '库存不足';
|
||||
default:
|
||||
return '未知状态';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库库存状态颜色
|
||||
*/
|
||||
getWarehouseInventoryStatusColor(warehouse: any): string {
|
||||
const status = this.getWarehouseInventoryStatus(warehouse);
|
||||
|
||||
switch (status) {
|
||||
case 'high':
|
||||
return '#52c41a'; // 绿色
|
||||
case 'medium':
|
||||
return '#faad14'; // 橙色
|
||||
case 'low':
|
||||
return '#f5222d'; // 红色
|
||||
default:
|
||||
return '#d9d9d9'; // 灰色
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新仓库
|
||||
*/
|
||||
async createWarehouse(warehouseData: any): Promise<void> {
|
||||
try {
|
||||
await warehouseService.createWarehouse(warehouseData);
|
||||
|
||||
showToast('仓库创建成功');
|
||||
console.log('新仓库创建成功:', warehouseData);
|
||||
|
||||
// 不需要重新加载仓库数据,因为仓库数据变化不频繁
|
||||
// 用户可以通过手动刷新来获取最新数据
|
||||
|
||||
} catch (error) {
|
||||
console.error('创建仓库失败:', error);
|
||||
showToast('创建仓库失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除仓库
|
||||
*/
|
||||
async deleteWarehouse(warehouseId: number): Promise<void> {
|
||||
try {
|
||||
await warehouseService.deleteWarehouse(warehouseId);
|
||||
|
||||
showToast('仓库删除成功');
|
||||
console.log(`仓库 ${warehouseId} 已删除`);
|
||||
|
||||
// 不需要重新加载仓库数据,因为仓库数据变化不频繁
|
||||
// 用户可以通过手动刷新来获取最新数据
|
||||
|
||||
} catch (error) {
|
||||
console.error('删除仓库失败:', error);
|
||||
showToast('删除仓库失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制刷新仓库数据(忽略缓存)
|
||||
*/
|
||||
async forceRefreshWarehouses(): Promise<void> {
|
||||
console.log('强制刷新仓库数据');
|
||||
return this.loadWarehouses(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user