فهرست منبع

feat: 调整依赖,添加位移吸附

liaojiaxing 9 ماه پیش
والد
کامیت
1bc1d814a5

+ 1 - 13
apps/shalu-bigscreen-designer/package.json

@@ -17,31 +17,19 @@
     "@codemirror/theme-one-dark": "^6.1.2",
     "@vueuse/components": "^10.11.0",
     "@vueuse/core": "^10.10.1",
-    "ant-design-vue": "4.x",
     "axios": "^1.7.2",
     "dayjs": "^1.11.11",
-    "echarts": "^5.5.0",
-    "element-plus": "^2.7.6",
     "js-beautify": "^1.14.3",
-    "less": "^4.2.0",
-    "less-loader": "^12.2.0",
     "lodash": "^4.17.21",
     "mockjs": "^1.1.0",
     "pinia": "^2.1.7",
     "unplugin-element-plus": "^0.8.0",
-    "vue": "^3.4.21",
     "vue-codemirror": "^6.1.1",
-    "vue-hooks-plus": "^2.2.0",
     "vue-router": "^4.3.3",
     "vuedraggable": "^4.1.0"
   },
   "devDependencies": {
     "@types/node": "^20.14.2",
-    "@vitejs/plugin-vue": "^5.0.4",
-    "@vitejs/plugin-vue-jsx": "^4.0.0",
-    "typescript": "^5.2.2",
-    "vite": "^5.2.0",
-    "vite-plugin-mock": "^3.0.2",
-    "vue-tsc": "^2.0.6"
+    "vite-plugin-mock": "^3.0.2"
   }
 }

+ 1 - 0
apps/shalu-bigscreen-designer/src/hooks/index.ts

@@ -0,0 +1 @@
+export * from './useAdsorb';

+ 87 - 0
apps/shalu-bigscreen-designer/src/hooks/useAdsorb.ts

@@ -0,0 +1,87 @@
+import { useProjectStore } from "@/store/modules/project";
+import { calcComboInfo } from "@/utils/calc";
+
+const ABSORB_DISTANCE = 10;
+
+export function useAdsorb() {
+  const projectStore = useProjectStore();
+
+  const getAdsorb = ( move: number, xy: number, wh: number, targetVal: number) => {
+    // 始端吸附
+    if (Math.abs((xy + move) - targetVal) < ABSORB_DISTANCE) {
+      move = targetVal - xy;
+    }
+    // 中间吸附
+    if (Math.abs((xy + wh / 2 + move) - targetVal) < ABSORB_DISTANCE) {
+      move = targetVal - xy - wh / 2;
+    }
+    // 终端吸附
+    if (Math.abs((xy + wh + move) - targetVal) < ABSORB_DISTANCE) {
+      move = targetVal - xy - wh;
+    }
+    
+    return move;
+  }
+
+  /**
+   * 获取吸附信息
+   * @param moveX 移动x坐标
+   * @param moveY 移动y坐标
+   * @param moveW 移动宽度
+   * @param moveH 移动高度
+   */
+  const getAdsorbInfo = ({ moveX, moveY, moveW, moveH }: { moveX: number, moveY: number, moveW: number, moveH: number }) => {
+    // 1、获取当前操作元素
+    const selcetedElements = projectStore.currentSelectedElements;
+    // 2、获取所有组件及参考线
+    const referLines = projectStore.showReffer ? projectStore.referLines : [];
+    const elements = projectStore.elements.filter(item => selcetedElements.findIndex(ele => ele.key === item.key) === -1);
+    // 3、将当前的操作元素当作一个整体 计算出x y w h
+    const { minX: x, minY: y, maxX, maxY } = calcComboInfo(selcetedElements);
+    const w = maxX - x;
+    const h = maxY - y;
+
+    // 组件间吸附
+    elements.forEach(item => {
+      const { x: itemX = 0, y: itemY = 0, width = 0, height = 0 } = item.container.props;
+      // 左
+      moveX = getAdsorb(moveX, x, w, itemX);
+      // 中
+      moveX = getAdsorb(moveX, x, w, itemX + (width / 2));
+      // 右
+      moveX = getAdsorb(moveX, x, w, itemX + width);
+
+      // 上
+      moveY = getAdsorb(moveY, y, h, itemY);
+      // 中
+      moveY = getAdsorb(moveY, y, h, itemY + (height / 2));
+      // 下
+      moveY = getAdsorb(moveY, y, h, itemY + height);
+    })
+
+    referLines.forEach(line => {
+      if (line.type === "vertical") {
+        moveY = getAdsorb(moveY, y, h, line.value);
+      } else {
+        moveX = getAdsorb(moveX, x, w, line.value);
+      }
+    })
+
+    // 屏幕边线吸附
+    moveY = getAdsorb(moveY, y, h, 0);
+    moveY = getAdsorb(moveY, y, h, projectStore.projectInfo.height);
+    moveX = getAdsorb(moveX, x, w, 0);
+    moveX = getAdsorb(moveX, x, w, projectStore.projectInfo.width);
+
+    return {
+      newMoveX: moveX,
+      newMoveY: moveY,
+      newMoveW: moveW,
+      newMoveH: moveH
+    }
+  }
+
+  return {
+    getAdsorbInfo
+  }
+}

