useContextMenu.hook.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import { ref, nextTick } from 'vue'
  2. import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  3. import { CreateComponentType } from '@/packages/index.d'
  4. import { renderIcon, loadingError } from '@/utils'
  5. import { icon } from '@/plugins'
  6. import { MenuEnum, MenuOptionsItemType } from './useContextMenu.hook.d'
  7. const {
  8. CopyIcon,
  9. CutIcon,
  10. ClipboardOutlineIcon,
  11. TrashIcon,
  12. ChevronDownIcon,
  13. ChevronUpIcon,
  14. } = icon.ionicons5
  15. const { UpToTopIcon, DownToBottomIcon, PaintBrushIcon } = icon.carbon
  16. const chartEditStore = useChartEditStore()
  17. // * 默认选项
  18. const defaultOptions: MenuOptionsItemType[] = [
  19. {
  20. label: '复制',
  21. key: MenuEnum.COPY,
  22. icon: renderIcon(CopyIcon),
  23. fnHandle: chartEditStore.setCopy,
  24. },
  25. {
  26. label: '剪切',
  27. key: MenuEnum.CUT,
  28. icon: renderIcon(CutIcon),
  29. fnHandle: chartEditStore.setCut,
  30. },
  31. {
  32. label: '粘贴',
  33. key: MenuEnum.PARSE,
  34. icon: renderIcon(ClipboardOutlineIcon),
  35. fnHandle: chartEditStore.setParse,
  36. },
  37. {
  38. type: 'divider',
  39. key: 'd1',
  40. },
  41. {
  42. label: '置顶',
  43. key: MenuEnum.TOP,
  44. icon: renderIcon(UpToTopIcon),
  45. fnHandle: chartEditStore.setTop,
  46. },
  47. {
  48. label: '置底',
  49. key: MenuEnum.BOTTOM,
  50. icon: renderIcon(DownToBottomIcon),
  51. fnHandle: chartEditStore.setBottom,
  52. },
  53. {
  54. label: '上移一层',
  55. key: MenuEnum.UP,
  56. icon: renderIcon(ChevronUpIcon),
  57. fnHandle: chartEditStore.setUp,
  58. },
  59. {
  60. label: '下移一层',
  61. key: MenuEnum.DOWN,
  62. icon: renderIcon(ChevronDownIcon),
  63. fnHandle: chartEditStore.setDown,
  64. },
  65. {
  66. type: 'divider',
  67. key: 'd2',
  68. },
  69. {
  70. label: '清空剪贴板',
  71. key: MenuEnum.CLEAR,
  72. icon: renderIcon(PaintBrushIcon),
  73. fnHandle: chartEditStore.setRecordChart,
  74. },
  75. {
  76. label: '删除',
  77. key: MenuEnum.DELETE,
  78. icon: renderIcon(TrashIcon),
  79. fnHandle: chartEditStore.removeComponentList,
  80. },
  81. ]
  82. // * 无数据传递拥有的选项
  83. const defaultNoItemKeys = [MenuEnum.PARSE, MenuEnum.CLEAR]
  84. /**
  85. * * 挑选选项
  86. * @param options
  87. * @param pickList
  88. * @returns
  89. */
  90. const pickOption = (options: MenuOptionsItemType[], pickList?: MenuEnum[]) => {
  91. if (!pickList) return options
  92. return options.filter((op: MenuOptionsItemType) => {
  93. return pickList.findIndex((e: MenuEnum) => e === op.key) !== -1
  94. })
  95. }
  96. /**
  97. * * 去除选项
  98. * @param options
  99. * @param hideList
  100. * @returns
  101. */
  102. const hideOption = (options: MenuOptionsItemType[], hideList?: MenuEnum[]) => {
  103. if (!hideList) return options
  104. return options.filter((op: MenuOptionsItemType) => {
  105. return hideList.findIndex((e: MenuEnum) => e !== op.key) !== -1
  106. })
  107. }
  108. // * 右键内容
  109. const menuOptions = ref<MenuOptionsItemType[]>([])
  110. // * 右键处理
  111. const handleContextMenu = (
  112. e: MouseEvent,
  113. // 右键对象
  114. item?: CreateComponentType,
  115. // 判断函数
  116. optionsHandle?: Function,
  117. // 隐藏选项列表
  118. hideOptionsList?: MenuEnum[],
  119. // 挑选选项列表
  120. pickOptionsList?: MenuEnum[],
  121. // 自定义列表
  122. defaultOptions?: MenuOptionsItemType[]
  123. ) => {
  124. e.stopPropagation()
  125. e.preventDefault()
  126. let target = e.target
  127. while (target instanceof SVGElement) {
  128. target = target.parentNode
  129. }
  130. chartEditStore.setRightMenuShow(false)
  131. // * 设置默认选项
  132. if(defaultOptions) menuOptions.value = defaultOptions || defaultOptions
  133. if (!item) {
  134. menuOptions.value = pickOption(menuOptions.value, defaultNoItemKeys)
  135. }
  136. if (hideOptionsList) {
  137. menuOptions.value = hideOption(menuOptions.value, hideOptionsList)
  138. }
  139. if (pickOptionsList) {
  140. menuOptions.value = hideOption(menuOptions.value, pickOptionsList)
  141. }
  142. if (optionsHandle) {
  143. menuOptions.value = optionsHandle(menuOptions.value)
  144. }
  145. nextTick().then(() => {
  146. chartEditStore.setMousePosition(e.clientX, e.clientY)
  147. chartEditStore.setRightMenuShow(true)
  148. })
  149. }
  150. /**
  151. * * 右键hook
  152. * @param menuConfig
  153. * @returns
  154. */
  155. export const useContextMenu = () => {
  156. // * 失焦
  157. const onClickoutside = () => {
  158. chartEditStore.setRightMenuShow(false)
  159. }
  160. // * 事件处理
  161. const handleMenuSelect = (key: string) => {
  162. chartEditStore.setRightMenuShow(false)
  163. const targetItem: MenuOptionsItemType[] = menuOptions.value.filter(
  164. (e: MenuOptionsItemType) => e.key === key
  165. )
  166. menuOptions.value.forEach((e: MenuOptionsItemType) => {
  167. if (e.key === key) {
  168. if (e.fnHandle) {
  169. e.fnHandle()
  170. return
  171. }
  172. if (!targetItem) loadingError()
  173. }
  174. })
  175. }
  176. return {
  177. menuOptions,
  178. handleContextMenu,
  179. onClickoutside,
  180. handleMenuSelect,
  181. mousePosition: chartEditStore.getMousePosition,
  182. }
  183. }