feat: 更新批量编辑模态框,添加编辑模式切换功能,支持属性编辑和机器人绑定,优化相关逻辑和界面
This commit is contained in:
parent
d3b2bba880
commit
1f87271ebc
@ -3,104 +3,110 @@
|
|||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
title="批量编辑"
|
title="批量编辑"
|
||||||
width="500px"
|
width="500px"
|
||||||
:ok-button-props="{ disabled: !hasChanges }"
|
:ok-button-props="{ disabled: !hasChanges && editMode === 'property' }"
|
||||||
@ok="handleConfirm"
|
@ok="handleConfirm"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
>
|
>
|
||||||
<div class="batch-edit-content">
|
<div class="batch-edit-content">
|
||||||
<!-- 选中元素统计 -->
|
<a-radio-group v-model:value="editMode" button-style="solid" style="margin-bottom: 16px">
|
||||||
<div class="selection-info">
|
<a-radio-button value="property">属性编辑</a-radio-button>
|
||||||
<a-alert
|
<a-radio-button value="binding">机器人绑定</a-radio-button>
|
||||||
:message="`已选择 ${selectedItems.length} 个元素`"
|
</a-radio-group>
|
||||||
:description="selectionDescription"
|
|
||||||
type="info"
|
|
||||||
show-icon
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 点位批量编辑 -->
|
<!-- 属性编辑 -->
|
||||||
<div v-if="pointItems.length > 0" class="edit-section">
|
<div v-if="editMode === 'property'">
|
||||||
<h4>点位编辑 ({{ pointItems.length }} 个)</h4>
|
<!-- 选中元素统计 -->
|
||||||
<a-form layout="vertical">
|
<div class="selection-info">
|
||||||
<a-form-item label="点位类型">
|
<a-alert
|
||||||
<a-select
|
:message="`已选择 ${selectedItems.length} 个元素`"
|
||||||
v-model:value="pointType"
|
:description="selectionDescription"
|
||||||
placeholder="选择点位类型"
|
type="info"
|
||||||
allow-clear
|
show-icon
|
||||||
@change="markChanged"
|
/>
|
||||||
>
|
</div>
|
||||||
<a-select-option
|
|
||||||
v-for="[key, value] in MAP_POINT_TYPES"
|
|
||||||
:key="value"
|
|
||||||
:value="value"
|
|
||||||
>
|
|
||||||
{{ key }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 路线批量编辑 -->
|
<!-- 点位批量编辑 -->
|
||||||
<div v-if="lineItems.length > 0" class="edit-section">
|
<div v-if="pointItems.length > 0" class="edit-section">
|
||||||
<h4>路线编辑 ({{ lineItems.length }} 个)</h4>
|
<h4>点位编辑 ({{ pointItems.length }} 个)</h4>
|
||||||
<a-form layout="vertical">
|
<a-form layout="vertical">
|
||||||
<a-form-item label="通行类型">
|
<a-form-item label="点位类型">
|
||||||
<a-select
|
<a-select v-model:value="pointType" placeholder="选择点位类型" allow-clear @change="markChanged">
|
||||||
v-model:value="routePassType"
|
<a-select-option v-for="[key, value] in MAP_POINT_TYPES" :key="value" :value="value">
|
||||||
placeholder="选择通行类型"
|
{{ key }}
|
||||||
allow-clear
|
</a-select-option>
|
||||||
@change="markChanged"
|
</a-select>
|
||||||
>
|
</a-form-item>
|
||||||
<a-select-option
|
</a-form>
|
||||||
v-for="[key, value] in MAP_ROUTE_PASS_TYPES"
|
</div>
|
||||||
:key="value"
|
|
||||||
:value="value"
|
|
||||||
>
|
|
||||||
{{ key }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 预览区域 -->
|
<!-- 路线批量编辑 -->
|
||||||
<div v-if="hasChanges" class="preview-section">
|
<div v-if="lineItems.length > 0" class="edit-section">
|
||||||
<h4>预览更改</h4>
|
<h4>路线编辑 ({{ lineItems.length }} 个)</h4>
|
||||||
<div class="preview-list">
|
<a-form layout="vertical">
|
||||||
<div
|
<a-form-item label="通行类型">
|
||||||
v-for="item in selectedItems"
|
<a-select v-model:value="routePassType" placeholder="选择通行类型" allow-clear @change="markChanged">
|
||||||
:key="item.id"
|
<a-select-option v-for="[key, value] in MAP_ROUTE_PASS_TYPES" :key="value" :value="value">
|
||||||
class="preview-item"
|
{{ key }}
|
||||||
>
|
</a-select-option>
|
||||||
<span class="item-name">{{ getItemName(item) }}</span>
|
</a-select>
|
||||||
<span class="item-type">{{ getItemType(item) }}</span>
|
</a-form-item>
|
||||||
<div class="changes">
|
</a-form>
|
||||||
<a-tag v-if="getPointChanges(item).length" color="blue" class="change-tag">
|
</div>
|
||||||
点位: {{ getPointChanges(item).join(', ') }}
|
|
||||||
</a-tag>
|
<!-- 预览区域 -->
|
||||||
<a-tag v-if="getRouteChanges(item).length" color="green" class="change-tag">
|
<div v-if="hasChanges" class="preview-section">
|
||||||
路线: {{ getRouteChanges(item).join(', ') }}
|
<h4>预览更改</h4>
|
||||||
</a-tag>
|
<div class="preview-list">
|
||||||
|
<div v-for="item in selectedItems" :key="item.id" class="preview-item">
|
||||||
|
<span class="item-name">{{ getItemName(item) }}</span>
|
||||||
|
<span class="item-type">{{ getItemType(item) }}</span>
|
||||||
|
<div class="changes">
|
||||||
|
<a-tag v-if="getPointChanges(item).length" color="blue" class="change-tag">
|
||||||
|
点位: {{ getPointChanges(item).join(', ') }}
|
||||||
|
</a-tag>
|
||||||
|
<a-tag v-if="getRouteChanges(item).length" color="green" class="change-tag">
|
||||||
|
路线: {{ getRouteChanges(item).join(', ') }}
|
||||||
|
</a-tag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 机器人绑定 -->
|
||||||
|
<div v-if="editMode === 'binding'">
|
||||||
|
<div class="selection-info">
|
||||||
|
<a-alert :message="`已选择 ${pointItems.length} 个点位`" type="info" show-icon />
|
||||||
|
</div>
|
||||||
|
<div v-if="chargingPoints.length > 0" class="edit-section">
|
||||||
|
<h4>充电点 ({{ chargingPoints.length }} 个)</h4>
|
||||||
|
<a-button type="primary" @click="handleBatchBind(chargingPoints)">批量绑定机器人</a-button>
|
||||||
|
</div>
|
||||||
|
<div v-if="parkingPoints.length > 0" class="edit-section">
|
||||||
|
<h4>停靠点 ({{ parkingPoints.length }} 个)</h4>
|
||||||
|
<a-button type="primary" @click="handleBatchBind(parkingPoints)">批量绑定机器人</a-button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="chargingPoints.length === 0 && parkingPoints.length === 0 && pointItems.length > 0"
|
||||||
|
class="edit-section"
|
||||||
|
>
|
||||||
|
<h4>无符合条件的点位</h4>
|
||||||
|
<p>仅充电点和停靠点支持批量绑定机器人。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
<robot-bind-modal :token="editorToken" ref="robotBindModalRef" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, ref, watch } from 'vue';
|
import { computed, type InjectionKey, nextTick, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
|
||||||
|
|
||||||
import type { MapPen } from '../../apis/map';
|
import type { MapPen } from '../../apis/map';
|
||||||
import {
|
import { MAP_POINT_TYPES, MAP_ROUTE_PASS_TYPES, MapPointType, MapRoutePassType } from '../../apis/map';
|
||||||
MAP_POINT_TYPES,
|
|
||||||
MAP_ROUTE_PASS_TYPES,
|
|
||||||
MapPointType,
|
|
||||||
MapRoutePassType
|
|
||||||
} from '../../apis/map';
|
|
||||||
import type { EditorService } from '../../services/editor.service';
|
import type { EditorService } from '../../services/editor.service';
|
||||||
|
import type { RobotBindModalRef } from './robot-bind-modal.vue';
|
||||||
|
import RobotBindModal from './robot-bind-modal.vue';
|
||||||
|
|
||||||
// 点位类型对应的尺寸和图像配置
|
// 点位类型对应的尺寸和图像配置
|
||||||
const getPointTypeConfig = (type: MapPointType, editor: EditorService) => {
|
const getPointTypeConfig = (type: MapPointType, editor: EditorService) => {
|
||||||
@ -108,12 +114,12 @@ const getPointTypeConfig = (type: MapPointType, editor: EditorService) => {
|
|||||||
const height = type < 10 ? 24 : 60;
|
const height = type < 10 ? 24 : 60;
|
||||||
const lineWidth = type < 10 ? 2 : 3;
|
const lineWidth = type < 10 ? 2 : 3;
|
||||||
const iconSize = type < 10 ? 4 : 10;
|
const iconSize = type < 10 ? 4 : 10;
|
||||||
|
|
||||||
// 使用与 editor.service.ts 中 #mapPointImage 相同的逻辑
|
// 使用与 editor.service.ts 中 #mapPointImage 相同的逻辑
|
||||||
const theme = editor.data().theme;
|
const theme = editor.data().theme;
|
||||||
// 使用相对路径,图片文件在 public/point/ 目录下
|
// 使用相对路径,图片文件在 public/point/ 目录下
|
||||||
const image = type < 10 ? '' : `./point/${type}-${theme}.png`;
|
const image = type < 10 ? '' : `./point/${type}-${theme}.png`;
|
||||||
|
|
||||||
return { width, height, lineWidth, iconSize, image };
|
return { width, height, lineWidth, iconSize, image };
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,17 +139,29 @@ const emit = defineEmits<Emits>();
|
|||||||
|
|
||||||
const modalVisible = computed({
|
const modalVisible = computed({
|
||||||
get: () => props.visible,
|
get: () => props.visible,
|
||||||
set: (value) => emit('update:visible', value)
|
set: (value) => emit('update:visible', value),
|
||||||
});
|
});
|
||||||
|
|
||||||
// 分离点位和路线
|
// 分离点位和路线
|
||||||
const pointItems = computed(() =>
|
const pointItems = computed(() => props.selectedItems.filter((item) => item.name === 'point'));
|
||||||
props.selectedItems.filter(item => item.name === 'point')
|
|
||||||
);
|
|
||||||
|
|
||||||
const lineItems = computed(() =>
|
const lineItems = computed(() => props.selectedItems.filter((item) => item.name === 'line'));
|
||||||
props.selectedItems.filter(item => item.name === 'line')
|
|
||||||
);
|
// 编辑模式
|
||||||
|
const editMode = ref<'property' | 'binding'>('property');
|
||||||
|
|
||||||
|
// 机器人绑定相关
|
||||||
|
const robotBindModalRef = ref<RobotBindModalRef>();
|
||||||
|
const editorToken: InjectionKey<ShallowRef<EditorService>> = Symbol('editor');
|
||||||
|
provide(editorToken, shallowRef(props.editor));
|
||||||
|
|
||||||
|
const chargingPoints = computed(() => pointItems.value.filter((item) => item.point?.type === MapPointType.充电点));
|
||||||
|
|
||||||
|
const parkingPoints = computed(() => pointItems.value.filter((item) => item.point?.type === MapPointType.停靠点));
|
||||||
|
|
||||||
|
const handleBatchBind = (pens: MapPen[]) => {
|
||||||
|
robotBindModalRef.value?.open(pens);
|
||||||
|
};
|
||||||
|
|
||||||
// 编辑状态
|
// 编辑状态
|
||||||
const pointType = ref<MapPointType>();
|
const pointType = ref<MapPointType>();
|
||||||
@ -161,14 +179,18 @@ const resetForm = () => {
|
|||||||
pointType.value = undefined;
|
pointType.value = undefined;
|
||||||
routePassType.value = undefined;
|
routePassType.value = undefined;
|
||||||
hasChanges.value = false;
|
hasChanges.value = false;
|
||||||
|
editMode.value = 'property';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听模态框显示状态
|
// 监听模态框显示状态
|
||||||
watch(() => props.visible, (visible) => {
|
watch(
|
||||||
if (visible) {
|
() => props.visible,
|
||||||
resetForm();
|
(visible) => {
|
||||||
}
|
if (visible) {
|
||||||
});
|
resetForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// 选中元素描述
|
// 选中元素描述
|
||||||
const selectionDescription = computed(() => {
|
const selectionDescription = computed(() => {
|
||||||
@ -182,8 +204,8 @@ const selectionDescription = computed(() => {
|
|||||||
|
|
||||||
// 获取元素名称
|
// 获取元素名称
|
||||||
const getItemName = (item: MapPen) => {
|
const getItemName = (item: MapPen) => {
|
||||||
if(item.tags?.includes('route')){
|
if (item.tags?.includes('route')) {
|
||||||
return item.desc||item.label || item.id || '未命名';
|
return item.desc || item.label || item.id || '未命名';
|
||||||
}
|
}
|
||||||
return item.label || item.id || '未命名';
|
return item.label || item.id || '未命名';
|
||||||
};
|
};
|
||||||
@ -192,7 +214,7 @@ const getItemName = (item: MapPen) => {
|
|||||||
const getItemType = (item: MapPen) => {
|
const getItemType = (item: MapPen) => {
|
||||||
if (item.name === 'point') {
|
if (item.name === 'point') {
|
||||||
const pointTypeName = Object.keys(MapPointType).find(
|
const pointTypeName = Object.keys(MapPointType).find(
|
||||||
key => MapPointType[key as keyof typeof MapPointType] === item.point?.type
|
(key) => MapPointType[key as keyof typeof MapPointType] === item.point?.type,
|
||||||
);
|
);
|
||||||
return `点位-${pointTypeName || '未知'}`;
|
return `点位-${pointTypeName || '未知'}`;
|
||||||
} else if (item.name === 'line') {
|
} else if (item.name === 'line') {
|
||||||
@ -204,90 +226,93 @@ const getItemType = (item: MapPen) => {
|
|||||||
// 获取点位变更描述
|
// 获取点位变更描述
|
||||||
const getPointChanges = (item: MapPen) => {
|
const getPointChanges = (item: MapPen) => {
|
||||||
if (item.name !== 'point' || !pointType.value) return [];
|
if (item.name !== 'point' || !pointType.value) return [];
|
||||||
|
|
||||||
const currentType = item.point?.type;
|
const currentType = item.point?.type;
|
||||||
if (currentType === pointType.value) return [];
|
if (currentType === pointType.value) return [];
|
||||||
|
|
||||||
const currentTypeName = Object.keys(MapPointType).find(
|
const currentTypeName = Object.keys(MapPointType).find(
|
||||||
key => MapPointType[key as keyof typeof MapPointType] === currentType
|
(key) => MapPointType[key as keyof typeof MapPointType] === currentType,
|
||||||
);
|
);
|
||||||
const newTypeName = Object.keys(MapPointType).find(
|
const newTypeName = Object.keys(MapPointType).find(
|
||||||
key => MapPointType[key as keyof typeof MapPointType] === pointType.value
|
(key) => MapPointType[key as keyof typeof MapPointType] === pointType.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
return [`类型: ${currentTypeName || '未知'} → ${newTypeName}`];
|
return [`类型: ${currentTypeName || '未知'} → ${newTypeName}`];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取路线变更描述
|
// 获取路线变更描述
|
||||||
const getRouteChanges = (item: MapPen) => {
|
const getRouteChanges = (item: MapPen) => {
|
||||||
if (item.name !== 'line') return [];
|
if (item.name !== 'line') return [];
|
||||||
|
|
||||||
const changes: string[] = [];
|
const changes: string[] = [];
|
||||||
|
|
||||||
if (routePassType.value !== undefined && item.route?.pass !== routePassType.value) {
|
if (routePassType.value !== undefined && item.route?.pass !== routePassType.value) {
|
||||||
const currentPassName = Object.keys(MapRoutePassType).find(
|
const currentPassName = Object.keys(MapRoutePassType).find(
|
||||||
key => MapRoutePassType[key as keyof typeof MapRoutePassType] === item.route?.pass
|
(key) => MapRoutePassType[key as keyof typeof MapRoutePassType] === item.route?.pass,
|
||||||
);
|
);
|
||||||
const newPassName = Object.keys(MapRoutePassType).find(
|
const newPassName = Object.keys(MapRoutePassType).find(
|
||||||
key => MapRoutePassType[key as keyof typeof MapRoutePassType] === routePassType.value
|
(key) => MapRoutePassType[key as keyof typeof MapRoutePassType] === routePassType.value,
|
||||||
);
|
);
|
||||||
changes.push(`通行: ${currentPassName || '未知'} → ${newPassName}`);
|
changes.push(`通行: ${currentPassName || '未知'} → ${newPassName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changes;
|
return changes;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 确认更改
|
// 确认更改
|
||||||
const handleConfirm = () => {
|
const handleConfirm = () => {
|
||||||
|
if (editMode.value !== 'property') {
|
||||||
|
modalVisible.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
const updates: Array<{ id: string; updates: Partial<MapPen> }> = [];
|
const updates: Array<{ id: string; updates: Partial<MapPen> }> = [];
|
||||||
|
|
||||||
// 处理点位更新
|
// 处理点位更新
|
||||||
pointItems.value.forEach(item => {
|
pointItems.value.forEach((item) => {
|
||||||
if (pointType.value) {
|
if (pointType.value) {
|
||||||
const pointConfig = getPointTypeConfig(pointType.value, props.editor);
|
const pointConfig = getPointTypeConfig(pointType.value, props.editor);
|
||||||
const rect = props.editor.getPointRect(item);
|
const rect = props.editor.getPointRect(item);
|
||||||
|
|
||||||
updates.push({
|
updates.push({
|
||||||
id: item.id!,
|
id: item.id!,
|
||||||
updates: {
|
updates: {
|
||||||
// 更新点位类型
|
// 更新点位类型
|
||||||
point: {
|
point: {
|
||||||
...item.point,
|
...item.point,
|
||||||
type: pointType.value
|
type: pointType.value,
|
||||||
},
|
},
|
||||||
// 更新点位尺寸和图像
|
// 更新点位尺寸和图像
|
||||||
...pointConfig,
|
...pointConfig,
|
||||||
// 调整位置以保持中心点不变
|
// 调整位置以保持中心点不变
|
||||||
x: rect ? rect.x - pointConfig.width / 2 : item.x,
|
x: rect ? rect.x - pointConfig.width / 2 : item.x,
|
||||||
y: rect ? rect.y - pointConfig.height / 2 : item.y,
|
y: rect ? rect.y - pointConfig.height / 2 : item.y,
|
||||||
|
},
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理路线更新
|
// 处理路线更新
|
||||||
lineItems.value.forEach(item => {
|
lineItems.value.forEach((item) => {
|
||||||
if (item.route && routePassType.value !== undefined) {
|
if (item.route && routePassType.value !== undefined) {
|
||||||
const routeUpdates: Partial<MapPen> = {
|
const routeUpdates: Partial<MapPen> = {
|
||||||
route: {
|
route: {
|
||||||
...item.route,
|
...item.route,
|
||||||
pass: routePassType.value
|
pass: routePassType.value,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
updates.push({
|
updates.push({
|
||||||
id: item.id!,
|
id: item.id!,
|
||||||
updates: routeUpdates
|
updates: routeUpdates,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
emit('update', updates);
|
emit('update', updates);
|
||||||
|
|
||||||
// 立即关闭弹窗,提供更好的用户体验
|
// 立即关闭弹窗,提供更好的用户体验
|
||||||
modalVisible.value = false;
|
modalVisible.value = false;
|
||||||
|
|
||||||
// 在后台异步重新加载主题,避免界面卡顿
|
// 在后台异步重新加载主题,避免界面卡顿
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 使用 setTimeout 确保点位更新完成后再重新加载主题
|
// 使用 setTimeout 确保点位更新完成后再重新加载主题
|
||||||
@ -304,7 +329,7 @@ const handleCancel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'BatchEditModal'
|
name: 'BatchEditModal',
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -315,28 +340,28 @@ defineOptions({
|
|||||||
.selection-info {
|
.selection-info {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-section {
|
.edit-section {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin: 0 0 12px 0;
|
margin: 0 0 12px 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-section {
|
.preview-section {
|
||||||
h4 {
|
h4 {
|
||||||
margin: 0 0 12px 0;
|
margin: 0 0 12px 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-list {
|
.preview-list {
|
||||||
max-height: 150px;
|
max-height: 150px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.preview-item {
|
.preview-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -344,32 +369,32 @@ defineOptions({
|
|||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
.item-name {
|
.item-name {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-type {
|
.item-type {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.changes {
|
.changes {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
.ant-tag {
|
.ant-tag {
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.change-tag {
|
.change-tag {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border: 1px solid currentColor;
|
border: 1px solid currentColor;
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
// 突出显示箭头符号
|
// 突出显示箭头符号
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
@ -395,22 +420,22 @@ defineOptions({
|
|||||||
.edit-section {
|
.edit-section {
|
||||||
background: theme.get-color(fill3);
|
background: theme.get-color(fill3);
|
||||||
border: 1px solid theme.get-color(border2);
|
border: 1px solid theme.get-color(border2);
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
color: theme.get-color(primary);
|
color: theme.get-color(primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-section {
|
.preview-section {
|
||||||
h4 {
|
h4 {
|
||||||
color: theme.get-color(success);
|
color: theme.get-color(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-list {
|
.preview-list {
|
||||||
.preview-item {
|
.preview-item {
|
||||||
background: theme.get-color(bg_component);
|
background: theme.get-color(bg_component);
|
||||||
border: 1px solid theme.get-color(border1);
|
border: 1px solid theme.get-color(border1);
|
||||||
|
|
||||||
.item-type {
|
.item-type {
|
||||||
color: theme.get-color(text3);
|
color: theme.get-color(text3);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,13 +12,23 @@ const editor = inject(props.token)!;
|
|||||||
|
|
||||||
export type RobotBindModalRef = Ref;
|
export type RobotBindModalRef = Ref;
|
||||||
type Ref = {
|
type Ref = {
|
||||||
open: (pen: MapPen) => void;
|
open: (pen: MapPen | MapPen[]) => void;
|
||||||
};
|
};
|
||||||
|
const targetPens = ref<MapPen[]>([]);
|
||||||
const open: Ref['open'] = (pen) => {
|
const open: Ref['open'] = (pen) => {
|
||||||
if (!pen?.id) return;
|
if (!pen) return;
|
||||||
|
const pens = Array.isArray(pen) ? pen : [pen];
|
||||||
|
if (pens.length === 0) return;
|
||||||
|
|
||||||
keyword.value = '';
|
keyword.value = '';
|
||||||
id.value = pen.id;
|
targetPens.value = pens;
|
||||||
selected.value = pen.point?.robots ?? [];
|
|
||||||
|
if (pens.length === 1) {
|
||||||
|
selected.value = pens[0].point?.robots ?? [];
|
||||||
|
} else {
|
||||||
|
selected.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
show.value = true;
|
show.value = true;
|
||||||
};
|
};
|
||||||
defineExpose<Ref>({ open });
|
defineExpose<Ref>({ open });
|
||||||
@ -28,11 +38,15 @@ const keyword = ref<string>('');
|
|||||||
|
|
||||||
const robots = computed<RobotInfo[]>(() => editor.value.robots.filter(({ label }) => label.includes(keyword.value)));
|
const robots = computed<RobotInfo[]>(() => editor.value.robots.filter(({ label }) => label.includes(keyword.value)));
|
||||||
|
|
||||||
const id = ref<string>('');
|
|
||||||
const selected = ref<string[]>([]);
|
const selected = ref<string[]>([]);
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
editor.value.updatePoint(id.value, { robots: toRaw(selected.value) });
|
const robotIds = toRaw(selected.value);
|
||||||
|
targetPens.value.forEach((pen) => {
|
||||||
|
if (pen.id) {
|
||||||
|
editor.value.updatePoint(pen.id, { robots: robotIds });
|
||||||
|
}
|
||||||
|
});
|
||||||
show.value = false;
|
show.value = false;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user