+ 2 - 5
apps/shalu-bigscreen-designer/src/store/modules/action.ts

@@ -5,6 +5,7 @@ import { useProjectStore } from "@/store/modules/project";
 import { cloneDeep } from "lodash";
 import { CustomElement } from "#/project";
 import { uuid } from "@/utils";
+import { calcComboInfo } from "@/utils/calc";
 // import { recoverRecord } from "@/utils/recover";
 
 // type RecordItem = {
@@ -262,11 +263,7 @@ export const useAcionStore = defineStore({
       elements.forEach((element) => {
         this.projectStore.removeElement(element.key);
       });
-      const minX = Math.min(...elements.map((item) => item.container.props.x));
-      const minY = Math.min(...elements.map((item) => item.container.props.y));
-      const maxX = Math.max(...elements.map((item) => item.container.props.x + item.container.props.width));
-      const maxY = Math.max(...elements.map((item) => item.container.props.y + item.container.props.height));
-      const maxZIndex = Math.max(...elements.map((item) => item.zIndex));
+      const { minX, minY, maxX, maxY, maxZIndex } = calcComboInfo(elements);
       const groupIndex = this.projectStore.elements.filter((item) => item.componentType === "group").length + 1;
       // 重新计算子元素位置
       elements.forEach((item) => {

+ 8 - 1
apps/shalu-bigscreen-designer/src/store/modules/project.ts

@@ -21,6 +21,7 @@ type ProjectState = {
   } | null;
   mode: "edit" | "player";
   selectedElementKeys: string[];
+  showReffer: boolean;
 };
 const defaultPage: Page = {
   key: "1",
@@ -58,6 +59,8 @@ export const useProjectStore = defineStore({
     mode: "edit",
     // 选中的元素
     selectedElementKeys: [],
+    // 辅助线
+    showReffer: true,
   }),
   getters: {
     referLines(state) {
@@ -146,7 +149,7 @@ export const useProjectStore = defineStore({
       const elements = this.projectInfo.pages[this.activePageIndex].elements;
       // 获取每个自定义组件暴露出来的默认属性
       const { defaultPropsValue } =
-        (await asyncComponentAll[element.componentType]?.()) || {};
+        (await asyncComponentAll[element.componentType as keyof typeof asyncComponentAll]?.()) || {};
 
       const { defaultWidth = 400, defaultHeight = 260 } =
         defaultPropsValue?.container?.props || {};
@@ -253,5 +256,9 @@ export const useProjectStore = defineStore({
       editPageDesignApi(params);
       message.success("保存成功");
     },
+    // 切换辅助线隐藏
+    toggleReffer() {
+      this.showReffer = !this.showReffer;
+    }
   },
 });

+ 21 - 0
apps/shalu-bigscreen-designer/src/utils/calc.ts

@@ -0,0 +1,21 @@
+import type { CustomElement } from "#/project";
+/**
+ * 计算组合组件几何信息
+ * @param elements 组件列表
+ * @returns 
+ */
+export const calcComboInfo = (elements: CustomElement[]) => {
+  const minX = Math.min(...elements.map((item) => item.container.props.x));
+  const minY = Math.min(...elements.map((item) => item.container.props.y));
+  const maxX = Math.max(...elements.map((item) => item.container.props.x + item.container.props.width));
+  const maxY = Math.max(...elements.map((item) => item.container.props.y + item.container.props.height));
+  const maxZIndex = Math.max(...elements.map((item) => item.zIndex));
+
+  return {
+    minX,
+    minY,
+    maxX,
+    maxY,
+    maxZIndex
+  }
+}

+ 12 - 3
apps/shalu-bigscreen-designer/src/views/designer/component/ComponentWrapper.vue

@@ -51,6 +51,7 @@ import { useAcionStore } from "@/store/modules/action";
 import { asyncComponentAll } from "@shalu/dashboard-ui";
 import Container from "@/components/Container/index.vue";
 import { scaleAction } from "@/utils/scale";
+import { useAdsorb } from "@/hooks";
 
 const { componentData } = defineProps<{ componentData: CustomElement }>();
 // 动态引入组件
@@ -63,6 +64,7 @@ const componentWrapperRef = ref<HTMLElement | null>(null);
 const stageStore = useStageStore();
 const projectStore = useProjectStore();
 const actionStore = useAcionStore();
+const { getAdsorbInfo } = useAdsorb();
 const editWapperStyle = computed(() => {
   const { width = 400, height = 260 } = componentData.container.props || {};
 
@@ -137,19 +139,26 @@ useDraggable(componentWrapperRef, {
     const xMoveLength = position.x - originPosition.left;
     const yMoveLentgh = position.y - originPosition.top;
 
-    moveLeft = Math.max(Math.abs(xMoveLength), Math.abs(yMoveLentgh));
+    const { newMoveX, newMoveY } = getAdsorbInfo({
+      moveX: xMoveLength,
+      moveY: yMoveLentgh,
+      moveH: 0,
+      moveW: 0,
+    });
+
+    moveLeft = Math.max(Math.abs(newMoveX), Math.abs(newMoveY));
     // 对每个选中的组件进行移动
     projectStore.currentSelectedElements.forEach((item) => {
       const { x, y } = item.container.props || {};
       projectStore.updateElement(
         item.key,
         "container.props.x",
-        Math.round(x + xMoveLength)
+        Math.round(x + newMoveX)
       );
       projectStore.updateElement(
         item.key,
         "container.props.y",
-        Math.round(y + yMoveLentgh)
+        Math.round(y + newMoveY)
       );
     });
   },

+ 8 - 9
apps/shalu-bigscreen-designer/src/views/designer/component/Scaleplate.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="scaleplate" id="scaleplate">
     <!-- 显示/隐藏参考线 -->
-    <div class="refer-line-img" @click="showReferLine = !showReferLine">
-      <EyeFilled v-if="showReferLine" />
+    <div class="refer-line-img" @click="projectStore.toggleReffer()">
+      <EyeFilled v-if="projectStore.showReffer" />
       <EyeInvisibleFilled v-else />
     </div>
     <!-- 标尺 -->
@@ -37,7 +37,7 @@
     <div
       class="refer-line"
       v-for="item in stageStore.getReferLines"
-      v-show="showReferLine"
+      v-show="projectStore.showReffer"
       :key="item.key"
       :style="{ left: item.x + 'px', top: item.y + 'px' }"
       :class="item.type === 'horizontal' ? 'refer-line-h' : 'refer-line-v'"
@@ -75,7 +75,7 @@ import { onMounted, ref, onBeforeUnmount, nextTick, watch } from "vue";
 import type { Ref } from "vue";
 import { EyeFilled, EyeInvisibleFilled } from "@ant-design/icons-vue";
 import { UseDraggable } from "@vueuse/components";
-import { drawScaleplate } from "@/utils";
+import { drawScaleplate, uuid } from "@/utils";
 import { useStageStore } from "@/store/modules/stage";
 import { useProjectStore } from "@/store/modules/project";
 import type { ReferLine } from "#/project";
@@ -84,7 +84,6 @@ const stageStore = useStageStore();
 const projectStore = useProjectStore();
 const horizontalRef = ref<HTMLElement | null>(null);
 const verticalRef = ref<HTMLElement | null>(null);
-const showReferLine: Ref<boolean> = ref(true);
 const windowSize: Ref<{ width: number; height: number }> = ref({
   width: 0,
   height: 0,
@@ -123,7 +122,7 @@ const handleDrawScaleplate = () => {
 
 /* =============================== 参考线 ================================= */
 const virtualReferLine: Ref<ReferLine> = ref({
-  key: 0,
+  key: '0',
   x: 0,
   y: 0,
   value: 0,
@@ -154,14 +153,14 @@ const handleAddReferLine = () => {
 
   projectStore.addReferLine({
     ...virtualReferLine.value,
-    key: Date.now(),
+    key: uuid(),
   });
 };
 /* 拖拽参考线 */
 const handleDragReferLine = (
   { x, y }: { x: number; y: number },
-  e: PointerEvent,
-  key: number
+  _: PointerEvent,
+  key: string
 ) => {
   const referLine = projectStore.referLines.find((item) => item.key === key);
   if (!referLine) return;

+ 3 - 3
apps/shalu-bigscreen-designer/types/project.d.ts

@@ -45,15 +45,15 @@ declare interface CustomElement {
 
 declare export interface ReferLine {
   // 辅助线唯一标识
-  key: number;
+  key: string;
   // 辅助线类型
   type: 'horizontal' | 'vertical' | null;
   // 辅助线位置
   value: number;
   // x坐标
-  x?: number;
+  x: number;
   // y坐标
-  y?: number;
+  y: number;
 }
 
 declare interface Page {

+ 20 - 3
package.json

@@ -3,6 +3,7 @@
   "version": "1.0.0",
   "privite": true,
   "scripts": {
+    "serve": "pnpm run dev",
     "dev": "pnpm -C apps/shalu-bigscreen-designer run dev",
     "build:ui": "pnpm -C packages/shalu-dashboard-ui run build"
   },
@@ -14,9 +15,25 @@
     "gulp": "^5.0.0",
     "sucrase": "^3.35.0",
     "typescript": "^5.5.3",
-    "vue": "^3.4.31"
+    "vue": "^3.2.13",
+    "vite": "^5.3.4",
+    "vite-plugin-dts": "^3.9.1",
+    "vue-codemirror": "^6.1.1",
+    "vue-hooks-plus": "^2.2.0",
+    "vue-loader": "^17.4.2",
+    "vue-tsc": "^2.0.24",
+    "@vitejs/plugin-vue": "^5.0.4",
+    "@vitejs/plugin-vue-jsx": "^4.0.0",
+    "less-loader": "^12.2.0",
+    "css-loader": "^7.1.2"
+    
   },
   "dependencies": {
-    "@shalu/dashboard-ui": "workspace:^"
+    "@shalu/dashboard-ui": "workspace:^",
+    "ant-design-vue": "^4.X",
+    "element-plus": "^2.7.6",
+    "echarts": "^5.5.1",
+    "vue-hooks-plus": "^2.2.0",
+    "lodash-es": "^4.17.21"
   }
-}
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 27 - 27
packages/shalu-dashboard-ui/lib/shalu-dashboard-ui.cjs


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
packages/shalu-dashboard-ui/lib/shalu-dashboard-ui.cjs.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 524 - 506
packages/shalu-dashboard-ui/lib/shalu-dashboard-ui.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
packages/shalu-dashboard-ui/lib/shalu-dashboard-ui.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 95 - 95
packages/shalu-dashboard-ui/lib/shalu-dashboard-ui.umd.cjs


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
packages/shalu-dashboard-ui/lib/shalu-dashboard-ui.umd.cjs.map


+ 2 - 14
packages/shalu-dashboard-ui/package.json

@@ -11,9 +11,7 @@
   "dependencies": {
     "@types/lodash-es": "^4.17.12",
     "@vueuse/core": "^10.11.0",
-    "core-js": "^3.8.3",
-    "echarts": "^5.5.1",
-    "lodash-es": "^4.17.21"
+    "core-js": "^3.8.3"
   },
   "devDependencies": {
     "@ant-design/icons-vue": "^7.0.1",
@@ -34,28 +32,18 @@
     "@vue/eslint-config-typescript": "^9.1.0",
     "@vue/test-utils": "^2.0.0-0",
     "@vue/vue3-jest": "^27.0.0-alpha.1",
-    "ant-design-vue": "^4.2.3",
     "babel-jest": "^27.0.6",
-    "css-loader": "^7.1.2",
-    "element-plus": "^2.7.6",
     "eslint": "^7.32.0",
     "eslint-config-prettier": "^8.3.0",
     "eslint-plugin-prettier": "^4.0.0",
     "eslint-plugin-vue": "^8.0.3",
     "jest": "^27.0.5",
     "js-beautify": "^1.15.1",
-    "less-loader": "^12.2.0",
     "lint-staged": "^11.1.2",
     "prettier": "^2.4.1",
     "progress-bar-webpack-plugin": "^2.1.0",
     "style-loader": "^4.0.0",
     "typescript": "^5.2.2",
-    "vite": "^5.3.4",
-    "vite-plugin-dts": "^3.9.1",
-    "vue": "^3.2.13",
-    "vue-codemirror": "^6.1.1",
-    "vue-hooks-plus": "^2.2.0",
-    "vue-loader": "^17.4.2",
-    "vue-tsc": "^2.0.24"
+    "vite-plugin-dts": "^3.9.1"
   }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 180 - 126
pnpm-lock.yaml