feat: 增强库位服务配置功能,添加常量定义和配置合并逻辑,支持动态更新和获取当前配置

This commit is contained in:
xudan 2025-09-05 00:52:30 +08:00
parent 95fc2f4a16
commit 0e38d2fff6

View File

@ -8,6 +8,97 @@ import { type Ref, ref } from 'vue';
import { createStorageLocationPens } from './draw/storage-location-drawer';
// ==================== 常量定义 ====================
/**
*
*/
const COLORS = {
OCCUPIED: '#ff4d4f', // 占用状态 - 红色
AVAILABLE: '#52c41a', // 可用状态 - 绿色
DEFAULT: '#f5f5f5' // 默认状态 - 浅灰色
} as const;
/**
*
*/
const MESSAGE_TYPES = {
BATCH_UPDATE: 'storage_location_update',
SINGLE_UPDATE: 'storage_location_status_change',
GET_STATUS: 'get_status'
} as const;
/**
*
*/
const DEFAULT_CONFIG = {
MONITOR_INTERVAL: 3, // 默认监控间隔(秒)
POINT_TYPE_ACTION: 15 // 动作点类型
} as const;
/**
* Pen类型常量
*/
const PEN_TYPES = {
POINT: 'point',
STORAGE_LOCATION: 'storage-location',
STORAGE_MORE: 'storage-more',
STORAGE_BACKGROUND: 'storage-background'
} as const;
/**
*
*/
const TAGS = {
POINT_PREFIX: 'point-'
} as const;
/**
*
*/
export interface StorageLocationConfig {
colors: {
occupied: string;
available: string;
default: string;
};
penTypes: {
point: string;
storageLocation: string;
storageMore: string;
storageBackground: string;
};
tags: {
pointPrefix: string;
};
monitoring: {
defaultInterval: number;
};
}
/**
*
*/
const DEFAULT_STORAGE_CONFIG: StorageLocationConfig = {
colors: {
occupied: COLORS.OCCUPIED,
available: COLORS.AVAILABLE,
default: COLORS.DEFAULT
},
penTypes: {
point: PEN_TYPES.POINT,
storageLocation: PEN_TYPES.STORAGE_LOCATION,
storageMore: PEN_TYPES.STORAGE_MORE,
storageBackground: PEN_TYPES.STORAGE_BACKGROUND
},
tags: {
pointPrefix: TAGS.POINT_PREFIX
},
monitoring: {
defaultInterval: DEFAULT_CONFIG.MONITOR_INTERVAL
}
};
// 提供给绘制层快速查询的全局状态映射pointId -> (layerName -> { occupied, locked })
export type StorageState = { occupied?: boolean; locked?: boolean };
export const storageStateMap = new Map<string, Map<string, StorageState>>();
@ -21,12 +112,28 @@ export class StorageLocationService {
private storageLocations: Ref<Map<string, StorageLocationInfo[]>> = ref(new Map());
private editor: EditorService | null = null;
private sceneId: string = '';
private config: StorageLocationConfig;
// 渲染调度标记,避免在高频事件中重复 render
private renderScheduled = false;
constructor(editor: EditorService, sceneId: string) {
constructor(editor: EditorService, sceneId: string, config?: Partial<StorageLocationConfig>) {
this.editor = editor;
this.sceneId = sceneId;
this.config = this.mergeConfig(config);
}
/**
* 使
*/
private mergeConfig(userConfig?: Partial<StorageLocationConfig>): StorageLocationConfig {
if (!userConfig) return DEFAULT_STORAGE_CONFIG;
return {
colors: { ...DEFAULT_STORAGE_CONFIG.colors, ...userConfig.colors },
penTypes: { ...DEFAULT_STORAGE_CONFIG.penTypes, ...userConfig.penTypes },
tags: { ...DEFAULT_STORAGE_CONFIG.tags, ...userConfig.tags },
monitoring: { ...DEFAULT_STORAGE_CONFIG.monitoring, ...userConfig.monitoring }
};
}
/**
@ -48,6 +155,21 @@ export class StorageLocationService {
return this.storageLocations;
}
/**
*
* @param newConfig
*/
updateConfig(newConfig: Partial<StorageLocationConfig>): void {
this.config = this.mergeConfig(newConfig);
}
/**
*
*/
getConfig(): StorageLocationConfig {
return { ...this.config };
}
/**
* ID的映射关系
* @returns ID的映射Map
@ -56,8 +178,10 @@ export class StorageLocationService {
const stationToPointIdMap = new Map<string, string>();
if (!this.editor) return stationToPointIdMap;
// 获取所有动作点 (MapPointType.动作点 = 15)
const actionPoints = this.editor.find('point').filter((pen) => pen.point?.type === 15);
// 获取所有动作点
const actionPoints = this.editor.find(this.config.penTypes.point).filter(
(pen) => pen.point?.type === DEFAULT_CONFIG.POINT_TYPE_ACTION
);
actionPoints.forEach((pen) => {
const stationName = pen.label; // 如 "AP9"
@ -114,7 +238,7 @@ export class StorageLocationService {
const allOccupied = locations.every((loc) => loc.is_occupied);
const allLocked = locations.every((loc) => loc.is_locked);
const color = allOccupied ? '#ff4d4f' : '#52c41a'; // 占用红色,否则绿色
const color = allOccupied ? this.config.colors.occupied : this.config.colors.available;
// 更新边框颜色
this.editor?.updatePointBorderColor(pointId, color);
@ -137,7 +261,7 @@ export class StorageLocationService {
* @param message
*/
private handleStorageLocationUpdate(message: StorageLocationMessage) {
if (message.type === 'storage_location_update') {
if (message.type === MESSAGE_TYPES.BATCH_UPDATE) {
// 优先使用后端提供的 operate_point_id 直接映射到画布点ID
// 若无该字段或为空,再回退通过站点名映射到点标签。
const stationToPointIdMap = this.buildStationToPointIdMap();
@ -181,7 +305,7 @@ export class StorageLocationService {
// 批量更新后触发一次重绘
this.scheduleRender();
} else if (message.type === 'storage_location_status_change') {
} else if (message.type === MESSAGE_TYPES.SINGLE_UPDATE) {
// 处理单个库位状态变化
const { new_status } = message;
const pointId = this.getPointIdByStorageLocationId(new_status.id);
@ -228,7 +352,9 @@ export class StorageLocationService {
this.stopMonitoring();
// 监控库位状态
const ws = await monitorStorageLocationById(this.sceneId, { interval: options.interval || 3 });
const ws = await monitorStorageLocationById(this.sceneId, {
interval: options.interval || this.config.monitoring.defaultInterval
});
if (isNil(ws)) return;
ws.onmessage = (e) => {
@ -243,7 +369,7 @@ export class StorageLocationService {
// 连接成功后主动请求当前状态
ws.onopen = () => {
const message = {
type: 'get_status',
type: MESSAGE_TYPES.GET_STATUS,
timestamp: new Date().toISOString(),
};
ws.send(JSON.stringify(message));
@ -278,7 +404,7 @@ export class StorageLocationService {
if (!this.editor) return;
const pointPen = this.editor.getPenById(pointId);
if (!pointPen || pointPen.name !== 'point' || pointPen.point?.type !== MapPointType.) {
if (!pointPen || pointPen.name !== this.config.penTypes.point || pointPen.point?.type !== MapPointType.) {
console.warn(`无法为 ${pointId} 创建库位: 不是动作点或点位不存在`);
return;
}
@ -341,7 +467,7 @@ export class StorageLocationService {
const updatedState = { ...storagePen.storageLocation, ...state };
this.editor.updatePen(storagePen.id!, {
storageLocation: updatedState,
background: updatedState.occupied ? '#ff4d4f' : '#f5f5f5',
background: updatedState.occupied ? this.config.colors.occupied : this.config.colors.default,
}, false);
}
return;
@ -368,7 +494,7 @@ export class StorageLocationService {
const updatedState = { ...pen.storageLocation, ...state };
this.editor.updatePen(pen.id!, {
storageLocation: updatedState,
background: updatedState.occupied ? '#ff4d4f' : '#f5f5f5',
background: updatedState.occupied ? this.config.colors.occupied : this.config.colors.default,
}, false);
}
}
@ -383,8 +509,10 @@ export class StorageLocationService {
public delete(pointId: string): void {
if (!this.editor) return;
const storagePens = this.editor.find('storage-location,storage-more,storage-background').filter(
(pen) => pen.tags?.includes(`point-${pointId}`)
const storagePens = this.editor.find(
`${this.config.penTypes.storageLocation},${this.config.penTypes.storageMore},${this.config.penTypes.storageBackground}`
).filter(
(pen) => pen.tags?.includes(`${this.config.tags.pointPrefix}${pointId}`)
);
if (storagePens.length > 0) {
this.editor.delete(storagePens, true, true);
@ -417,8 +545,8 @@ export class StorageLocationService {
private getStorageLocationPens(pointId: string): MapPen[] {
if (!this.editor) return [];
return this.editor.find('storage-location,storage-more').filter(
(pen) => pen.tags?.includes(`point-${pointId}`)
return this.editor.find(`${this.config.penTypes.storageLocation},${this.config.penTypes.storageMore}`).filter(
(pen) => pen.tags?.includes(`${this.config.tags.pointPrefix}${pointId}`)
);
}
@ -431,7 +559,7 @@ export class StorageLocationService {
private findStorageLocationPen(pointId: string, locationName: string): MapPen | undefined {
if (!this.editor) return undefined;
return this.editor.find('storage-location').find(
return this.editor.find(this.config.penTypes.storageLocation).find(
(pen) => pen.storageLocation?.pointId === pointId && pen.storageLocation?.locationName === locationName
);
}
@ -443,7 +571,7 @@ export class StorageLocationService {
public createAll(): void {
if (!this.editor) return;
const actionPoints = this.editor.find('point').filter(
const actionPoints = this.editor.find(this.config.penTypes.point).filter(
(pen) => pen.point?.type === MapPointType. && pen.point?.associatedStorageLocations?.length
);
@ -542,3 +670,36 @@ export class StorageLocationUpdater {
export function createStorageLocationUpdater(service: StorageLocationService): StorageLocationUpdater {
return new StorageLocationUpdater(service);
}
// ==================== 使用示例 ====================
/**
*
*
* @example
* ```typescript
* // 使用默认配置
* const service = new StorageLocationService(editor, sceneId);
*
* // 使用自定义配置
* const customService = new StorageLocationService(editor, sceneId, {
* colors: {
* occupied: '#ff0000', // 自定义占用颜色
* available: '#00ff00', // 自定义可用颜色
* default: '#cccccc' // 自定义默认颜色
* },
* penTypes: {
* point: 'custom-point', // 自定义点类型
* storageLocation: 'custom-storage-location'
* },
* monitoring: {
* defaultInterval: 5 // 自定义监控间隔
* }
* });
*
* // 运行时更新配置
* service.updateConfig({
* colors: { occupied: '#ff4444' }
* });
* ```
*/