256 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="point-menu">
<!-- 菜单头部显示站点信息 -->
<div class="menu-header">
<div class="point-info">
<div class="point-icon">📍</div>
<div class="point-details">
<div class="point-name">{{ pointInfo?.name || '未知站点' }}</div>
<div class="point-id">ID: {{ pointInfo?.id }}</div>
</div>
</div>
</div>
<!-- 菜单分割线 -->
<a-divider style="margin: 12px 0;" />
<!-- 菜单选项 -->
<div class="menu-options">
<!-- 导航至此站点 -->
<div
class="menu-item"
:class="{ disabled: !canNavigate }"
@click="handleNavigateToPoint"
>
<div class="menu-item-content">
<span class="menu-icon">🧭</span>
<span class="menu-text">导航至此站点</span>
</div>
<div class="menu-description">
选择机器人并下发移动任务到当前站点
</div>
</div>
</div>
<!-- 机器人选择弹窗 -->
<RobotSelectorModal
v-model:open="showRobotSelector"
:target-point-name="pointInfo?.name"
@confirm="handleRobotSelected"
@cancel="handleRobotSelectorCancel"
/>
</div>
</template>
<script setup lang="ts">
import { message } from 'ant-design-vue';
import { computed, ref } from 'vue';
import type { RobotInfo } from '../../apis/robot';
import { executeNavigateToPoint } from '../../services/context-menu/point-menu.service';
import RobotSelectorModal from '../modal/robot-selector-modal.vue';
interface Props {
menuType?: 'point' | 'default';
pointInfo?: {
id: string;
name: string;
type: string;
};
}
interface Emits {
(e: 'actionComplete', data: {
action: string;
point: any;
success: boolean;
message?: string;
}): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
// 响应式数据
const showRobotSelector = ref(false);
const loading = ref(false);
// 计算属性
const pointInfo = computed(() => props.pointInfo);
// 判断是否可以进行导航
const canNavigate = computed(() => {
return pointInfo.value?.name && pointInfo.value?.id;
});
// 处理导航到站点
const handleNavigateToPoint = async () => {
if (!canNavigate.value) {
message.warning('站点信息不完整,无法导航');
return;
}
// 打开机器人选择弹窗
showRobotSelector.value = true;
};
// 处理机器人选择
const handleRobotSelected = async (data: { robot: RobotInfo; targetPointName: string }) => {
if (!pointInfo.value) {
message.error('站点信息丢失,无法执行导航');
return;
}
loading.value = true;
try {
console.log('选择机器人进行导航:', {
robot: data.robot.label,
targetPoint: data.targetPointName,
});
// 调用导航API
const result = await executeNavigateToPoint(
pointInfo.value.id,
pointInfo.value.name,
data.robot.id,
data.robot.label
);
// 发送操作完成事件
emit('actionComplete', {
action: 'navigateToPoint',
point: pointInfo.value,
success: result.success,
message: result.message,
});
// 显示结果提示
if (result.success) {
message.success(`已为机器人 ${data.robot.label} 下发导航任务到 ${data.targetPointName}`);
} else {
// 如果API返回了错误信息让全局错误处理显示
if (!result.message) {
message.error('导航任务下发失败');
}
}
} catch (error) {
console.error('导航操作失败:', error);
// 发送失败事件
emit('actionComplete', {
action: 'navigateToPoint',
point: pointInfo.value,
success: false,
message: undefined, // 让全局错误处理显示
});
message.error('导航操作失败');
} finally {
loading.value = false;
}
};
// 处理机器人选择弹窗取消
const handleRobotSelectorCancel = () => {
showRobotSelector.value = false;
console.log('用户取消了机器人选择');
};
</script>
<style scoped>
.point-menu {
width: 100%;
min-width: 320px;
max-width: 400px;
padding: 8px;
}
/* 菜单头部 */
.menu-header {
padding: 8px 12px;
}
.point-info {
display: flex;
align-items: center;
gap: 12px;
}
.point-icon {
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.point-details {
flex: 1;
}
.point-name {
font-size: 14px;
font-weight: 500;
color: #262626;
margin-bottom: 4px;
}
.point-id {
font-size: 12px;
color: #8c8c8c;
}
/* 菜单选项 */
.menu-options {
padding: 0 4px;
}
.menu-item {
padding: 12px;
margin: 4px 0;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
}
.menu-item:hover:not(.disabled) {
background-color: #f5f5f5;
}
.menu-item.disabled {
opacity: 0.6;
cursor: not-allowed;
}
.menu-item-content {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 4px;
}
.menu-icon {
font-size: 16px;
width: 20px;
text-align: center;
}
.menu-text {
font-size: 14px;
font-weight: 500;
color: #262626;
}
.menu-description {
font-size: 12px;
color: #8c8c8c;
margin-left: 32px;
}
/* 分割线样式 */
:deep(.ant-divider) {
border-color: #f0f0f0;
}
</style>