index.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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" :component="LayersIcon" />
  12. </template>
  13. <template #top-right>
  14. <n-button-group style="display: flex">
  15. <n-button
  16. v-for="(item, index) in layerModeList"
  17. :key="index"
  18. ghost
  19. size="small"
  20. :type="layerMode === item.value ? 'primary' : 'tertiary'"
  21. @click="changeLayerType(item.value)"
  22. >
  23. <n-tooltip :show-arrow="false" trigger="hover">
  24. <template #trigger>
  25. <n-icon size="14" :component="item.icon" />
  26. </template>
  27. {{ item.label }}
  28. </n-tooltip>
  29. </n-button>
  30. </n-button-group>
  31. </template>
  32. <!-- 图层内容 -->
  33. <n-space v-if="reverseList.length === 0" justify="center">
  34. <n-text class="not-layer-text">暂无图层~</n-text>
  35. </n-space>
  36. <!-- https://github.com/SortableJS/vue.draggable.next -->
  37. <draggable item-key="id" v-model="layerList" ghostClass="ghost" @change="onMoveCallback">
  38. <template #item="{ element }">
  39. <div class="go-content-layer-box">
  40. <!-- 组合 -->
  41. <layers-group-list-item
  42. v-if="element.isGroup"
  43. :componentGroupData="element"
  44. :layer-mode="layerMode"
  45. ></layers-group-list-item>
  46. <!-- 单组件 -->
  47. <layers-list-item
  48. v-else
  49. :componentData="element"
  50. :layer-mode="layerMode"
  51. @mousedown="mousedownHandle($event, element)"
  52. @mouseenter="mouseenterHandle(element)"
  53. @mouseleave="mouseleaveHandle(element)"
  54. @contextmenu="handleContextMenu($event, element, optionsHandle)"
  55. ></layers-list-item>
  56. </div>
  57. </template>
  58. </draggable>
  59. </content-box>
  60. </template>
  61. <script setup lang="ts">
  62. import { computed, ref, watch } from 'vue'
  63. import Draggable from 'vuedraggable'
  64. import cloneDeep from 'lodash/cloneDeep'
  65. import { ContentBox } from '../ContentBox/index'
  66. import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
  67. import { ChartLayoutStoreEnum, LayerModeEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
  68. import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  69. import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
  70. import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
  71. import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
  72. import { MenuEnum, MouseEventButton, WinKeyboard, MacKeyboard } from '@/enums/editPageEnum'
  73. import { LayersListItem } from './components/LayersListItem/index'
  74. import { LayersGroupListItem } from './components/LayersGroupListItem/index'
  75. import { icon } from '@/plugins'
  76. const { LayersIcon, GridIcon, ListIcon } = icon.ionicons5
  77. const chartLayoutStore = useChartLayoutStore()
  78. const chartEditStore = useChartEditStore()
  79. const { handleContextMenu, onClickOutSide } = useContextMenu()
  80. const layerModeList = [
  81. { label: '缩略图', icon: GridIcon, value: LayerModeEnum.THUMBNAIL },
  82. { label: '文本列表', icon: ListIcon, value: LayerModeEnum.TEXT }
  83. ]
  84. const layerList = ref<any>([])
  85. const layerMode = ref<LayerModeEnum>(chartLayoutStore.getLayerType)
  86. // 逆序展示
  87. const reverseList = computed(() => {
  88. const list: Array<CreateComponentType | CreateComponentGroupType> = cloneDeep(chartEditStore.getComponentList)
  89. return list.reverse()
  90. })
  91. watch(
  92. () => reverseList.value,
  93. newValue => {
  94. layerList.value = newValue
  95. }
  96. )
  97. // 右键事件
  98. const optionsHandle = (
  99. targetList: MenuOptionsItemType[],
  100. allList: MenuOptionsItemType[],
  101. targetInstance: CreateComponentType
  102. ) => {
  103. // 多选处理
  104. if (chartEditStore.getTargetChart.selectId.length > 1) {
  105. return targetList.filter(i => i.key === MenuEnum.GROUP)
  106. }
  107. const statusMenuEnums: MenuEnum[] = []
  108. // 处理锁定与隐藏
  109. if (targetInstance.status.lock) {
  110. statusMenuEnums.push(MenuEnum.LOCK)
  111. } else {
  112. statusMenuEnums.push(MenuEnum.UNLOCK)
  113. }
  114. if (targetInstance.status.hide) {
  115. statusMenuEnums.push(MenuEnum.HIDE)
  116. } else {
  117. statusMenuEnums.push(MenuEnum.SHOW)
  118. }
  119. return targetList.filter(item => !statusMenuEnums.includes(item.key as MenuEnum))
  120. }
  121. // 缩小
  122. const backHandle = () => {
  123. chartLayoutStore.setItem(ChartLayoutStoreEnum.LAYERS, false)
  124. }
  125. // 移动结束处理
  126. const onMoveCallback = (val: any) => {
  127. const { oldIndex, newIndex } = val.moved
  128. if (newIndex - oldIndex > 0) {
  129. // 从上往下
  130. const moveTarget = chartEditStore.getComponentList.splice(-(oldIndex + 1), 1)[0]
  131. chartEditStore.getComponentList.splice(-newIndex, 0, moveTarget)
  132. } else {
  133. // 从下往上
  134. const moveTarget = chartEditStore.getComponentList.splice(-(oldIndex + 1), 1)[0]
  135. if (newIndex === 0) {
  136. chartEditStore.getComponentList.push(moveTarget)
  137. } else {
  138. chartEditStore.getComponentList.splice(-newIndex, 0, moveTarget)
  139. }
  140. }
  141. }
  142. const boxMousedownHandle = (e: MouseEvent) => {
  143. const box = document.querySelector('.go-content-layer-box')
  144. if ((e.target as any).contains(box)) {
  145. chartEditStore.setTargetSelectChart()
  146. }
  147. }
  148. // 点击事件
  149. const mousedownHandle = (e: MouseEvent, item: CreateComponentType) => {
  150. onClickOutSide()
  151. // 若此时按下了 CTRL, 表示多选
  152. const id = item.id
  153. if (e.buttons === MouseEventButton.LEFT && window.$KeyboardActive?.ctrl) {
  154. // 若已选中,则去除
  155. if (chartEditStore.targetChart.selectId.includes(id)) {
  156. const exList = chartEditStore.targetChart.selectId.filter(e => e !== id)
  157. chartEditStore.setTargetSelectChart(exList)
  158. } else {
  159. chartEditStore.setTargetSelectChart(id, true)
  160. }
  161. return
  162. }
  163. chartEditStore.setTargetSelectChart(id)
  164. }
  165. // 进入事件
  166. const mouseenterHandle = (item: CreateComponentType) => {
  167. chartEditStore.setTargetHoverChart(item.id)
  168. }
  169. // 移出事件
  170. const mouseleaveHandle = (item: CreateComponentType) => {
  171. chartEditStore.setTargetHoverChart(undefined)
  172. }
  173. // 修改图层展示方式
  174. const changeLayerType = (value: LayerModeEnum) => {
  175. layerMode.value = value
  176. chartLayoutStore.setItem(ChartLayoutStoreEnum.LAYER_TYPE, value)
  177. }
  178. </script>
  179. <style lang="scss" scoped>
  180. $wight: 200px;
  181. @include go(content-layers) {
  182. width: $wight;
  183. flex-shrink: 0;
  184. overflow: hidden;
  185. @extend .go-transition;
  186. .not-layer-text {
  187. position: relative;
  188. top: 10px;
  189. white-space: nowrap;
  190. opacity: 0.4;
  191. }
  192. &.scoped {
  193. width: 0;
  194. }
  195. .ghost {
  196. opacity: 0;
  197. }
  198. .go-layer-mode-active {
  199. color: #51d6a9;
  200. }
  201. }
  202. </style>