Эх сурвалжийг харах

Merge branch 'dev' into master-fetch-dev

奔跑的面条 2 жил өмнө
parent
commit
2d752f119d

+ 1 - 0
package.json

@@ -21,6 +21,7 @@
     "axios": "^0.27.2",
     "color": "^4.2.3",
     "crypto-js": "^4.1.1",
+    "dom-helpers": "^5.2.1",
     "echarts-liquidfill": "^3.1.0",
     "echarts-stat": "^1.2.0",
     "echarts-wordcloud": "^2.0.0",

+ 21 - 1
pnpm-lock.yaml

@@ -25,6 +25,7 @@ specifiers:
   commitlint: ^17.0.2
   crypto-js: ^4.1.1
   default-passive-events: ^2.0.0
+  dom-helpers: ^5.2.1
   echarts: ^5.3.2
   echarts-liquidfill: ^3.1.0
   echarts-stat: ^1.2.0
@@ -77,6 +78,7 @@ dependencies:
   axios: 0.27.2
   color: 4.2.3
   crypto-js: 4.1.1
+  dom-helpers: 5.2.1
   echarts-liquidfill: 3.1.0_echarts@5.3.3
   echarts-stat: 1.2.0
   echarts-wordcloud: 2.0.0_echarts@5.3.3
@@ -402,6 +404,13 @@ packages:
       - supports-color
     dev: true
 
+  /@babel/runtime/7.20.6:
+    resolution: {integrity: sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      regenerator-runtime: 0.13.11
+    dev: false
+
   /@babel/template/7.16.7:
     resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==}
     engines: {node: '>=6.9.0'}
@@ -1912,7 +1921,7 @@ packages:
     dev: true
 
   /csstype/2.6.20:
-    resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/csstype/-/csstype-2.6.20.tgz}
+    resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==}
     dev: false
 
   /csstype/3.0.11:
@@ -2065,6 +2074,13 @@ packages:
     resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==}
     dev: true
 
+  /dom-helpers/5.2.1:
+    resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
+    dependencies:
+      '@babel/runtime': 7.20.6
+      csstype: 3.0.11
+    dev: false
+
   /dom-serializer/1.4.1:
     resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
     dependencies:
@@ -4462,6 +4478,10 @@ packages:
       strip-indent: 3.0.0
     dev: true
 
+  /regenerator-runtime/0.13.11:
+    resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
+    dev: false
+
   /regexp.prototype.flags/1.4.3:
     resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==}
     engines: {node: '>= 0.4'}

+ 4 - 2
src/enums/editPageEnum.ts

@@ -66,7 +66,8 @@ export enum WinKeyboard {
   ALT = ' alt',
   CTRL_SOURCE_KEY = 'control',
   SHIFT_SOURCE_KEY = 'shift',
-  ALT_SOURCE_KEY = 'alt'
+  ALT_SOURCE_KEY = 'alt',
+  SPACE = 'Space'
 }
 
 // Mac 键盘枚举
@@ -77,7 +78,8 @@ export enum MacKeyboard {
   ALT = '⌥',
   CTRL_SOURCE_KEY = '⌘',
   SHIFT_SOURCE_KEY = '⇧',
-  ALT_SOURCE_KEY = '⌥'
+  ALT_SOURCE_KEY = '⌥',
+  SPACE = 'Space'
 }
 
 // 同步状态枚举

+ 5 - 2
src/store/modules/chartLayoutStore/chartLayoutStore.d.ts

@@ -1,5 +1,5 @@
 export enum ChartModeEnum {
-  SINGLE= 'single',
+  SINGLE = 'single',
   DOUBLE = 'double'
 }
 
