feat: 添加BinTask编辑功能,集成BinTaskEditorModal,优化BinTask管理逻辑,增强用户交互体验
This commit is contained in:
parent
c31f9d5bef
commit
c41263d39f
BIN
src/assets/icons/png/delete.png
Normal file
BIN
src/assets/icons/png/delete.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 406 B |
BIN
src/assets/icons/png/setting.png
Normal file
BIN
src/assets/icons/png/setting.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@ -10,6 +10,8 @@ import {
|
||||
type Rect,
|
||||
} from '@api/map';
|
||||
import type { RobotInfo } from '@api/robot';
|
||||
import type { BinTaskItem } from '@api/scene';
|
||||
import BinTaskEditorModal from '@common/modal/bintask-editor-modal.vue';
|
||||
import type { PointBindModalRef } from '@common/modal/point-bind-modal.vue';
|
||||
import type { RobotBindModalRef } from '@common/modal/robot-bind-modal.vue';
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
@ -19,6 +21,8 @@ import { isNil } from 'lodash-es';
|
||||
import { ref, shallowRef } from 'vue';
|
||||
import { computed, inject, type InjectionKey, type ShallowRef } from 'vue';
|
||||
|
||||
// BinTaskManagerService 通过 editor.getBinTaskManager() 获取
|
||||
|
||||
type Props = {
|
||||
token: InjectionKey<ShallowRef<EditorService>>;
|
||||
id?: string;
|
||||
@ -64,6 +68,11 @@ const actions = computed<MapPen[]>(
|
||||
),
|
||||
);
|
||||
|
||||
// BinTask编辑相关
|
||||
const refBinTaskEditor = shallowRef<any>();
|
||||
const binTaskEditorVisible = ref(false);
|
||||
const selectedLocationName = ref<string>('');
|
||||
|
||||
const coArea1 = computed<MapPen[]>(() => editor.value.getBoundAreas(props.id, 'point', MapAreaType.库区));
|
||||
const coArea2 = computed<MapPen[]>(() => editor.value.getBoundAreas(props.id, 'point', MapAreaType.互斥区));
|
||||
|
||||
@ -213,11 +222,50 @@ function onChangeLocation(i: number, v: string) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// BinTask编辑相关函数
|
||||
function onEditBinTask(locationName: string) {
|
||||
selectedLocationName.value = locationName;
|
||||
binTaskEditorVisible.value = true;
|
||||
}
|
||||
|
||||
function onBinTaskSave(data: { pointName: string; locationName: string; binTasks: BinTaskItem[] }) {
|
||||
const pointName = pen.value?.label || pen.value?.id || '';
|
||||
if (!pointName) return;
|
||||
|
||||
// 更新场景文件中的BinTask配置
|
||||
editor.value.updateBinTask(pointName, data.locationName, data.binTasks);
|
||||
|
||||
// 延迟渲染并重新选中点位,避免失焦
|
||||
requestAnimationFrame(() => {
|
||||
editor.value.render();
|
||||
editor.value.active(props.id!);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取库位的BinTask数据
|
||||
function getBinTaskData(locationName: string): BinTaskItem[] {
|
||||
const pointName = pen.value?.label || pen.value?.id || '';
|
||||
return editor.value.getBinTaskManager().getBinTaskData(pointName, locationName);
|
||||
}
|
||||
|
||||
// 设置图标路径
|
||||
const settingIconUrl = new URL('../../assets/icons/png/setting.png', import.meta.url).toString();
|
||||
// 删除图标路径
|
||||
const deleteIconUrl = new URL('../../assets/icons/png/delete.png', import.meta.url).toString();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RobotBindModal ref="refBindRobot" :token="token" />
|
||||
<PointBindModal ref="refBindPoint" :token="token" />
|
||||
<BinTaskEditorModal
|
||||
ref="refBinTaskEditor"
|
||||
v-model:open="binTaskEditorVisible"
|
||||
:point-name="pen?.label || pen?.id || ''"
|
||||
:location-name="selectedLocationName"
|
||||
:initial-data="getBinTaskData(selectedLocationName)"
|
||||
@save="onBinTaskSave"
|
||||
/>
|
||||
|
||||
<a-card class="full" :title="$t('属性')" :bordered="false">
|
||||
<a-flex v-if="id && pen && point" :gap="24" vertical>
|
||||
@ -380,8 +428,24 @@ function onChangeLocation(i: number, v: string) {
|
||||
:placeholder="$t('请输入库位')"
|
||||
@change="onChangeLocation(i, ($event.target as any).value)"
|
||||
/>
|
||||
<a-button
|
||||
class="icon-btn"
|
||||
size="small"
|
||||
@click="onEditBinTask(l)"
|
||||
:title="$t('编辑BinTask配置')"
|
||||
>
|
||||
<img
|
||||
:src="settingIconUrl"
|
||||
alt="设置"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</a-button>
|
||||
<a-button class="icon-btn" size="small" danger @click="onRemoveLocation(i)">
|
||||
<i class="mask trash" />
|
||||
<img
|
||||
:src="deleteIconUrl"
|
||||
alt="删除"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</a-button>
|
||||
</a-flex>
|
||||
<a-button type="dashed" block @click="onAddLocation">
|
||||
|
452
src/components/modal/bintask-editor-modal.vue
Normal file
452
src/components/modal/bintask-editor-modal.vue
Normal file
@ -0,0 +1,452 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:open="visible"
|
||||
:title="$t('编辑BinTask配置')"
|
||||
:width="1000"
|
||||
:confirm-loading="loading"
|
||||
@ok="handleSave"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<div class="bintask-editor">
|
||||
<a-alert
|
||||
v-if="!currentLocation"
|
||||
message="请先选择一个库位"
|
||||
type="warning"
|
||||
show-icon
|
||||
class="mb-16"
|
||||
/>
|
||||
|
||||
<div v-else>
|
||||
<div class="location-header">
|
||||
<a-typography-title :level="4">{{ $t('库位') }}: {{ currentLocation }}</a-typography-title>
|
||||
</div>
|
||||
|
||||
<a-divider />
|
||||
|
||||
<div class="task-list">
|
||||
<div v-for="(task, taskIndex) in localTaskList" :key="taskIndex" class="task-item">
|
||||
<a-card :title="`${$t('任务')} ${taskIndex + 1}`" size="small" class="task-card">
|
||||
<template #extra>
|
||||
<a-button
|
||||
type="text"
|
||||
danger
|
||||
size="small"
|
||||
@click="removeTask(taskIndex)"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<div class="task-content">
|
||||
<div v-for="(operation, opKey) in task.operations" :key="String(opKey)" class="operation-item">
|
||||
<a-card size="small" class="operation-card">
|
||||
<template #title>
|
||||
<a-input
|
||||
:value="opKey"
|
||||
:placeholder="$t('操作名称')"
|
||||
@blur="updateOperationKey(
|
||||
taskIndex,
|
||||
String(opKey),
|
||||
($event.target as HTMLInputElement).value
|
||||
)"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</template>
|
||||
<template #extra>
|
||||
<a-button
|
||||
type="text"
|
||||
danger
|
||||
size="small"
|
||||
@click="removeOperation(taskIndex, String(opKey))"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<div class="operation-properties">
|
||||
<div v-for="(value, propKey) in operation" :key="String(propKey)" class="property-row">
|
||||
<a-row :gutter="8" align="middle">
|
||||
<a-col :span="6">
|
||||
<a-input
|
||||
:value="propKey"
|
||||
:placeholder="$t('属性名')"
|
||||
@blur="updatePropertyKey(
|
||||
taskIndex,
|
||||
String(opKey),
|
||||
String(propKey),
|
||||
($event.target as HTMLInputElement).value
|
||||
)"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-input
|
||||
v-if="typeof value === 'string'"
|
||||
:value="value"
|
||||
:placeholder="$t('属性值')"
|
||||
@change="updatePropertyValue(
|
||||
taskIndex,
|
||||
String(opKey),
|
||||
String(propKey),
|
||||
($event.target as HTMLInputElement).value
|
||||
)"
|
||||
/>
|
||||
<a-input-number
|
||||
v-else-if="typeof value === 'number'"
|
||||
:value="value"
|
||||
:placeholder="$t('属性值')"
|
||||
@change="updatePropertyValue(taskIndex, String(opKey), String(propKey), $event)"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<a-checkbox
|
||||
v-else-if="typeof value === 'boolean'"
|
||||
:checked="value"
|
||||
@change="updatePropertyValue(
|
||||
taskIndex,
|
||||
String(opKey),
|
||||
String(propKey),
|
||||
($event.target as HTMLInputElement).checked
|
||||
)"
|
||||
>
|
||||
{{ value ? $t('是') : $t('否') }}
|
||||
</a-checkbox>
|
||||
<a-input
|
||||
v-else
|
||||
:value="String(value)"
|
||||
:placeholder="$t('属性值')"
|
||||
@change="updatePropertyValue(
|
||||
taskIndex,
|
||||
String(opKey),
|
||||
String(propKey),
|
||||
($event.target as HTMLInputElement).value
|
||||
)"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-select
|
||||
:value="getValueType(value)"
|
||||
@change="changeValueType(taskIndex, String(opKey), String(propKey), $event as string)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<a-select-option value="string">{{ $t('字符串') }}</a-select-option>
|
||||
<a-select-option value="number">{{ $t('数字') }}</a-select-option>
|
||||
<a-select-option value="boolean">{{ $t('布尔值') }}</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button
|
||||
type="text"
|
||||
danger
|
||||
size="small"
|
||||
@click="removeProperty(taskIndex, String(opKey), String(propKey))"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<a-button
|
||||
type="dashed"
|
||||
block
|
||||
class="add-property-btn"
|
||||
@click="addProperty(taskIndex, String(opKey))"
|
||||
>
|
||||
<template #icon><PlusOutlined /></template>
|
||||
{{ $t('添加属性') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
|
||||
<a-button
|
||||
type="dashed"
|
||||
block
|
||||
class="add-operation-btn"
|
||||
@click="addOperation(taskIndex)"
|
||||
>
|
||||
<template #icon><PlusOutlined /></template>
|
||||
{{ $t('添加操作') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
|
||||
<a-button
|
||||
type="dashed"
|
||||
block
|
||||
class="add-task-btn"
|
||||
@click="addTask"
|
||||
>
|
||||
<template #icon><PlusOutlined /></template>
|
||||
{{ $t('添加任务') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import type { BinTaskItem } from '../../apis/scene';
|
||||
import { BinTaskManagerService } from '../../services/bintask-manager.service';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
pointName?: string;
|
||||
locationName?: string;
|
||||
initialData?: BinTaskItem[];
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:open', open: boolean): void;
|
||||
(e: 'save', data: { pointName: string; locationName: string; binTasks: BinTaskItem[] }): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
open: false,
|
||||
pointName: '',
|
||||
locationName: '',
|
||||
initialData: () => []
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const loading = ref(false);
|
||||
const visible = ref(props.open);
|
||||
|
||||
// 当前选中的库位
|
||||
const currentLocation = computed(() => props.locationName);
|
||||
|
||||
// 创建临时的BinTaskManagerService实例(用于状态管理)
|
||||
const tempBinTaskManager = new BinTaskManagerService({} as any);
|
||||
|
||||
// 本地编辑状态 - 用于隔离编辑过程中的数据变化
|
||||
const localTaskList = ref<Array<{ operations: Record<string, Record<string, any>> }>>([]);
|
||||
|
||||
// 监听props变化
|
||||
watch(() => props.open, (newOpen) => {
|
||||
visible.value = newOpen;
|
||||
if (newOpen) {
|
||||
loadInitialData();
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.initialData, () => {
|
||||
if (props.open) {
|
||||
loadInitialData();
|
||||
}
|
||||
});
|
||||
|
||||
// 加载初始数据到本地状态
|
||||
const loadInitialData = () => {
|
||||
const parsedData = tempBinTaskManager.parseBinTaskData(props.initialData || []);
|
||||
localTaskList.value = parsedData;
|
||||
};
|
||||
|
||||
// 获取值的类型
|
||||
const getValueType = (value: any) => {
|
||||
if (typeof value === 'boolean') return 'boolean';
|
||||
if (typeof value === 'number') return 'number';
|
||||
return 'string';
|
||||
};
|
||||
|
||||
|
||||
// 生成唯一的键名
|
||||
const generateUniqueKey = (prefix: string): string => {
|
||||
return `${prefix}_${Date.now()}`;
|
||||
};
|
||||
|
||||
// 添加任务
|
||||
const addTask = () => {
|
||||
localTaskList.value.push({ operations: {} });
|
||||
};
|
||||
|
||||
// 删除任务
|
||||
const removeTask = (taskIndex: number) => {
|
||||
localTaskList.value.splice(taskIndex, 1);
|
||||
};
|
||||
|
||||
// 添加操作
|
||||
const addOperation = (taskIndex: number) => {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task) {
|
||||
const newOpKey = generateUniqueKey('operation');
|
||||
task.operations[newOpKey] = { operation: 'pick' };
|
||||
}
|
||||
};
|
||||
|
||||
// 删除操作
|
||||
const removeOperation = (taskIndex: number, opKey: string) => {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[opKey]) {
|
||||
delete task.operations[opKey];
|
||||
}
|
||||
};
|
||||
|
||||
// 更新操作键名 - 只在失去焦点时更新
|
||||
const updateOperationKey = (taskIndex: number, oldKey: string, newKey: string) => {
|
||||
if (newKey && newKey !== oldKey) {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[oldKey]) {
|
||||
const newOperations = { ...task.operations };
|
||||
const operation = newOperations[oldKey];
|
||||
delete newOperations[oldKey];
|
||||
newOperations[newKey] = operation;
|
||||
task.operations = newOperations;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 添加属性
|
||||
const addProperty = (taskIndex: number, opKey: string) => {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[opKey]) {
|
||||
const newPropKey = generateUniqueKey('property');
|
||||
task.operations[opKey][newPropKey] = '';
|
||||
}
|
||||
};
|
||||
|
||||
// 删除属性
|
||||
const removeProperty = (taskIndex: number, opKey: string, propKey: string) => {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[opKey] && task.operations[opKey][propKey] !== undefined) {
|
||||
delete task.operations[opKey][propKey];
|
||||
}
|
||||
};
|
||||
|
||||
// 更新属性键名 - 只在失去焦点时更新
|
||||
const updatePropertyKey = (taskIndex: number, opKey: string, oldPropKey: string, newPropKey: string) => {
|
||||
if (newPropKey && newPropKey !== oldPropKey) {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[opKey] && task.operations[opKey][oldPropKey] !== undefined) {
|
||||
const value = task.operations[opKey][oldPropKey];
|
||||
delete task.operations[opKey][oldPropKey];
|
||||
task.operations[opKey][newPropKey] = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 更新属性值
|
||||
const updatePropertyValue = (taskIndex: number, opKey: string, propKey: string, value: any) => {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[opKey]) {
|
||||
task.operations[opKey][propKey] = value;
|
||||
}
|
||||
};
|
||||
|
||||
// 改变值类型
|
||||
const changeValueType = (taskIndex: number, opKey: string, propKey: string, newType: string) => {
|
||||
const task = localTaskList.value[taskIndex];
|
||||
if (task && task.operations[opKey] && task.operations[opKey][propKey] !== undefined) {
|
||||
const currentValue = task.operations[opKey][propKey];
|
||||
const newValue = tempBinTaskManager.convertValueType(currentValue, newType);
|
||||
task.operations[opKey][propKey] = newValue;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存数据 - 统一处理所有更新
|
||||
const handleSave = async () => {
|
||||
if (!props.pointName || !props.locationName) {
|
||||
message.error('缺少必要的参数');
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
// 将本地编辑状态转换为BinTask格式
|
||||
const binTasks = tempBinTaskManager.convertToBinTaskData(localTaskList.value);
|
||||
|
||||
// 发送保存事件,由父组件处理实际的更新
|
||||
emit('save', {
|
||||
pointName: props.pointName,
|
||||
locationName: props.locationName,
|
||||
binTasks
|
||||
});
|
||||
|
||||
message.success('BinTask配置保存成功');
|
||||
handleCancel();
|
||||
} catch (error) {
|
||||
console.error('保存BinTask配置失败:', error);
|
||||
message.error('保存失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 取消操作 - 重置本地状态
|
||||
const handleCancel = () => {
|
||||
visible.value = false;
|
||||
emit('update:open', false);
|
||||
// 重置本地状态,下次打开时会重新加载初始数据
|
||||
localTaskList.value = [];
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bintask-editor {
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.location-header {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.task-item {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.task-card {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.task-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.operation-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.operation-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.operation-card {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.operation-properties {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.property-row {
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.add-property-btn,
|
||||
.add-operation-btn,
|
||||
.add-task-btn {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mb-16 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
581
src/services/bintask-manager.service.ts
Normal file
581
src/services/bintask-manager.service.ts
Normal file
@ -0,0 +1,581 @@
|
||||
import type { BinLocationGroup, BinLocationsList, BinTaskItem } from '../apis/scene';
|
||||
import type { EditorService } from './editor.service';
|
||||
|
||||
/**
|
||||
* BinTask统一管理服务
|
||||
* 整合了数据获取、编辑和场景更新的所有BinTask相关功能
|
||||
*/
|
||||
export class BinTaskManagerService {
|
||||
private editor: EditorService;
|
||||
|
||||
constructor(editor: EditorService) {
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
//#region 数据获取相关
|
||||
|
||||
/**
|
||||
* 获取指定库位的BinTask数据
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 库位名称
|
||||
* @returns BinTask数据列表
|
||||
*/
|
||||
public getBinTaskData(pointName: string, locationName: string): BinTaskItem[] {
|
||||
if (!pointName || !locationName) return [];
|
||||
|
||||
try {
|
||||
const rawData = this.editor.getBinLocationsList();
|
||||
if (!rawData) return [];
|
||||
|
||||
const binLocationGroups = Array.isArray(rawData)
|
||||
? (rawData as BinLocationGroup[])
|
||||
: (rawData as BinLocationsList)?.binLocationsList;
|
||||
|
||||
if (!binLocationGroups || !Array.isArray(binLocationGroups)) return [];
|
||||
|
||||
const allBinLocations = binLocationGroups
|
||||
.filter((group) => group && Array.isArray(group.binLocationList))
|
||||
.flatMap((group) => group.binLocationList)
|
||||
.filter((item) => item && typeof item === 'object');
|
||||
|
||||
const targetLocation = allBinLocations.find(
|
||||
(item) => item.pointName === pointName && item.instanceName === locationName
|
||||
);
|
||||
|
||||
if (!targetLocation || !targetLocation.property || !Array.isArray(targetLocation.property)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const binTaskProperty = targetLocation.property.find((prop) => prop && prop.key === 'binTask');
|
||||
if (!binTaskProperty || !binTaskProperty.stringValue) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(binTaskProperty.stringValue.replace(/\n/g, '').trim());
|
||||
} catch (error) {
|
||||
console.error('解析BinTask数据失败:', error);
|
||||
return [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取BinTask数据失败:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取动作点的所有库位BinTask数据
|
||||
* @param pointName 动作点名称
|
||||
* @returns 库位BinTask数据映射
|
||||
*/
|
||||
public getPointBinTaskData(pointName: string): Record<string, BinTaskItem[]> {
|
||||
if (!pointName) return {};
|
||||
|
||||
try {
|
||||
const rawData = this.editor.getBinLocationsList();
|
||||
if (!rawData) return {};
|
||||
|
||||
const binLocationGroups = Array.isArray(rawData)
|
||||
? (rawData as BinLocationGroup[])
|
||||
: (rawData as BinLocationsList)?.binLocationsList;
|
||||
|
||||
if (!binLocationGroups || !Array.isArray(binLocationGroups)) return {};
|
||||
|
||||
const allBinLocations = binLocationGroups
|
||||
.filter((group) => group && Array.isArray(group.binLocationList))
|
||||
.flatMap((group) => group.binLocationList)
|
||||
.filter((item) => item && typeof item === 'object');
|
||||
|
||||
const pointLocations = allBinLocations.filter(
|
||||
(item) => item.pointName === pointName
|
||||
);
|
||||
|
||||
const result: Record<string, BinTaskItem[]> = {};
|
||||
|
||||
pointLocations.forEach((location) => {
|
||||
if (location.instanceName && location.property && Array.isArray(location.property)) {
|
||||
const binTaskProperty = location.property.find((prop) => prop && prop.key === 'binTask');
|
||||
if (binTaskProperty && binTaskProperty.stringValue) {
|
||||
try {
|
||||
const binTasks = JSON.parse(binTaskProperty.stringValue.replace(/\n/g, '').trim());
|
||||
result[location.instanceName] = binTasks;
|
||||
} catch (error) {
|
||||
console.error('解析库位BinTask数据失败:', error, location);
|
||||
result[location.instanceName] = [];
|
||||
}
|
||||
} else {
|
||||
result[location.instanceName] = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('获取动作点BinTask数据失败:', error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查库位是否存在BinTask配置
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 库位名称
|
||||
* @returns 是否存在BinTask配置
|
||||
*/
|
||||
public hasBinTaskConfig(pointName: string, locationName: string): boolean {
|
||||
const binTaskData = this.getBinTaskData(pointName, locationName);
|
||||
return binTaskData.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库位的BinTask配置数量
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 库位名称
|
||||
* @returns BinTask配置数量
|
||||
*/
|
||||
public getBinTaskCount(pointName: string, locationName: string): number {
|
||||
const binTaskData = this.getBinTaskData(pointName, locationName);
|
||||
return binTaskData.length;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 数据编辑相关
|
||||
|
||||
/**
|
||||
* 解析BinTask数据为可编辑的格式
|
||||
* @param binTaskData 原始BinTask数据
|
||||
* @returns 可编辑的任务列表
|
||||
*/
|
||||
public parseBinTaskData(binTaskData: BinTaskItem[]): TaskData[] {
|
||||
if (!binTaskData || binTaskData.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return binTaskData.map(task => {
|
||||
const operations: Record<string, Record<string, any>> = {};
|
||||
Object.entries(task).forEach(([key, value]) => {
|
||||
if (value && typeof value === 'object') {
|
||||
operations[key] = { ...value };
|
||||
}
|
||||
});
|
||||
return { operations };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将编辑后的数据转换回BinTask格式
|
||||
* @param taskList 编辑后的任务列表
|
||||
* @returns BinTask数据
|
||||
*/
|
||||
public convertToBinTaskData(taskList: TaskData[]): BinTaskItem[] {
|
||||
return taskList.map(task => {
|
||||
const result: any = {};
|
||||
Object.entries(task.operations).forEach(([key, value]) => {
|
||||
result[key] = value;
|
||||
});
|
||||
return result as BinTaskItem;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值的类型
|
||||
* @param value 任意值
|
||||
* @returns 类型字符串
|
||||
*/
|
||||
public getValueType(value: any): string {
|
||||
if (typeof value === 'boolean') return 'boolean';
|
||||
if (typeof value === 'number') return 'number';
|
||||
return 'string';
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换值类型
|
||||
* @param value 当前值
|
||||
* @param newType 新类型
|
||||
* @returns 转换后的值
|
||||
*/
|
||||
public convertValueType(value: any, newType: string): any {
|
||||
switch (newType) {
|
||||
case 'string':
|
||||
return String(value);
|
||||
case 'number':
|
||||
return isNaN(Number(value)) ? 0 : Number(value);
|
||||
case 'boolean':
|
||||
return Boolean(value);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的操作
|
||||
* @returns 新操作对象
|
||||
*/
|
||||
public createNewOperation(): Record<string, any> {
|
||||
return {
|
||||
operation: 'pick'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的属性
|
||||
* @returns 新属性值
|
||||
*/
|
||||
public createNewProperty(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一的键名
|
||||
* @param prefix 前缀
|
||||
* @returns 唯一键名
|
||||
*/
|
||||
public generateUniqueKey(prefix: string): string {
|
||||
return `${prefix}_${Date.now()}`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 场景更新相关
|
||||
|
||||
/**
|
||||
* 更新库位的BinTask配置
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 库位名称
|
||||
* @param binTasks BinTask配置数据
|
||||
*/
|
||||
public updateBinTask(pointName: string, locationName: string, binTasks: BinTaskItem[]): void {
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
if (binLocationGroups.length === 0) return;
|
||||
|
||||
// 查找目标库位
|
||||
let targetLocation: any = null;
|
||||
for (const group of binLocationGroups) {
|
||||
if (group && Array.isArray(group.binLocationList)) {
|
||||
const location = group.binLocationList.find(
|
||||
(item: any) => item && item.pointName === pointName && item.instanceName === locationName
|
||||
);
|
||||
if (location) {
|
||||
targetLocation = location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetLocation) {
|
||||
console.warn(`未找到库位: ${pointName} - ${locationName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保property数组存在
|
||||
if (!targetLocation.property) {
|
||||
targetLocation.property = [];
|
||||
}
|
||||
|
||||
// 查找或创建binTask属性
|
||||
let binTaskProperty = targetLocation.property.find((prop: any) => prop && prop.key === 'binTask');
|
||||
if (!binTaskProperty) {
|
||||
binTaskProperty = {
|
||||
key: 'binTask',
|
||||
type: 'string',
|
||||
stringValue: ''
|
||||
};
|
||||
targetLocation.property.push(binTaskProperty);
|
||||
}
|
||||
|
||||
// 更新binTask数据
|
||||
binTaskProperty.stringValue = JSON.stringify(binTasks);
|
||||
|
||||
// 更新原始场景数据
|
||||
this.updateOriginalSceneData(binLocationGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新库位任务配置中的库位名称
|
||||
* @param pointName 动作点名称
|
||||
* @param oldLocationName 旧的库位名称
|
||||
* @param newLocationName 新的库位名称
|
||||
*/
|
||||
public updateBinLocationName(pointName: string, oldLocationName: string, newLocationName: string): void {
|
||||
// 预检查:确保要更新的库位项存在
|
||||
if (!this.checkBinLocationExists(pointName, oldLocationName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
if (binLocationGroups.length === 0) return;
|
||||
|
||||
// 遍历所有库位组,查找匹配的库位并更新名称
|
||||
binLocationGroups.forEach((group) => {
|
||||
if (group && Array.isArray(group.binLocationList)) {
|
||||
group.binLocationList.forEach((item: any) => {
|
||||
if (item && item.pointName === pointName && item.instanceName === oldLocationName) {
|
||||
item.instanceName = newLocationName;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新原始场景数据
|
||||
this.updateOriginalSceneData(binLocationGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除库位任务配置中的库位
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 要删除的库位名称
|
||||
*/
|
||||
public removeBinLocation(pointName: string, locationName: string): void {
|
||||
// 预检查:确保要删除的库位项存在
|
||||
if (!this.checkBinLocationExists(pointName, locationName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
if (binLocationGroups.length === 0) return;
|
||||
|
||||
// 遍历所有库位组,查找匹配的库位并删除
|
||||
binLocationGroups.forEach((group) => {
|
||||
if (group && Array.isArray(group.binLocationList)) {
|
||||
const index = group.binLocationList.findIndex(
|
||||
(item: any) => item && item.pointName === pointName && item.instanceName === locationName
|
||||
);
|
||||
if (index !== -1) {
|
||||
group.binLocationList.splice(index, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 更新原始场景数据
|
||||
this.updateOriginalSceneData(binLocationGroups);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 私有辅助方法
|
||||
|
||||
/**
|
||||
* 获取并验证库位组数据
|
||||
* @returns 库位组数组,如果数据无效则返回空数组
|
||||
*/
|
||||
private getBinLocationGroups(): BinLocationGroup[] {
|
||||
const rawData = this.editor.getBinLocationsList();
|
||||
if (!rawData) return [];
|
||||
|
||||
const binLocationGroups = Array.isArray(rawData)
|
||||
? (rawData as BinLocationGroup[])
|
||||
: (rawData as { binLocationsList: BinLocationGroup[] })?.binLocationsList;
|
||||
|
||||
return Array.isArray(binLocationGroups) ? binLocationGroups : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查库位项是否存在
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 库位名称
|
||||
* @returns 如果库位项存在则返回true,否则返回false
|
||||
*/
|
||||
private checkBinLocationExists(pointName: string, locationName: string): boolean {
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
|
||||
return binLocationGroups.some(
|
||||
(group) =>
|
||||
group &&
|
||||
Array.isArray(group.binLocationList) &&
|
||||
group.binLocationList.some(
|
||||
(item) => item && item.pointName === pointName && item.instanceName === locationName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新原始场景数据
|
||||
* @param binLocationGroups 库位组数据
|
||||
*/
|
||||
private updateOriginalSceneData(binLocationGroups: BinLocationGroup[]): void {
|
||||
// 通过EditorService的公共方法更新原始场景数据
|
||||
this.editor.updateOriginalSceneBinLocations(binLocationGroups);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务数据结构
|
||||
*/
|
||||
export interface TaskData {
|
||||
operations: Record<string, Record<string, any>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* BinTask编辑器操作接口
|
||||
*/
|
||||
export interface BinTaskEditorOperations {
|
||||
// 任务操作
|
||||
addTask: () => void;
|
||||
removeTask: (taskIndex: number) => void;
|
||||
|
||||
// 操作操作
|
||||
addOperation: (taskIndex: number) => void;
|
||||
removeOperation: (taskIndex: number, opKey: string) => void;
|
||||
updateOperationKey: (taskIndex: number, oldKey: string, newKey: string) => void;
|
||||
|
||||
// 属性操作
|
||||
addProperty: (taskIndex: number, opKey: string) => void;
|
||||
removeProperty: (taskIndex: number, opKey: string, propKey: string) => void;
|
||||
updatePropertyKey: (taskIndex: number, opKey: string, oldPropKey: string, newPropKey: string) => void;
|
||||
updatePropertyValue: (taskIndex: number, opKey: string, propKey: string, value: any) => void;
|
||||
changeValueType: (taskIndex: number, opKey: string, propKey: string, newType: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* BinTask编辑器状态管理
|
||||
*/
|
||||
export class BinTaskEditorState {
|
||||
private taskList: TaskData[] = [];
|
||||
private operations: BinTaskEditorOperations;
|
||||
private manager: BinTaskManagerService;
|
||||
|
||||
constructor(operations: BinTaskEditorOperations, manager?: BinTaskManagerService) {
|
||||
this.operations = operations;
|
||||
this.manager = manager || new BinTaskManagerService({} as any); // 提供默认值
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务列表
|
||||
*/
|
||||
public getTaskList(): TaskData[] {
|
||||
return this.taskList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置任务列表
|
||||
*/
|
||||
public setTaskList(taskList: TaskData[]): void {
|
||||
this.taskList = taskList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载初始数据
|
||||
*/
|
||||
public loadInitialData(initialData: BinTaskItem[]): void {
|
||||
this.taskList = this.manager.parseBinTaskData(initialData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取保存数据
|
||||
*/
|
||||
public getSaveData(): BinTaskItem[] {
|
||||
return this.manager.convertToBinTaskData(this.taskList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
public addTask(): void {
|
||||
this.taskList.push({ operations: {} });
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*/
|
||||
public removeTask(taskIndex: number): void {
|
||||
this.taskList.splice(taskIndex, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加操作
|
||||
*/
|
||||
public addOperation(taskIndex: number): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task) {
|
||||
const newOpKey = this.manager.generateUniqueKey('operation');
|
||||
task.operations[newOpKey] = this.manager.createNewOperation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除操作
|
||||
*/
|
||||
public removeOperation(taskIndex: number, opKey: string): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[opKey]) {
|
||||
delete task.operations[opKey];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新操作键名
|
||||
*/
|
||||
public updateOperationKey(taskIndex: number, oldKey: string, newKey: string): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[oldKey] && newKey && newKey !== oldKey) {
|
||||
const operation = task.operations[oldKey];
|
||||
delete task.operations[oldKey];
|
||||
task.operations[newKey] = operation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加属性
|
||||
*/
|
||||
public addProperty(taskIndex: number, opKey: string): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[opKey]) {
|
||||
const newPropKey = this.manager.generateUniqueKey('property');
|
||||
task.operations[opKey][newPropKey] = this.manager.createNewProperty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除属性
|
||||
*/
|
||||
public removeProperty(taskIndex: number, opKey: string, propKey: string): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[opKey] && task.operations[opKey][propKey] !== undefined) {
|
||||
delete task.operations[opKey][propKey];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新属性键名
|
||||
*/
|
||||
public updatePropertyKey(
|
||||
taskIndex: number,
|
||||
opKey: string,
|
||||
oldPropKey: string,
|
||||
newPropKey: string
|
||||
): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[opKey] &&
|
||||
task.operations[opKey][oldPropKey] !== undefined &&
|
||||
newPropKey && newPropKey !== oldPropKey) {
|
||||
const value = task.operations[opKey][oldPropKey];
|
||||
delete task.operations[opKey][oldPropKey];
|
||||
task.operations[opKey][newPropKey] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新属性值
|
||||
*/
|
||||
public updatePropertyValue(taskIndex: number, opKey: string, propKey: string, value: any): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[opKey]) {
|
||||
task.operations[opKey][propKey] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变值类型
|
||||
*/
|
||||
public changeValueType(taskIndex: number, opKey: string, propKey: string, newType: string): void {
|
||||
const task = this.taskList[taskIndex];
|
||||
if (task && task.operations[opKey] && task.operations[opKey][propKey] !== undefined) {
|
||||
const currentValue = task.operations[opKey][propKey];
|
||||
const newValue = this.manager.convertValueType(currentValue, newType);
|
||||
task.operations[opKey][propKey] = newValue;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,8 +13,6 @@ import {
|
||||
} from '@api/map';
|
||||
import type { RobotGroup, RobotInfo, RobotType } from '@api/robot';
|
||||
import type {
|
||||
BinLocationGroup,
|
||||
BinLocationItem,
|
||||
GroupSceneDetail,
|
||||
SceneData,
|
||||
StandardScene,
|
||||
@ -30,6 +28,7 @@ import { BehaviorSubject, debounceTime, filter, map, Subject, switchMap } from '
|
||||
import { reactive, watch } from 'vue';
|
||||
|
||||
import { AreaOperationService } from './area-operation.service';
|
||||
import { BinTaskManagerService } from './bintask-manager.service';
|
||||
import colorConfig from './color/color-config.service';
|
||||
import {
|
||||
drawStorageBackground,
|
||||
@ -132,6 +131,9 @@ export class EditorService extends Meta2d {
|
||||
return JSON.stringify(scene);
|
||||
}
|
||||
|
||||
/** BinTask管理服务实例 */
|
||||
private readonly binTaskManager: BinTaskManagerService;
|
||||
|
||||
/**
|
||||
* 获取库位任务配置数据
|
||||
* @returns 库位任务配置列表
|
||||
@ -140,21 +142,6 @@ export class EditorService extends Meta2d {
|
||||
return (this.#originalSceneData as Record<string, unknown>)?.binLocationsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并验证库位组数据
|
||||
* @returns 库位组数组,如果数据无效则返回空数组
|
||||
*/
|
||||
private getBinLocationGroups(): BinLocationGroup[] {
|
||||
const rawData = this.getBinLocationsList();
|
||||
if (!rawData) return [];
|
||||
|
||||
const binLocationGroups = Array.isArray(rawData)
|
||||
? (rawData as BinLocationGroup[])
|
||||
: (rawData as { binLocationsList: BinLocationGroup[] })?.binLocationsList;
|
||||
|
||||
return Array.isArray(binLocationGroups) ? binLocationGroups : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查库位项是否存在
|
||||
* @param pointName 动作点名称
|
||||
@ -162,16 +149,7 @@ export class EditorService extends Meta2d {
|
||||
* @returns 如果库位项存在则返回true,否则返回false
|
||||
*/
|
||||
public checkBinLocationExists(pointName: string, locationName: string): boolean {
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
|
||||
return binLocationGroups.some(
|
||||
(group) =>
|
||||
group &&
|
||||
Array.isArray(group.binLocationList) &&
|
||||
group.binLocationList.some(
|
||||
(item) => item && item.pointName === pointName && item.instanceName === locationName,
|
||||
),
|
||||
);
|
||||
return this.binTaskManager.hasBinTaskConfig(pointName, locationName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,30 +159,7 @@ export class EditorService extends Meta2d {
|
||||
* @param newLocationName 新的库位名称
|
||||
*/
|
||||
public updateBinLocationName(pointName: string, oldLocationName: string, newLocationName: string): void {
|
||||
// 预检查:确保要更新的库位项存在
|
||||
if (!this.checkBinLocationExists(pointName, oldLocationName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
if (binLocationGroups.length === 0) return;
|
||||
|
||||
// 遍历所有库位组,查找匹配的库位并更新名称
|
||||
binLocationGroups.forEach((group) => {
|
||||
if (group && Array.isArray(group.binLocationList)) {
|
||||
group.binLocationList.forEach((item: BinLocationItem) => {
|
||||
if (item && item.pointName === pointName && item.instanceName === oldLocationName) {
|
||||
item.instanceName = newLocationName;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新原始场景数据
|
||||
if (!this.#originalSceneData) {
|
||||
this.#originalSceneData = {};
|
||||
}
|
||||
(this.#originalSceneData as Record<string, unknown>).binLocationsList = binLocationGroups;
|
||||
this.binTaskManager.updateBinLocationName(pointName, oldLocationName, newLocationName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,27 +168,32 @@ export class EditorService extends Meta2d {
|
||||
* @param locationName 要删除的库位名称
|
||||
*/
|
||||
public removeBinLocation(pointName: string, locationName: string): void {
|
||||
// 预检查:确保要删除的库位项存在
|
||||
if (!this.checkBinLocationExists(pointName, locationName)) {
|
||||
return;
|
||||
}
|
||||
this.binTaskManager.removeBinLocation(pointName, locationName);
|
||||
}
|
||||
|
||||
const binLocationGroups = this.getBinLocationGroups();
|
||||
if (binLocationGroups.length === 0) return;
|
||||
/**
|
||||
* 更新库位的BinTask配置
|
||||
* @param pointName 动作点名称
|
||||
* @param locationName 库位名称
|
||||
* @param binTasks BinTask配置数据
|
||||
*/
|
||||
public updateBinTask(pointName: string, locationName: string, binTasks: any[]): void {
|
||||
this.binTaskManager.updateBinTask(pointName, locationName, binTasks);
|
||||
}
|
||||
|
||||
// 遍历所有库位组,查找匹配的库位并删除
|
||||
binLocationGroups.forEach((group) => {
|
||||
if (group && Array.isArray(group.binLocationList)) {
|
||||
const index = group.binLocationList.findIndex(
|
||||
(item: BinLocationItem) => item && item.pointName === pointName && item.instanceName === locationName,
|
||||
);
|
||||
if (index !== -1) {
|
||||
group.binLocationList.splice(index, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* 获取BinTask管理服务实例
|
||||
* @returns BinTask管理服务实例
|
||||
*/
|
||||
public getBinTaskManager(): BinTaskManagerService {
|
||||
return this.binTaskManager;
|
||||
}
|
||||
|
||||
// 更新原始场景数据
|
||||
/**
|
||||
* 更新原始场景数据中的binLocationsList
|
||||
* @param binLocationGroups 库位组数据
|
||||
*/
|
||||
public updateOriginalSceneBinLocations(binLocationGroups: any[]): void {
|
||||
if (!this.#originalSceneData) {
|
||||
this.#originalSceneData = {};
|
||||
}
|
||||
@ -1669,6 +1629,9 @@ export class EditorService extends Meta2d {
|
||||
// 初始化自动生成库位工具
|
||||
this.autoStorageGenerator = new AutoStorageGenerator(this);
|
||||
|
||||
// 初始化BinTask管理服务
|
||||
this.binTaskManager = new BinTaskManagerService(this);
|
||||
|
||||
// 设置颜色配置服务的编辑器实例
|
||||
colorConfig.setEditorService(this);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user