feat: 在上下文菜单中添加拖拽功能,优化菜单样式并更新依赖项以提升用户体验
This commit is contained in:
parent
e347a6f633
commit
aa568b2da4
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@meta2d/core": "^1.0.78",
|
||||
"@vueuse/core": "^13.9.0",
|
||||
"@vueuse/rxjs": "^13.1.0",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"axios": "^1.8.4",
|
||||
|
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@ -14,6 +14,9 @@ importers:
|
||||
'@meta2d/core':
|
||||
specifier: ^1.0.78
|
||||
version: 1.0.95
|
||||
'@vueuse/core':
|
||||
specifier: ^13.9.0
|
||||
version: 13.9.0(vue@3.5.20(typescript@5.7.3))
|
||||
'@vueuse/rxjs':
|
||||
specifier: ^13.1.0
|
||||
version: 13.7.0(rxjs@7.8.2)(vue@3.5.20(typescript@5.7.3))
|
||||
@ -669,6 +672,9 @@ packages:
|
||||
'@types/node@22.18.0':
|
||||
resolution: {integrity: sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==}
|
||||
|
||||
'@types/web-bluetooth@0.0.21':
|
||||
resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.41.0':
|
||||
resolution: {integrity: sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@ -807,6 +813,14 @@ packages:
|
||||
vue:
|
||||
optional: true
|
||||
|
||||
'@vueuse/core@13.9.0':
|
||||
resolution: {integrity: sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==}
|
||||
peerDependencies:
|
||||
vue: ^3.5.0
|
||||
|
||||
'@vueuse/metadata@13.9.0':
|
||||
resolution: {integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==}
|
||||
|
||||
'@vueuse/rxjs@13.7.0':
|
||||
resolution: {integrity: sha512-PawsGxhmv7yvp2dhqtu1plsaMdMRQ/2TiYCJHIMTG+RFP/761q0+uVKNOhmuaExhj5bdAk23FhQ9Cl9Sn67RUQ==}
|
||||
peerDependencies:
|
||||
@ -818,6 +832,11 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.5.0
|
||||
|
||||
'@vueuse/shared@13.9.0':
|
||||
resolution: {integrity: sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==}
|
||||
peerDependencies:
|
||||
vue: ^3.5.0
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
@ -2684,6 +2703,8 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/web-bluetooth@0.0.21': {}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.7.3))(eslint@9.34.0)(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
@ -2891,6 +2912,15 @@ snapshots:
|
||||
typescript: 5.7.3
|
||||
vue: 3.5.20(typescript@5.7.3)
|
||||
|
||||
'@vueuse/core@13.9.0(vue@3.5.20(typescript@5.7.3))':
|
||||
dependencies:
|
||||
'@types/web-bluetooth': 0.0.21
|
||||
'@vueuse/metadata': 13.9.0
|
||||
'@vueuse/shared': 13.9.0(vue@3.5.20(typescript@5.7.3))
|
||||
vue: 3.5.20(typescript@5.7.3)
|
||||
|
||||
'@vueuse/metadata@13.9.0': {}
|
||||
|
||||
'@vueuse/rxjs@13.7.0(rxjs@7.8.2)(vue@3.5.20(typescript@5.7.3))':
|
||||
dependencies:
|
||||
'@vueuse/shared': 13.7.0(vue@3.5.20(typescript@5.7.3))
|
||||
@ -2901,6 +2931,10 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.5.20(typescript@5.7.3)
|
||||
|
||||
'@vueuse/shared@13.9.0(vue@3.5.20(typescript@5.7.3))':
|
||||
dependencies:
|
||||
vue: 3.5.20(typescript@5.7.3)
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
@ -1,51 +1,39 @@
|
||||
<template>
|
||||
<a-dropdown
|
||||
v-if="visible"
|
||||
:open="visible"
|
||||
:trigger="[]"
|
||||
:placement="dropdownPlacement"
|
||||
:get-popup-container="getPopupContainer"
|
||||
@open-change="handleOpenChange"
|
||||
:z-index="998"
|
||||
>
|
||||
<div ref="triggerRef" class="context-menu-trigger" :style="triggerStyle" />
|
||||
<template #overlay>
|
||||
<div class="context-menu-overlay">
|
||||
<div class="context-menu-header">
|
||||
<div class="menu-title">{{ headerTitle }}</div>
|
||||
<div class="close-button" @click="handleCloseMenu" title="关闭菜单">
|
||||
<span class="close-icon">×</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 库位菜单 -->
|
||||
<StorageMenu
|
||||
v-if="menuType === 'storage-background' && storageLocations?.length"
|
||||
:storage-locations="storageLocations"
|
||||
:menu-x="x"
|
||||
:menu-y="y"
|
||||
:main-menu-width="mainMenuWidth"
|
||||
@action-complete="handleActionComplete"
|
||||
/>
|
||||
|
||||
<!-- 机器人菜单 -->
|
||||
<RobotMenu
|
||||
v-else-if="menuType === 'robot' && robotId"
|
||||
:robot-id="robotId"
|
||||
@action-complete="handleActionComplete"
|
||||
@custom-image="handleCustomImage"
|
||||
/>
|
||||
|
||||
<!-- 默认菜单 -->
|
||||
<DefaultMenu v-else @action-complete="handleActionComplete" />
|
||||
<div v-if="visible" ref="menuRef" class="context-menu-overlay" :style="style">
|
||||
<div ref="handleRef" class="context-menu-header">
|
||||
<div class="menu-title">{{ headerTitle }}</div>
|
||||
<div class="close-button" @click="handleCloseMenu" title="关闭菜单">
|
||||
<span class="close-icon">×</span>
|
||||
</div>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
|
||||
<!-- 库位菜单 -->
|
||||
<StorageMenu
|
||||
v-if="menuType === 'storage-background' && storageLocations?.length"
|
||||
:storage-locations="storageLocations"
|
||||
:menu-x="x"
|
||||
:menu-y="y"
|
||||
:main-menu-width="mainMenuWidth"
|
||||
@action-complete="handleActionComplete"
|
||||
/>
|
||||
|
||||
<!-- 机器人菜单 -->
|
||||
<RobotMenu
|
||||
v-else-if="menuType === 'robot' && robotId"
|
||||
:robot-id="robotId"
|
||||
@action-complete="handleActionComplete"
|
||||
@custom-image="handleCustomImage"
|
||||
/>
|
||||
|
||||
<!-- 默认菜单 -->
|
||||
<DefaultMenu v-else @action-complete="handleActionComplete" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useDraggable } from '@vueuse/core';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import type { StorageLocationInfo } from '../../services/context-menu';
|
||||
import DefaultMenu from './default-menu.vue';
|
||||
@ -77,6 +65,24 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
});
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
// 拖拽功能
|
||||
const menuRef = ref<HTMLElement | null>(null);
|
||||
const handleRef = ref<HTMLElement | null>(null);
|
||||
|
||||
const { x, y, style } = useDraggable(menuRef, {
|
||||
handle: handleRef,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(isVisible) => {
|
||||
if (isVisible) {
|
||||
x.value = props.x;
|
||||
y.value = props.y;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 定义组件名称
|
||||
defineOptions({
|
||||
name: 'ContextMenu',
|
||||
@ -202,6 +208,7 @@ const handleCloseMenu = () => {
|
||||
|
||||
/* 下拉菜单覆盖层样式 */
|
||||
.context-menu-overlay {
|
||||
position: fixed;
|
||||
background: white;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 6px;
|
||||
@ -211,6 +218,7 @@ const handleCloseMenu = () => {
|
||||
user-select: none;
|
||||
color: #000;
|
||||
pointer-events: auto;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* 黑色主题 */
|
||||
@ -228,6 +236,7 @@ const handleCloseMenu = () => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
/* 黑色主题菜单头部 */
|
||||
|
@ -301,28 +301,28 @@ export function getRobotActionText(action: RobotAction): string {
|
||||
* @param action 操作类型
|
||||
* @returns 图标文本
|
||||
*/
|
||||
export function getRobotActionIcon(action: RobotAction): string {
|
||||
const iconMap: Record<RobotAction, string> = {
|
||||
'seize_control': '🎮',
|
||||
'enable_orders': '✅',
|
||||
'disable_orders': '❌',
|
||||
'pause': '⏸️',
|
||||
'resume': '▶️',
|
||||
'go_charge': '🔋',
|
||||
'go_dock': '🏠',
|
||||
'navigate': '🧭',
|
||||
'start': '🚀',
|
||||
'stop': '⏹️',
|
||||
'reset': '🔄',
|
||||
'diagnose': '🔧',
|
||||
'update': '📱',
|
||||
'custom_image': '🖼️',
|
||||
'follow_view': '👁️',
|
||||
'stop_follow_view': '👁️🗨️',
|
||||
};
|
||||
// export function getRobotActionIcon(action: RobotAction): string {
|
||||
// const iconMap: Record<RobotAction, string> = {
|
||||
// 'seize_control': '🎮',
|
||||
// 'enable_orders': '✅',
|
||||
// 'disable_orders': '❌',
|
||||
// 'pause': '⏸️',
|
||||
// 'resume': '▶️',
|
||||
// 'go_charge': '🔋',
|
||||
// 'go_dock': '🏠',
|
||||
// 'navigate': '🧭',
|
||||
// 'start': '🚀',
|
||||
// 'stop': '⏹️',
|
||||
// 'reset': '🔄',
|
||||
// 'diagnose': '🔧',
|
||||
// 'update': '📱',
|
||||
// 'custom_image': '🖼️',
|
||||
// 'follow_view': '👁️',
|
||||
// 'stop_follow_view': '👁️🗨️',
|
||||
// };
|
||||
|
||||
return iconMap[action] || '⚙️';
|
||||
}
|
||||
// return iconMap[action] || '⚙️';
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取机器人信息
|
||||
|
Loading…
x
Reference in New Issue
Block a user