@@ -13,7 +13,8 @@ export enum ChartLayoutStoreEnum {
   CHARTS = 'charts',
   DETAILS = 'details',
   Chart_TYPE = 'chartType',
-  LAYER_TYPE = 'layerType'
+  LAYER_TYPE = 'layerType',
+  PERCENTAGE = 'percentage'
 }
 
 export interface ChartLayoutType {
@@ -27,4 +28,6 @@ export interface ChartLayoutType {
   [ChartLayoutStoreEnum.Chart_TYPE]: ChartModeEnum
   // 层级展示方式
   [ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum
+  // 当前正在加载的数量
+  [ChartLayoutStoreEnum.PERCENTAGE]: number
 }

+ 10 - 0
src/store/modules/chartLayoutStore/chartLayoutStore.ts

@@ -24,6 +24,8 @@ export const useChartLayoutStore = defineStore({
     chartType: ChartModeEnum.SINGLE,
     // 图层类型(默认图片)
     layerType: LayerModeEnum.THUMBNAIL,
+    // 当前加载数量
+    percentage: 0,
     // 防止值不存在
     ...storageChartLayout
   }),
@@ -42,6 +44,9 @@ export const useChartLayoutStore = defineStore({
     },
     getLayerType(): LayerModeEnum {
       return this.layerType
+    },
+    getPercentage(): number {
+      return this.percentage
     }
   },
   actions: {
@@ -54,6 +59,11 @@ export const useChartLayoutStore = defineStore({
       setTimeout(() => {
         chartEditStore.computedScale()
       }, 500)
+    },
+    setItemUnHandle<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
+      this.$patch(state => {
+        state[key] = value
+      })
     }
   }
 })

+ 1 - 1
src/styles/common/mixins/mixins.scss

@@ -17,7 +17,7 @@
 }
 
 @mixin deep() {
-  :deep {
+  :deep() {
     @content;
   }
 }

+ 7 - 1
src/utils/utils.ts

@@ -250,15 +250,21 @@ export const objToCookie = (obj: RequestParamsObjType) => {
  * @returns
  */
 export const setKeyboardDressShow = (keyCode?: number) => {
-  const code = new Map([[17, WinKeyboard.CTRL]])
+  const code = new Map([
+    [17, WinKeyboard.CTRL],
+    [32, WinKeyboard.SPACE]
+  ])
 
   const dom = document.getElementById('keyboard-dress-show')
   if (!dom) return
   if (!keyCode) {
+    window.onKeySpacePressHold?.(false)
     dom.innerText = ''
     return
   }
   if (keyCode && code.has(keyCode)) {
+    if (keyCode == 32) window.onKeySpacePressHold?.(true)
     dom.innerText = `按下了「${code.get(keyCode)}」键`
   }
 }
+

+ 27 - 9
src/views/chart/ContentBox/index.vue

@@ -18,14 +18,14 @@
       </n-space>
     </div>
 
-    <div
-      class="content"
-      :class="{
-        'content-height-show-top-bottom': showBottom || showTop,
-        'content-height-show-both': showBottom && showTop
-      }"
-    >
-      <template v-if="xScroll">
+    <div class="content" :class="{
+      'content-height-show-top-bottom': showBottom || showTop,
+      'content-height-show-both': showBottom && showTop
+    }">
+      <template v-if="disabledScroll">
+        <slot></slot>
+      </template>
+      <template v-else-if="xScroll">
         <n-scrollbar x-scrollable>
           <n-scrollbar>
             <slot></slot>
@@ -83,7 +83,11 @@ defineProps({
   xScroll: {
     type: Boolean,
     default: false
-  }
+  },
+  disabledScroll: {
+    type: Boolean,
+    default: false
+  },
 })
 
 const backHandle = () => {
@@ -93,41 +97,52 @@ const backHandle = () => {
 
 <style lang="scss" scoped>
 $topOrBottomHeight: 40px;
+
 @include go(content-box) {
   height: calc(100vh - #{$--header-height});
   margin: 1px;
   margin-bottom: 0;
+
   &.bg-depth0 {
     @include fetch-bg-color('background-color1');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color1');
     }
   }
+
   &.bg-depth1 {
     @include fetch-bg-color('background-color1');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color2');
     }
   }
+
   &.bg-depth2 {
     @include fetch-bg-color('background-color2');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color3');
     }
   }
+
   &.bg-depth3 {
     @include fetch-bg-color('background-color3');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color4');
     }
   }
+
   &.flex {
     flex: 1;
   }
+
   .top,
   .bottom {
     display: flex;
@@ -138,10 +153,12 @@ $topOrBottomHeight: 40px;
     padding: 0 10px;
     border-top: 1px solid;
     @include fetch-border-color('hover-border-color');
+
     .mt-1 {
       margin-top: 2px;
     }
   }
