Skip to content

右键菜单

@erp/biz 提供的右键菜单功能,用于创建自定义的上下文菜单。

核心功能

  • createContextMenu - 创建自定义右键菜单
  • 支持图标、点击回调
  • 自动处理位置和关闭逻辑

引入方式

typescript
import { createContextMenu } from '@erp/biz'

createContextMenu

创建自定义右键菜单。

基础用法

typescript
import { createContextMenu } from '@erp/biz'

// 在元素上绑定右键事件
element.addEventListener('contextmenu', (evt) => {
  createContextMenu(evt, [
    { label: '复制', value: 'copy', click: () => handleCopy() },
    { label: '粘贴', value: 'paste', click: () => handlePaste() },
    { label: '删除', value: 'delete', click: () => handleDelete() }
  ])
})

参数说明

typescript
function createContextMenu(
  evt: MouseEvent,
  menus: ContextMenuItem[]
): Promise<ContextMenuItem>

interface ContextMenuItem {
  /** 菜单显示文本 */
  label: string
  
  /** 菜单值标识 */
  value: string
  
  /** 菜单图标(组件或图标类名) */
  icon?: string | Component
  
  /** 点击回调函数 */
  click?: () => void
}

返回值

返回 Promise,resolve 时返回被点击的菜单项。

typescript
const selectedItem = await createContextMenu(evt, menus)
console.log('选中了:', selectedItem.label)

使用示例

表格行右键菜单

vue
<template>
  <vxe-grid @cell-menu="handleCellMenu" />
</template>

<script setup>
import { createContextMenu } from '@erp/biz'
import { IconEdit, IconDelete, IconCopy } from '@erp/common'

const handleCellMenu = ({ row, $event }) => {
  createContextMenu($event, [
    { 
      label: '编辑', 
      value: 'edit', 
      icon: IconEdit,
      click: () => editRow(row) 
    },
    { 
      label: '复制', 
      value: 'copy', 
      icon: IconCopy,
      click: () => copyRow(row) 
    },
    { 
      label: '删除', 
      value: 'delete', 
      icon: IconDelete,
      click: () => deleteRow(row) 
    }
  ])
}
</script>

图片右键菜单

typescript
import { createContextMenu, copyImageByUrl, downloadImageByUrl } from '@erp/biz'
import { IconCopy, IconDownload } from '@erp/common'

imageElement.addEventListener('contextmenu', (evt) => {
  const url = imageElement.src
  
  createContextMenu(evt, [
    {
      label: '复制图片',
      value: 'copy',
      icon: IconCopy,
      click: () => copyImageByUrl(url)
    },
    {
      label: '下载图片',
      value: 'download',
      icon: IconDownload,
      click: () => downloadImageByUrl(url)
    }
  ])
})

动态菜单

typescript
const getMenus = (row) => {
  const menus = [
    { label: '查看详情', value: 'view', click: () => viewDetail(row) }
  ]
  
  if (row.status === 'draft') {
    menus.push({ label: '编辑', value: 'edit', click: () => editRow(row) })
    menus.push({ label: '删除', value: 'delete', click: () => deleteRow(row) })
  }
  
  if (row.status === 'published') {
    menus.push({ label: '下架', value: 'offline', click: () => offlineRow(row) })
  }
  
  return menus
}

element.addEventListener('contextmenu', (evt) => {
  createContextMenu(evt, getMenus(currentRow))
})

注意事项

  1. createContextMenu 会自动阻止默认右键菜单
  2. 点击菜单项后菜单会自动关闭
  3. 点击菜单外部区域也会关闭菜单
  4. 菜单位置会根据鼠标位置自动调整,避免超出视口

基于 MIT 许可发布