feat: 添加右键菜单功能,优化机器人列表交互,增强用户体验
This commit is contained in:
parent
fe1ef44e9d
commit
c32dd105ef
@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { type RobotGroup, type RobotInfo, seizeRobotByIds } from '@api/robot';
|
||||
import { type RobotGroup, type RobotInfo } from '@api/robot';
|
||||
import type { RobotAddModalRef } from '@common/modal/robot-add-modal.vue';
|
||||
import type { RobotGroupRenameModalRef } from '@common/modal/robot-group-rename-modal.vue';
|
||||
import type { RobotRegisterModalRef } from '@common/modal/robot-register-modal.vue';
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import { Modal } from 'ant-design-vue';
|
||||
import { watch } from 'vue';
|
||||
import { reactive } from 'vue';
|
||||
import { computed, inject, type InjectionKey, ref, type ShallowRef, shallowRef } from 'vue';
|
||||
import { computed, inject, type InjectionKey, reactive, ref, type ShallowRef, shallowRef, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { createContextMenuManager, handleContextMenu } from '../services/context-menu';
|
||||
import ContextMenu from './context-menu/context-menu.vue';
|
||||
|
||||
type Props = {
|
||||
token: InjectionKey<ShallowRef<EditorService>>;
|
||||
@ -27,15 +27,25 @@ type Events = {
|
||||
const emit = defineEmits<Events>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
// const router = useRouter(); // 暂时注释掉,保留以备将来使用
|
||||
|
||||
//#region 接口
|
||||
const seizeRobots = async () => {
|
||||
const res = await seizeRobotByIds([...selected.keys()]);
|
||||
editor.value.updateRobots(res, { canControl: true });
|
||||
//#region 右键菜单
|
||||
const contextMenuManager = createContextMenuManager();
|
||||
const contextMenuState = ref(contextMenuManager.getState());
|
||||
|
||||
// 订阅右键菜单状态变化
|
||||
contextMenuManager.subscribe((state) => {
|
||||
contextMenuState.value = state;
|
||||
});
|
||||
|
||||
// 处理右键菜单关闭
|
||||
const handleContextMenuClose = () => {
|
||||
contextMenuManager.close();
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
const keyword = ref<string>('');
|
||||
|
||||
//#region 机器人列表
|
||||
@ -75,6 +85,22 @@ const selectRobot = (id: RobotInfo['id'], checked: boolean) => {
|
||||
selected.delete(id);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理机器人右键点击
|
||||
const handleRobotRightClick = (event: MouseEvent, robot: RobotInfo) => {
|
||||
// 为事件目标添加机器人标识
|
||||
if (event.target && event.target instanceof HTMLElement) {
|
||||
event.target.setAttribute('data-robot-id', robot.id);
|
||||
event.target.setAttribute('data-robot-type', 'robot');
|
||||
}
|
||||
|
||||
// 处理右键菜单 - handleContextMenu 内部会处理 preventDefault 和 stopPropagation
|
||||
handleContextMenu(event, contextMenuManager, {
|
||||
robotService: {
|
||||
getRobotById: (id: string) => editor.value.getRobotById(id)
|
||||
}
|
||||
});
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//#region 机器人组操作
|
||||
@ -92,16 +118,6 @@ const toDeleteGroup = (id: RobotGroup['id']) =>
|
||||
onOk: () => editor.value.deleteRobotGroup(id),
|
||||
});
|
||||
|
||||
const toEditGroup = (id: RobotGroup['id']) =>
|
||||
Modal.confirm({
|
||||
class: 'confirm',
|
||||
title: t('您确定要编辑该机器人组吗?'),
|
||||
content: t('请确保当前场景已经保存,否则将导致当前场景数据丢失。'),
|
||||
centered: true,
|
||||
cancelText: t('取消'),
|
||||
okText: t('编辑'),
|
||||
onOk: () => router.push({ name: '组编辑', params: { sid: props.sid, id } }),
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region 机器人操作
|
||||
@ -137,6 +153,16 @@ const toRemoveRobots = () =>
|
||||
<RobotAddModal ref="refAddRobot" :token="token" />
|
||||
<RobotRegisterModal ref="refRegisterRobot" :token="token" />
|
||||
<RobotGroupRenameModal ref="refRenameGroup" :token="token" />
|
||||
|
||||
<!-- 右键菜单 -->
|
||||
<ContextMenu
|
||||
:visible="contextMenuState.visible"
|
||||
:x="contextMenuState.x"
|
||||
:y="contextMenuState.y"
|
||||
:menu-type="contextMenuState.menuType"
|
||||
:robot-info="contextMenuState.robotInfo"
|
||||
@close="handleContextMenuClose"
|
||||
/>
|
||||
|
||||
<a-flex class="full" vertical>
|
||||
<a-input class="search mb-16" :placeholder="$t('请输入搜索关键字')" v-model:value="keyword">
|
||||
@ -148,16 +174,6 @@ const toRemoveRobots = () =>
|
||||
<a-flex v-if="editable" class="mb-8" style="height: 32px" justify="space-between" align="center">
|
||||
<a-checkbox :checked="isAllSelected" @change="selectAll($event.target.checked)">{{ $t('全选') }}</a-checkbox>
|
||||
<a-space align="center">
|
||||
<a-button
|
||||
v-if="false"
|
||||
class="icon-btn panel-btn"
|
||||
size="small"
|
||||
:title="$t('抢占控制权')"
|
||||
@click="seizeRobots"
|
||||
:disabled="!selected.size"
|
||||
>
|
||||
<i class="mask control" />
|
||||
</a-button>
|
||||
<a-button
|
||||
class="icon-btn panel-btn"
|
||||
size="small"
|
||||
@ -241,6 +257,7 @@ const toRemoveRobots = () =>
|
||||
:class="{ 'ph-16': !editable, 'pl-12': editable, 'pr-8': editable, selected: item.id === current }"
|
||||
style="height: 36px"
|
||||
@click="emit('change', item.id)"
|
||||
@contextmenu="handleRobotRightClick($event, item)"
|
||||
>
|
||||
<template v-if="editable" #actions>
|
||||
<a-button
|
||||
@ -283,4 +300,14 @@ const toRemoveRobots = () =>
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
// 机器人列表项样式
|
||||
.ant-list-item {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -165,7 +165,10 @@ export function parseEventData(event: MouseEvent | PointerEvent): ParsedEventDat
|
||||
}
|
||||
|
||||
// 回退到DOM元素检查
|
||||
if (target?.closest('.robot-item')) {
|
||||
// 检查机器人类型 - 支持多种选择器
|
||||
if (target?.closest('.robot-item') ||
|
||||
target?.closest('.ant-list-item') && target.dataset.robotType === 'robot' ||
|
||||
target?.classList.contains('ant-list-item') && target.dataset.robotType === 'robot') {
|
||||
return {
|
||||
type: 'robot',
|
||||
id: target.dataset.robotId || target.id,
|
||||
|
Loading…
x
Reference in New Issue
Block a user