+
   .top {
     border-bottom: 1px solid;
     @include fetch-border-color('background-color1');
@@ -159,6 +176,7 @@ $topOrBottomHeight: 40px;
   .content-height-show-top-bottom {
     height: calc(100vh - #{$--header-height} - #{$topOrBottomHeight});
   }
+
   .content-height-show-both {
     height: calc(100vh - #{$--header-height} - #{$topOrBottomHeight} - #{$topOrBottomHeight});
   }

+ 1 - 1
src/views/chart/ContentEdit/components/EditBottom/index.vue

@@ -172,7 +172,7 @@ $max-width: 670px;
     .scale-slider {
       position: relative;
       top: -4px;
-      width: 200px;
+      width: 100px;
     }
   }
 }

+ 2 - 0
src/views/chart/ContentEdit/components/EditRange/index.vue

@@ -55,6 +55,8 @@ const rangeModelStyle = computed(() => {
   position: relative;
   transform-origin: left top;
   background-size: cover;
+  border-radius: 20px;
+  overflow: hidden;
   @include fetch-border-color('hover-border-color');
   @include fetch-bg-color('background-color2');
   @include go(edit-range-model) {

+ 259 - 60
src/views/chart/ContentEdit/components/EditRule/index.vue

@@ -1,49 +1,158 @@
 <template>
-  <sketch-rule
-    v-if="configShow"
-    :thick="thick"
-    :scale="scale"
-    :width="canvasBox().width"
-    :height="canvasBox().height"
-    :startX="startX"
-    :startY="startY"
-    :lines="lines"
-  ></sketch-rule>
+  <div class="go-sketch-rule">
+    <sketch-rule
+      v-if="sketchRuleReDraw"
+      :thick="thick"
+      :scale="scale"
+      :width="canvasBox().width"
+      :height="canvasBox().height"
+      :startX="startX"
+      :startY="startY"
+      :lines="lines"
+      :palette="paletteStyle"
+    >
+    </sketch-rule>
+    <div ref="$app" class="edit-screens" @scroll="handleScroll">
+      <div ref="$container" class="edit-screen-container" :style="{ width: width * 2 + 'px' }">
+        <div
+          ref="refSketchRuleBox"
+          class="canvas"
+          @mousedown="dragCanvas"
+          :style="{ marginLeft: '-' + (canvasBox().width / 2 - 25) + 'px' }"
+        >
+          <div :style="{ pointerEvents: isPressSpace ? 'none' : 'auto' }">
+            <slot></slot>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 修复右下角白点用的 -->
+    <div v-if="designStore.getDarkTheme" class="fix-edit-screens-block"></div>
+  </div>
 </template>
-
 <script setup lang="ts">
-import { ref, toRefs, computed, watch, nextTick, onBeforeUnmount } from 'vue'
-import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
+import { ref, reactive, onMounted, toRefs, watch, onUnmounted, computed } from 'vue'
+import { listen } from 'dom-helpers'
 import { useDesignStore } from '@/store/modules/designStore/designStore'
-import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
+import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
 
 const chartEditStore = useChartEditStore()
-const chartLayoutStore = useChartLayoutStore()
 const designStore = useDesignStore()
 
+const thick = 20
+let prevMoveXValue = [0, 0]
+let prevMoveYValue = [0, 0]
+
+const $app = ref()
+const sketchRuleReDraw = ref(true)
+const refSketchRuleBox = ref()
+const $container = ref()
+const isPressSpace = ref(false)
+const cursorStyle = ref('auto')
 const { width, height } = toRefs(chartEditStore.getEditCanvasConfig)
-const { scale, lockScale } = toRefs(chartEditStore.getEditCanvas)
-const { getLayers, getCharts, getDetails } = toRefs(chartLayoutStore)
+const startX = ref(0)
+const startY = ref(0)
+const lines = reactive({ h: [], v: [] })
 
-const configShow = ref(true)
+const scale = computed(() => {
+  return chartEditStore.getEditCanvas.scale
+})
 
-// x轴标尺开始的坐标数值
-const startX = -10
-// y轴标尺开始的坐标数值
-const startY = -10
-// 标尺的厚度
-const thick = 20
-// 初始化水平标尺上的参考线
-const lines = {
-  h: [],
-  v: []
+// 滚动条拖动的高度
+const containerWidth = computed(() => {
+  return `${height.value * 2}px`
+})
+
+// 主题
+const paletteStyle = computed(() => {
+  const isDarkTheme = designStore.getDarkTheme
+  return isDarkTheme
+    ? {
+        bgColor: '#18181c',
+        longfgColor: '#4d4d4d',
+        shortfgColor: '#4d4d4d',
+        fontColor: '#4d4d4d',
+        shadowColor: '#18181c',
+        borderColor: '#18181c',
+        cornerActiveColor: '#18181c'
+      }
+    : {}
+})
+
+// 颜色
+const themeColor = computed(() => {
+  return designStore.getAppTheme
+})
+
+const handleWheel = (e: any) => {
+  if (e.ctrlKey || e.metaKey) {
+    e.preventDefault()
+    let resScale = scale.value
+    // 放大(200%)
+    if (e.wheelDelta >= 0 && scale.value < 2) {
+      resScale = scale.value + 0.05
+      chartEditStore.setScale(resScale)
+      return
+    }
+    // 缩小(10%)
+    if (e.wheelDelta < 0 && scale.value > 0.1) {
+      resScale = scale.value - 0.05
+      chartEditStore.setScale(resScale)
+    }
+  }
+}
+
+const handleScroll = () => {
+  if (!$app.value) return
+  const screensRect = $app.value.getBoundingClientRect()
+  const canvasRect = refSketchRuleBox.value.getBoundingClientRect()
+  // 标尺开始的刻度
+  startX.value = (screensRect.left + thick - canvasRect.left) / scale.value
+  startY.value = (screensRect.top + thick - canvasRect.top) / scale.value
+}
+
+const dragCanvas = (e: any) => {
+  e.preventDefault()
+  e.stopPropagation()
+
+  if (e.which == 2) isPressSpace.value = true
+  else if (!window.$KeyboardActive?.space) return
+  // @ts-ignore
+  document.activeElement?.blur()
+
+  const startX = e.pageX
+  const startY = e.pageY
+
+  const listenMousemove = listen(window, 'mousemove', (e: any) => {
+    const nx = e.pageX - startX
+    const ny = e.pageY - startY
+
+    const [prevMoveX1, prevMoveX2] = prevMoveXValue
+    const [prevMoveY1, prevMoveY2] = prevMoveYValue
+
+    prevMoveXValue = [prevMoveX2, nx]
+    prevMoveYValue = [prevMoveY2, ny]
+
+    $app.value.scrollLeft -=
+      prevMoveX2 > prevMoveX1 ? Math.abs(prevMoveX2 - prevMoveX1) : -Math.abs(prevMoveX2 - prevMoveX1)
+    $app.value.scrollTop -=
+      prevMoveY2 > prevMoveY1 ? Math.abs(prevMoveY2 - prevMoveY1) : -Math.abs(prevMoveY2 - prevMoveY1)
+  })
+
+  const listenMouseup = listen(window, 'mouseup', () => {
+    listenMousemove()
+    listenMouseup()
+    prevMoveXValue = [0, 0]
+    prevMoveYValue = [0, 0]
+    isPressSpace.value = false
+  })
 }
 
 const canvasBox = () => {
   const layoutDom = document.getElementById('go-chart-edit-layout')
   if (layoutDom) {
     return {
-      height: layoutDom.clientHeight - 40,
+      height: layoutDom.clientHeight - 25,
       width: layoutDom.clientWidth
     }
   }
@@ -53,83 +162,104 @@ const canvasBox = () => {
   }
 }
 
-// 颜色
-const themeColor = computed(() => {
-  return designStore.getAppTheme
-})
-
-// 处理标尺重制大小
-const ruleChangeHandle = () => {
-  configShow.value = false
+// 在位置不动的情况下重绘标尺
+const reDraw = () => {
+  sketchRuleReDraw.value = false
   setTimeout(() => {
-    configShow.value = true
-  })
+    sketchRuleReDraw.value = true
+  }, 10)
 }
 
-const ruleChangeHandleTimeOut = () => {
-  if (lockScale.value) {
-    setTimeout(() => {
-      ruleChangeHandle()
-    }, 500)
+watch(
+  () => designStore.getDarkTheme,
+  () => {
+    reDraw()
   }
+)
+
+// 滚动居中
+const canvasPosCenter = () => {
+  const { width: containerWidth, height: containerHeight } = $container.value.getBoundingClientRect()
+  const { width, height } = canvasBox()
+
+  $app.value.scrollLeft = containerWidth / 2 - width / 2
+  $app.value.scrollTop = containerHeight / 2 - height / 2
 }
 
+// 处理标尺重制大小
 watch(
   () => scale.value,
-  () => ruleChangeHandle()
+  (newValue, oldValue) => {
+    if (oldValue !== newValue) {
+      handleScroll()
+      chartEditStore.setScale(newValue)
+      setTimeout(() => {
+        canvasPosCenter()
+      }, 500)
+    }
+  }
 )
 
 watch(
-  () => getLayers.value,
-  () => ruleChangeHandleTimeOut()
+  () => isPressSpace.value,
+  newValue => {
+    cursorStyle.value = newValue ? 'grab' : 'auto'
+  }
 )
 
-watch(
-  () => getCharts.value,
-  () => ruleChangeHandleTimeOut()
-)
+onMounted(() => {
+  if ($app.value) {
+    $app.value.addEventListener('wheel', handleWheel, { passive: false })
+    canvasPosCenter()
+  }
+})
 
-watch(
-  () => getDetails.value,
-  () => ruleChangeHandleTimeOut()
-)
+onUnmounted(() => {
+  if ($app.value) {
+    $app.value.removeEventListener('wheel', handleWheel)
+  }
+})
 
+window.onKeySpacePressHold = (isHold: boolean) => {
+  isPressSpace.value = isHold
+}
 </script>
 
 <style>
 /* 使用 SCSS 会报错,直接使用最基础的 CSS 进行修改,
 此库有计划 Vue3 版本,但是开发的时候还没发布 */
-
 #mb-ruler {
   top: 0;
   left: 0;
 }
-/* 适配底部的工具栏不遮盖 */
-#mb-ruler .v-container {
-  height: calc(100% - 65px) !important;
-}
+
 /* 横线 */
 #mb-ruler .v-container .lines .line {
   /* 最大缩放 200% */
   width: 200vw !important;
   border-top: 1px dashed v-bind('themeColor') !important;
 }
+
 #mb-ruler .v-container .indicator {
   border-bottom: 1px dashed v-bind('themeColor') !important;
 }
+
 /* 竖线 */
 #mb-ruler .h-container .lines .line {
   /* 最大缩放 200% */
   height: 200vh !important;
   border-left: 1px dashed v-bind('themeColor') !important;
 }
+
 #mb-ruler .h-container .indicator {
   border-left: 1px dashed v-bind('themeColor') !important;
 }
