index.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <template>
  2. <content-box
  3. class="go-content-layers"
  4. :class="{ scoped: !chartLayoutStore.getLayers }"
  5. title="图层"
  6. :depth="2"
  7. @back="backHandle"
  8. @mousedown="boxMousedownHandle($event)"
  9. >
  10. <template #icon>
  11. <n-icon size="16" :depth="2">
  12. <component :is="LayersIcon"></component>
  13. </n-icon>
  14. </template>
  15. <!-- 图层内容 -->
  16. <n-space v-if="reverseList.length === 0" justify="center">
  17. <n-text class="not-layer-text">暂无图层~</n-text>
  18. </n-space>
  19. <!-- https://github.com/SortableJS/vue.draggable.next -->
  20. <draggable item-key="id" v-model="reverseList" ghostClass="ghost" @change="onMoveCallback">
  21. <template #item="{ element }">
  22. <div class="go-content-layer-box">
  23. <!-- 组合 -->
  24. <layers-group-list-item v-if="element.isGroup" :componentGroupData="element"></layers-group-list-item>
  25. <!-- 单组件 -->
  26. <layers-list-item
  27. v-else
  28. :componentData="element"
  29. @mousedown="mousedownHandle($event, element)"
  30. @mouseenter="mouseenterHandle(element)"
  31. @mouseleave="mouseleaveHandle(element)"
  32. @contextmenu="handleContextMenu($event, element, optionsHandle)"
  33. ></layers-list-item>
  34. </div>
  35. </template>
  36. </draggable>
  37. </content-box>
  38. </template>
  39. <script setup lang="ts">
  40. import { computed, toRaw } from 'vue'
  41. import Draggable from 'vuedraggable'
  42. import cloneDeep from 'lodash/cloneDeep'
  43. import { ContentBox } from '../ContentBox/index'
  44. import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
  45. import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
  46. import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  47. import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
  48. import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
  49. import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
  50. import { MenuEnum, MouseEventButton, WinKeyboard, MacKeyboard } from '@/enums/editPageEnum'
  51. import { LayersListItem } from './components/LayersListItem/index'
  52. import { LayersGroupListItem } from './components/LayersGroupListItem/index'
  53. import { icon } from '@/plugins'
  54. const { LayersIcon } = icon.ionicons5
  55. const chartLayoutStore = useChartLayoutStore()
  56. const chartEditStore = useChartEditStore()
  57. const { handleContextMenu, onClickOutSide } = useContextMenu()
  58. // 右键事件
  59. const optionsHandle = (
  60. targetList: MenuOptionsItemType[],
  61. allList: MenuOptionsItemType[],
  62. targetInstance: CreateComponentType
  63. ) => {
  64. // 多选处理
  65. if (chartEditStore.getTargetChart.selectId.length > 1) {
  66. const list: MenuOptionsItemType[] = []
  67. targetList.forEach(item => {
  68. // 成组
  69. if (item.key === MenuEnum.GROUP) {
  70. list.push(item)
  71. }
  72. })
  73. return list
  74. }
  75. return targetList
  76. }
  77. // 逆序展示
  78. const reverseList = computed(() => {
  79. const list: Array<CreateComponentType | CreateComponentGroupType> = cloneDeep(chartEditStore.getComponentList)
  80. return list.reverse()
  81. })
  82. // 缩小
  83. const backHandle = () => {
  84. chartLayoutStore.setItem(ChartLayoutStoreEnum.LAYERS, false)
  85. }
  86. // 移动结束处理
  87. const onMoveCallback = (val: any) => {
  88. const { oldIndex, newIndex } = val.moved
  89. const moveTarget = toRaw(val.moved.element)
  90. if (newIndex - oldIndex > 0) {
  91. // 从上往下
  92. chartEditStore.getComponentList.splice(-(oldIndex + 1), 1)
  93. chartEditStore.getComponentList.splice(-newIndex, 0, moveTarget)
  94. } else {
  95. // 从下往上
  96. chartEditStore.getComponentList.splice(-(oldIndex + 1), 1)
  97. if (newIndex === 0) {
  98. chartEditStore.getComponentList.push(moveTarget)
  99. } else {
  100. chartEditStore.getComponentList.splice(-newIndex, 0, moveTarget)
  101. }
  102. }
  103. }
  104. const boxMousedownHandle = (e: MouseEvent) => {
  105. const box = document.querySelector('.go-content-layer-box')
  106. if ((e.target as any).contains(box)) {
  107. chartEditStore.setTargetSelectChart()
  108. }
  109. }
  110. // 点击事件
  111. const mousedownHandle = (e: MouseEvent, item: CreateComponentType) => {
  112. onClickOutSide()
  113. // 若此时按下了 CTRL, 表示多选
  114. const id = item.id
  115. if (
  116. e.buttons === MouseEventButton.LEFT &&
  117. (window.$KeyboardActive?.has(WinKeyboard.CTRL_SOURCE_KEY) ||
  118. window.$KeyboardActive?.has(MacKeyboard.CTRL_SOURCE_KEY))
  119. ) {
  120. // 若已选中,则去除
  121. if (chartEditStore.targetChart.selectId.includes(id)) {
  122. const exList = chartEditStore.targetChart.selectId.filter(e => e !== id)
  123. chartEditStore.setTargetSelectChart(exList)
  124. } else {
  125. chartEditStore.setTargetSelectChart(id, true)
  126. }
  127. return
  128. }
  129. chartEditStore.setTargetSelectChart(id)
  130. }
  131. // 进入事件
  132. const mouseenterHandle = (item: CreateComponentType) => {
  133. chartEditStore.setTargetHoverChart(item.id)
  134. }
  135. // 移出事件
  136. const mouseleaveHandle = (item: CreateComponentType) => {
  137. chartEditStore.setTargetHoverChart(undefined)
  138. }
  139. </script>
  140. <style lang="scss" scoped>
  141. $wight: 170px;
  142. @include go(content-layers) {
  143. width: $wight;
  144. flex-shrink: 0;
  145. overflow: hidden;
  146. @extend .go-transition;
  147. .not-layer-text {
  148. position: relative;
  149. top: 10px;
  150. white-space: nowrap;
  151. opacity: 0.4;
  152. }
  153. &.scoped {
  154. width: 0;
  155. }
  156. .ghost {
  157. opacity: 0;
  158. }
  159. }
  160. </style>