+
 /* 坐标数值背景颜色 */
 #mb-ruler .indicator .value {
   background-color: rgba(0, 0, 0, 0);
 }
+
 /* 删除按钮 */
 #mb-ruler .line .del {
   padding: 0;
@@ -142,3 +272,72 @@ watch(
   border-width: 0 !important;
 }
 </style>
+
+<style lang="scss" scoped>
+@include go('sketch-rule') {
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+  height: 100%;
+
+  .edit-screens {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    overflow: auto;
+    user-select: none;
+    padding-bottom: 0px;
+
+    /* firefox */
+    scrollbar-color: rgba(144, 146, 152, 0.3) transparent;
+    scrollbar-width: thin;
+
+    /* chrome */
+    &::-webkit-scrollbar,
+    &::-webkit-scrollbar-track-piece {
+      background-color: transparent;
+    }
+
+    &::-webkit-scrollbar {
+      width: 7px;
+    }
+
+    &::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      background-color: rgba(144, 146, 152, 0.3);
+    }
+  }
+
+  .fix-edit-screens-block {
+    position: absolute;
+    bottom: 0;
+    right: 0;
+    width: 10px;
+    height: 10px;
+    background-color: $--color-dark-bg-1;
+  }
+
+  .edit-screen-container {
+    position: absolute;
+    height: v-bind('containerWidth');
+    top: 0;
+    left: 0;
+  }
+
+  .canvas {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform-origin: 50% 0;
+    transform: translateY(-50%);
+
+    &:hover {
+      cursor: v-bind('cursorStyle');
+    }
+
+    &:active {
+      cursor: crosshair;
+    }
+  }
+}
+</style>

+ 9 - 17
src/views/chart/ContentEdit/components/EditShortcutKey/ShortcutKeyModal.vue

@@ -19,7 +19,8 @@
         <tr v-for="(item, index) in shortcutKeyOptions" :key="index">
           <td>{{ item.label }}</td>
           <td>{{ item.win }}</td>
-          <td>
+          <td v-if="item.macSource">{{ item.mac }}</td>
+          <td v-else>
             <n-gradient-text :size="22">{{ item.mac.substr(0, 1) }}</n-gradient-text>
             + {{ item.mac.substr(3) }}
           </td>
@@ -44,24 +45,15 @@ defineProps({
 // 快捷键
 const shortcutKeyOptions = [
   {
-    label: '向上移动',
-    win: `${WinKeyboard.CTRL.toUpperCase()} + ↑ `,
-    mac: `${MacKeyboard.CTRL.toUpperCase()} + ↑ `
-  },
-  {
-    label: '向右移动',
-    win: `${WinKeyboard.CTRL.toUpperCase()} + → `,
-    mac: `${MacKeyboard.CTRL.toUpperCase()} + → `
+    label: '拖拽画布',
+    win: `${WinKeyboard.SPACE.toUpperCase()} + 🖱️ `,
+    mac: `${MacKeyboard.SPACE.toUpperCase()} + 🖱️ `,
+    macSource: true
   },
   {
-    label: '向下移动',
-    win: `${WinKeyboard.CTRL.toUpperCase()} + ↓ `,
-    mac: `${MacKeyboard.CTRL.toUpperCase()} + ↓ `
-  },
-  {
-    label: '向左移动',
-    win: `${WinKeyboard.CTRL.toUpperCase()} + ← `,
-    mac: `${MacKeyboard.CTRL.toUpperCase()} + ← `
+    label: '向 上/右/下/左 移动',
+    win: `${WinKeyboard.CTRL.toUpperCase()} + ↑ 或 → 或 ↓ 或 ←`,
+    mac: `${MacKeyboard.CTRL.toUpperCase()} + ↑ `
   },
   {
     label: '锁定',

+ 3 - 0
src/views/chart/ContentEdit/hooks/useDrag.hook.ts

@@ -62,6 +62,9 @@ export const mousedownHandleUnStop = (e: MouseEvent, item?: CreateComponentType
 
 // * 框选
 export const mousedownBoxSelect = (e: MouseEvent, item?: CreateComponentType | CreateComponentGroupType) => {
+  if (e.which == 2) return
+  if (window.$KeyboardActive?.space) return
+
   mousedownHandleUnStop(e)
 
   // 记录点击初始位置

+ 56 - 52
src/views/chart/ContentEdit/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <edit-rule></edit-rule>
+  <!-- <edit-rule></edit-rule> -->
   <content-box
     id="go-chart-edit-layout"
     :flex="true"
@@ -7,65 +7,68 @@
     :showBottom="true"
     :depth="1"
     :xScroll="true"
+    :disabledScroll="true"
     @mousedown="mousedownHandleUnStop"
     @drop="dragHandle"
     @dragover="dragoverHandle"
     @dragenter="dragoverHandle"
   >
-    <!-- 画布主体 -->
-    <div id="go-chart-edit-content" @contextmenu="handleContextMenu">
-      <!-- 展示 -->
-      <edit-range>
-        <!-- 滤镜预览 -->
-        <div
-          :style="{
-            ...getFilterStyle(chartEditStore.getEditCanvasConfig),
-            ...rangeStyle
-          }"
-        >
-          <!-- 图表 -->
-          <div v-for="(item, index) in chartEditStore.getComponentList" :key="item.id">
-            <!-- 分组 -->
-            <edit-group
-              v-if="item.isGroup"
-              :groupData="(item as CreateComponentGroupType)"
-              :groupIndex="index"
-            ></edit-group>
-
-            <!-- 单组件 -->
-            <edit-shape-box
-              v-else
-              :data-id="item.id"
-              :index="index"
-              :style="{
+    <edit-rule>
+      <!-- 画布主体 -->
+      <div id="go-chart-edit-content" @contextmenu="handleContextMenu">
+        <!-- 展示 -->
+        <edit-range>
+          <!-- 滤镜预览 -->
+          <div
+            :style="{
+              ...getFilterStyle(chartEditStore.getEditCanvasConfig),
+              ...rangeStyle
+            }"
+          >
+            <!-- 图表 -->
+            <div v-for="(item, index) in chartEditStore.getComponentList" :key="item.id">
+              <!-- 分组 -->
+              <edit-group
+                v-if="item.isGroup"
+                :groupData="(item as CreateComponentGroupType)"
+                :groupIndex="index"
+              ></edit-group>
+
+              <!-- 单组件 -->
+              <edit-shape-box
+                v-else
+                :data-id="item.id"
+                :index="index"
+                :style="{
                 ...useComponentStyle(item.attr, index),
                 ...getBlendModeStyle(item.styles) as any
               }"
-              :item="item"
-              @click="mouseClickHandle($event, item)"
-              @mousedown="mousedownHandle($event, item)"
-              @mouseenter="mouseenterHandle($event, item)"
-              @mouseleave="mouseleaveHandle($event, item)"
-              @contextmenu="handleContextMenu($event, item, optionsHandle)"
-            >
-              <component
-                class="edit-content-chart"
-                :class="animationsClass(item.styles.animations)"
-                :is="item.chartConfig.chartKey"
-                :chartConfig="item"
-                :themeSetting="themeSetting"
-                :themeColor="themeColor"
-                :style="{
-                  ...useSizeStyle(item.attr),
-                  ...getFilterStyle(item.styles),
-                  ...getTransformStyle(item.styles)
-                }"
-              ></component>
-            </edit-shape-box>
+                :item="item"
+                @click="mouseClickHandle($event, item)"
+                @mousedown="mousedownHandle($event, item)"
+                @mouseenter="mouseenterHandle($event, item)"
+                @mouseleave="mouseleaveHandle($event, item)"
+                @contextmenu="handleContextMenu($event, item, optionsHandle)"
+              >
+                <component
+                  class="edit-content-chart"
+                  :class="animationsClass(item.styles.animations)"
+                  :is="item.chartConfig.chartKey"
+                  :chartConfig="item"
+                  :themeSetting="themeSetting"
+                  :themeColor="themeColor"
+                  :style="{
+                    ...useSizeStyle(item.attr),
+                    ...getFilterStyle(item.styles),
+                    ...getTransformStyle(item.styles)
+                  }"
+                ></component>
+              </edit-shape-box>
+            </div>
           </div>
-        </div>
-      </edit-range>
-    </div>
+        </edit-range>
+      </div>
+    </edit-rule>
 
     <!-- 工具栏 -->
     <template #aside>
@@ -191,12 +194,13 @@ onMounted(() => {
   overflow: hidden;
   @extend .go-point-bg;
   @include background-image('background-point');
+
   @include goId('chart-edit-content') {
     border-radius: 10px;
-    margin: 25px;
     overflow: hidden;
     @extend .go-transition;
     @include fetch-theme('box-shadow');
+
     .edit-content-chart {
       position: absolute;
       overflow: hidden;

+ 3 - 0
src/views/chart/ContentLoad/index.ts

@@ -0,0 +1,3 @@
+import ContentLoad from './index.vue'
+
+export { ContentLoad }

+ 33 - 0
src/views/chart/ContentLoad/index.vue

@@ -0,0 +1,33 @@
+<template>
+  <n-modal :show="showModal" :close-on-esc="false" transform-origin="center">
+    <div>
+      <span> 拼命加载中... </span>
+      <n-progress type="line" :color="themeColor" :percentage="percentage" style="width: 300px" />
+    </div>
+  </n-modal>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, computed } from 'vue'
+import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
+import { useDesignStore } from '@/store/modules/designStore/designStore'
+
+const chartLayoutStore = useChartLayoutStore()
+const designStore = useDesignStore()
+const showModal = ref(false)
+const percentage = ref(0)
+
+// 颜色
+const themeColor = computed(() => {
+  return designStore.getAppTheme
+})
+
+// 监听百分比
+watch(
+  () => chartLayoutStore.getPercentage,
+  newValue => {
+    percentage.value = newValue
+    showModal.value = newValue > 0
+  }
+)
+</script>

+ 19 - 7
src/views/chart/hooks/useKeyboard.hook.ts

@@ -115,21 +115,33 @@ const macKeyList: Array<string> = [
 const keyRecordHandle = () => {
   // 默认赋值
   window.$KeyboardActive = {
-    ctrl: false
+    ctrl: false,
+    space: false
   }
-  
+
   document.onkeydown = (e: KeyboardEvent) => {
-    if(e.keyCode === 17 && window.$KeyboardActive) {
+    const { keyCode } = e
+    if (keyCode == 32 && e.target == document.body) e.preventDefault()
+
+    if ([17, 32].includes(keyCode) && window.$KeyboardActive) {
       setKeyboardDressShow(e.keyCode)
-      window.$KeyboardActive.ctrl = true
+      switch (keyCode) {
+        case 17: window.$KeyboardActive.ctrl = true; break
+        case 32: window.$KeyboardActive.space = true; break
+      }
     }
   }
 
   document.onkeyup = (e: KeyboardEvent) => {
-    if(e.keyCode === 17 && window.$KeyboardActive) 
-    {
-      window.$KeyboardActive.ctrl = false
+    const { keyCode } = e
+    if (keyCode == 32 && e.target == document.body) e.preventDefault()
+
+    if ([17, 32].includes(keyCode) && window.$KeyboardActive) {
       setKeyboardDressShow()
+      switch (keyCode) {
+        case 17: window.$KeyboardActive.ctrl = false; break
+        case 32: window.$KeyboardActive.space = false; break
+      }
     }
   }
 }

+ 13 - 1
src/views/chart/hooks/useSync.hook.ts

@@ -6,6 +6,8 @@ import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStora
 import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
 import { StylesSetting } from '@/components/Pages/ChartItemSetting'
 import { useSystemStore } from '@/store/modules/systemStore/systemStore'
+import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
+import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
 import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index'
 import { saveInterval } from '@/settings/designSetting'
 import throttle from 'lodash/throttle'
@@ -98,7 +100,7 @@ export const useSync = () => {
   const chartEditStore = useChartEditStore()
   const chartHistoryStore = useChartHistoryStore()
   const systemStore = useSystemStore()
-
+  const chartLayoutStore = useChartLayoutStore()
   /**
    * * 组件动态注册
    * @param projectData 项目数据
@@ -164,7 +166,14 @@ export const useSync = () => {
     for (const key in projectData) {
       // 组件
       if (key === ChartEditStoreEnum.COMPONENT_LIST) {
+        let loadIndex = 0
+        const listLength = projectData[key].length;
+        console.log(listLength)
         for (const comItem of projectData[key]) {
+          // 设置加载数量
+          let percentage = parseInt((parseFloat(`${++loadIndex / listLength}`) * 100).toString())
+          chartLayoutStore.setItemUnHandle(ChartLayoutStoreEnum.PERCENTAGE, percentage)
+          // 判断类型
           if (comItem.isGroup) {
             // 创建分组
             let groupClass = new PublicGroupConfigClass()
@@ -195,6 +204,9 @@ export const useSync = () => {
         componentMerge(chartEditStore[key], projectData[key], true)
       }
     }
+
+    // 清除数量
+    chartLayoutStore.setItemUnHandle(ChartLayoutStoreEnum.PERCENTAGE, 0)
   }
 
   /**

+ 3 - 0
src/views/chart/index.vue

@@ -32,6 +32,8 @@
     :on-clickoutside="onClickOutSide"
     @select="handleMenuSelect"
   ></n-dropdown>
+  <!-- 加载蒙层 -->
+  <content-load></content-load>
 </template>
 
 <script setup lang="ts">
@@ -53,6 +55,7 @@ const HeaderTitle = loadAsyncComponent(() => import('./ContentHeader/headerTitle
 const ContentLayers = loadAsyncComponent(() => import('./ContentLayers/index.vue'))
 const ContentCharts = loadAsyncComponent(() => import('./ContentCharts/index.vue'))
 const ContentConfigurations = loadAsyncComponent(() => import('./ContentConfigurations/index.vue'))
+const ContentLoad = loadAsyncComponent(() => import('./ContentLoad/index.vue'))
 
 // 右键
 const {

+ 2 - 0
types/global.d.ts

@@ -7,6 +7,8 @@ interface Window {
   $vue: any
   // 键盘按键记录
   $KeyboardActive?: { [T: string]: boolean }
+  onKeySpacePressHold?: Function
+
   // 编辑 JSON 的存储对象
   opener: any
 }

+ 2 - 1
types/shims-vue.d.ts

@@ -4,4 +4,5 @@ declare module '*.vue' {
   export default component
 }
 
-declare module 'lodash/*'
+declare module 'lodash/*'
+declare module 'dom-helpers'