Quellcode durchsuchen

主页配置fix

zhudie vor 2 Jahren
Ursprung
Commit
1789a3badc

Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
src/assets/test/1-cir.svg


+ 4 - 0
src/assets/test/1-curv2.svg

@@ -17,4 +17,8 @@
             fill="url(#prefix__a)" />
 
     </g>
+    <!-- <g fill="none" fill-rule="evenodd">
+        <circle cx="16" cy="16" r="5" stroke-opacity="0.498250895" stroke="#B0E8FF" stroke-width="0.5" fill-opacity="1"
+            fill="#ffffff" />
+    </g> -->
 </svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 8 - 0
src/assets/test/2-shining.svg


+ 28 - 8
src/views/page-config/ConfigEdit.vue

@@ -134,7 +134,12 @@
       </div>
     </el-tooltip>
 
-    <ConfigDialog ref="configDrawer" @on-close="onClose" class="drawer-position" />
+    <ConfigDialog
+      ref="configDrawer"
+      @on-close="onClose"
+      @transformer-change="transformChange"
+      class="drawer-position"
+    />
 
     <ConfigFinish
       :visible="visibleResult"
@@ -150,7 +155,7 @@
   import ConfigFinish from './component/ConfigFinish.vue';
   import { storeToRefs } from 'pinia';
   import { ElMessage, ElInput } from 'element-plus';
-  import { onBeforeUnmount, onMounted, ref } from 'vue';
+  import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
   import { WorkShopInfoItem } from '@/api/scene/scene';
   import { computed } from 'vue';
   import { Search, Refresh, ArrowLeftBold, ArrowLeft } from '@element-plus/icons-vue';
@@ -162,7 +167,7 @@
   import { useRouter } from 'vue-router';
 
   const mapEditor = useMapEditor();
-  const { bgImg, addedShops, activeShopId } = storeToRefs(mapEditor);
+  const { bgImg, addedShops, activeShopId, showShops } = storeToRefs(mapEditor);
   const { addShop, addBg, calcLayout, resetMap, createMap, deleteShop } = mapEditor;
 
   const router = useRouter();
@@ -198,6 +203,18 @@
     leftShow.value = val;
   };
 
+  const transformChange = () => {
+    mapContainerRef.value.updateLayoutTransformer();
+  };
+
+  watch(
+    () => showShops,
+    () => {
+      transformChange();
+    },
+    { deep: true },
+  );
+
   const shadow = ref(false);
   const shadowAdd = () => {
     shadow.value = true;
@@ -244,6 +261,8 @@
         }
         layoutId.value = res.id;
         const layoutJSON = res.layout ? safeParse(res.layout) : null;
+        // console.log();
+
         if (!layoutJSON) {
           return;
         }
@@ -300,9 +319,10 @@
     }
     const shopNode = {
       ...shop,
-      x: 20,
-      y: 20,
-      scale: 1,
+      x: 50,
+      y: 50,
+      scaleX: 1,
+      scaleY: 1,
       bgColor: 'rgba(58, 170, 209, 1)',
       fontSize: 14,
       fontColor: '#ffffff',
@@ -476,8 +496,8 @@
 
   .feedback-position {
     position: absolute;
-    left: 460px;
-    top: 150px;
+    left: 760px;
+    top: 250px;
     z-index: 9999;
   }
 

+ 0 - 318
src/views/page-config/component/ConfigDrawer copy.vue

@@ -1,318 +0,0 @@
-<template>
-  <div
-    ><el-dialog
-      v-model="dialogTableVisible"
-      :modal="false"
-      :show-close="false"
-      draggable
-      :append-to-body="false"
-      :destroy-on-close="true"
-      @close="closeDialog"
-    >
-      <template #header>
-        <div style="position: relative">
-          <div class="dialog-header">{{ editShop.name }}</div>
-          <img
-            src="~@/assets/icons/slide-right.png"
-            alt=""
-            class="dialog-return"
-            @click="closeDialog"
-          />
-        </div>
-      </template>
-      <div class="config-content">
-        <div>
-          <div class="uploader-title">缩略图</div>
-          <el-upload
-            class="pic-uploader"
-            list-type="picture-card"
-            :action="
-              editShop.thumbnail
-                ? '/api/homepageConfig/updateWorkshopPicture'
-                : '/api/homepageConfig/uploadWorkshopPicture'
-            "
-            :show-file-list="false"
-            :with-credentials="true"
-            :before-upload="beforeAvatarUpload"
-            :on-success="handleAvatarSuccess"
-            :data="
-              editShop.thumbnail
-                ? { workshopId: editShop.id, deleteFileName: editShop.thumbnail }
-                : { workshopId: editShop.id }
-            "
-          >
-            <img v-if="editShop.thumbnail" :src="editShop.thumbnail" class="avatar" />
-            <!-- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> -->
-            <div v-else>
-              <el-icon class="avatar-upload-icon" size="24px"><Plus /></el-icon>
-              <div class="uploader-config-text">上传照片</div>
-            </div>
-          </el-upload>
-          <div class="upload-config-tip">只支持.jpg格式</div>
-          <div style="display: flex; text-align: center"
-            ><img src="~@/assets/icons/warn.png" style="width: 14px; height: 14px" alt="" />
-            <div class="upload-notice">上传车间内部情况的视频流截图</div></div
-          >
-
-          <!-- <div class="upload-tips">备注:车间内部情况的视频流截图</div> -->
-        </div>
-        <hr />
-        <div>
-          <div class="content-title"
-            ><div class="uploader-title">填充</div>
-            <el-icon class="refresh-right"><RefreshRight /></el-icon
-          ></div>
-          <div class="color-select"
-            ><el-color-picker
-              v-model="editShop.bgColor"
-              show-alpha
-              size="small"
-              color-format="rgb"
-            /><div class="color-content">{{ showColor[0] }}&emsp;{{ showColor[1] }}</div></div
-          >
-        </div>
-        <hr />
-        <div>
-          <div class="content-title"
-            ><div class="uploader-title">文字</div>
-            <el-icon class="refresh-right"><RefreshRight /></el-icon
-          ></div>
-          <div style="display: flex">
-            <el-select
-              v-model="editShop.fontSize"
-              class="fontsize-select"
-              style="width: 50px"
-              size="small"
-            >
-              <el-option
-                v-for="(item, index) in fontSizeList"
-                :key="index"
-                :label="item"
-                :value="item"
-              />
-            </el-select>
-            <div class="color-fontsize-select"
-              ><el-color-picker v-model="editShop.fontColor" color-format="hex" size="small" /><div
-                class="color-fontSize-content"
-                >{{ editShop.fontColor }}</div
-              ></div
-            >
-          </div>
-          <hr />
-          <div>
-            <!-- //这里要变选值 -->
-            <div class="content-title"><div class="uploader-title">布局</div> </div>
-            <div class="layout-set">
-              <img src="~@/assets/icons/layout-left.png" alt="" style="margin-right: 19px" />
-              <img src="~@/assets/icons/layout-right.png" alt="" style="margin-right: 17px" />
-              <img src="~@/assets/icons/layout-top.png" alt="" />
-            </div>
-          </div>
-        </div>
-      </div>
-      <el-button type="primary" class="save-dialog" @click="saveWorkshopConfig">保存</el-button>
-    </el-dialog>
-  </div>
-</template>
-<script lang="ts" setup>
-  import { computed, ref } from 'vue';
-  import { Plus, RefreshRight } from '@element-plus/icons-vue';
-  import { ElMessage } from 'element-plus';
-  import { colorRGB2Hex } from '@/utils';
-  import useMapEditor, { MapWorkShopInfoItem } from '../stores/useMapEditor';
-  import { storeToRefs } from 'pinia';
-  import { cloneDeep } from 'lodash-es';
-  import { useGlobSetting } from '@/hooks/setting';
-  import urlJoin from 'url-join';
-
-  const mapEditor = useMapEditor();
-  const { addedShops, showShops, activeShopId } = storeToRefs(mapEditor);
-
-  const globSetting = useGlobSetting();
-
-  const editShop = computed(
-    () =>
-      showShops.value.find((item) => item.id === activeShopId.value) || ({} as MapWorkShopInfoItem),
-  );
-
-  const emit = defineEmits(['onClose', 'saveConfig']);
-
-  const showColor = computed(() => colorRGB2Hex(editShop.value!.bgColor));
-  const dialogTableVisible = ref(false);
-
-  const beforeAvatarUpload = (rawFile) => {
-    if (rawFile.type !== 'image/jpeg') {
-      ElMessage.error('请上传jpg格式的图片!');
-      return false;
-    }
-    return true;
-  };
-
-  const handleAvatarSuccess = (e) => {
-    editShop.value.thumbnail = urlJoin(globSetting.imgUrl!, e.data);
-  };
-
-  const openDialog = () => {
-    dialogTableVisible.value = !dialogTableVisible.value;
-  };
-
-  const closeDialog = () => {
-    dialogTableVisible.value = false;
-    showShops.value = cloneDeep(addedShops.value);
-    emit('onClose', true);
-  };
-
-  const fontSizeList = Array.from({ length: 11 }, (_, index) => index + 10);
-
-  const saveWorkshopConfig = () => {
-    addedShops.value = cloneDeep(showShops.value);
-  };
-
-  defineExpose({ openDialog });
-</script>
-
-<style lang="scss" scoped>
-  :deep(.el-dialog) {
-    width: 271px !important;
-    height: 800px !important;
-    position: absolute;
-    right: 0px;
-    top: -10px;
-  }
-
-  .dialog-header {
-    font-size: 16px;
-  }
-  .dialog-return {
-    position: absolute;
-    right: -10px;
-    top: 0px;
-    cursor: pointer;
-  }
-
-  :deep(.el-dialog__headerbtn .el-dialog__close) {
-    display: none;
-  }
-
-  .drawer-box {
-    width: 251px;
-    height: 711px;
-  }
-
-  :deep(.el-upload--picture-card) {
-    margin-left: 50px;
-    width: 104px;
-    height: 104px;
-  }
-  .pic-uploader .el-upload {
-    border: 1px dashed var(--el-border-color);
-    border-radius: 6px;
-    width: 104px;
-    height: 104px;
-    cursor: pointer;
-    margin-left: 0px;
-    position: relative;
-    overflow: hidden;
-    transition: var(--el-transition-duration-fast);
-  }
-
-  .uploader-title {
-    font-size: 12px;
-    margin-bottom: 8px;
-  }
-
-  .avatar {
-    width: 104px;
-    height: 104px;
-    object-fit: contain;
-  }
-
-  .el-icon.avatar-upload-icon {
-    font-size: 18px;
-    color: black;
-    width: 104px;
-    height: 104px;
-    text-align: center;
-    margin-top: -60px;
-    margin-bottom: 10px;
-  }
-
-  .uploader-config-text {
-    margin-top: -45px;
-    margin-left: 26px;
-    font-size: 14px;
-    font-weight: 400;
-    color: rgba(0, 0, 0, 0.88);
-  }
-  .upload-config-tip {
-    text-align: center;
-    font-size: 14px;
-    font-weight: 400;
-    color: rgba(0, 0, 0, 0.45);
-    margin-left: -20px;
-    margin-top: 8px;
-    margin-bottom: 8px;
-  }
-
-  .upload-notice {
-    font-size: 12px;
-    font-weight: 400;
-    color: rgba(0, 0, 0, 0.45);
-    margin-left: 4px;
-    margin-bottom: 16px;
-  }
-
-  .content-title {
-    display: flex;
-    margin-top: 16px;
-    margin-bottom: 8px;
-  }
-
-  .refresh-right {
-    margin-left: 4px;
-    margin-top: 2px;
-  }
-
-  .color-select {
-    display: flex;
-    margin-left: 34px;
-    margin-bottom: 16px;
-  }
-  .color-content {
-    width: 120px;
-    height: 24px;
-    line-height: 24px;
-    padding-left: 10px;
-    background: rgba(0, 0, 0, 0.04);
-  }
-
-  .fontsize-select {
-    margin-left: 34px;
-  }
-  .color-fontSize-content {
-    width: 74px;
-    height: 24px;
-    line-height: 24px;
-    padding-left: 10px;
-    background: rgba(0, 0, 0, 0.04);
-  }
-
-  .color-fontsize-select {
-    display: flex;
-    margin-bottom: 16px;
-  }
-  .layout-set {
-    width: 156px;
-    height: 24px;
-    background: #f5f5f5;
-    border-radius: 2px;
-    margin-left: 34px;
-    display: flex;
-  }
-
-  .save-dialog {
-    position: absolute;
-    left: 105px;
-    bottom: 35px;
-  }
-</style>

+ 9 - 1
src/views/page-config/component/ConfigDrawer.vue

@@ -108,18 +108,21 @@
                 alt=""
                 @click="posAdj(LabelPositionEnum.LEFT)"
                 style="margin-right: 19px; cursor: pointer"
+                :class="{ active: editShop.posType === LabelPositionEnum.LEFT }"
               />
               <img
                 src="~@/assets/icons/layout-right.png"
                 alt=""
                 @click="posAdj(LabelPositionEnum.RIGHT)"
                 style="margin-right: 17px; cursor: pointer"
+                :class="{ active: editShop.posType === LabelPositionEnum.RIGHT }"
               />
               <img
                 src="~@/assets/icons/layout-top.png"
                 alt=""
                 style="cursor: pointer"
                 @click="posAdj(LabelPositionEnum.TOP)"
+                :class="{ active: editShop.posType === LabelPositionEnum.TOP }"
               />
             </div>
           </div>
@@ -154,7 +157,7 @@
     return val;
   });
 
-  const emit = defineEmits(['onClose', 'saveConfig']);
+  const emit = defineEmits(['onClose', 'transformerChange']);
 
   const showColor = computed(() => colorRGB2Hex(editShop.value!.bgColor));
   const dialogTableVisible = ref(false);
@@ -184,6 +187,7 @@
 
   const posAdj = (pos: LabelPositionEnum) => {
     editShop.value.posType = pos;
+    emit('transformerChange');
   };
 
   const fontSizeList = Array.from({ length: 11 }, (_, index) => index + 10);
@@ -340,4 +344,8 @@
     left: 105px;
     bottom: 35px;
   }
+
+  .active {
+    background-color: #cbcdce;
+  }
 </style>

+ 1 - 3
src/views/page-config/component/ConfigFinish.vue

@@ -17,9 +17,7 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { ref } from 'vue';
-  import { Close, Plus, RefreshRight } from '@element-plus/icons-vue';
-  import { ElMessage } from 'element-plus';
+  import { Close } from '@element-plus/icons-vue';
   import { useRouter } from 'vue-router';
   const router = useRouter();
 

+ 0 - 139
src/views/page-config/component/mapContainer/LabelItem copy.vue

@@ -1,139 +0,0 @@
-<template>
-  <v-image ref="pointRef" :config="getPointCurvConfig()" />
-  <v-image ref="rectRef" :config="getRectCurConfig()" />
-  <v-text :config="getTextConfig()" />
-  <v-image :config="shineConfig" />
-</template>
-
-<script setup lang="ts">
-  import { ref, onMounted, nextTick, computed, watch } from 'vue';
-  import rectBlock from '@/assets/test/2-rect.svg';
-  import pointCurv from '@/assets/test/1-curv2.svg';
-  import shine from '@/assets/test/2-shine.svg';
-  import Konva from 'konva';
-  import { MapWorkShopInfoItem } from '../../stores/useMapEditor';
-
-  const props = defineProps<{ shop: MapWorkShopInfoItem }>();
-
-  const shopData = computed(() => props.shop);
-
-  const curvImage = ref<HTMLImageElement>(new Image());
-  const rectImage = ref<HTMLImageElement>(new Image());
-  const shineImage = ref<HTMLImageElement>(new Image());
-  const rectRef = ref<Konva.Image>();
-  const pointRef = ref<Konva.Image>();
-
-  const getRGBANum = (color: string) => {
-    if (!color) return [0, 0, 0, 0];
-    const pattern = /\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)$/;
-    const array = color.match(pattern);
-    return [
-      Number(array![1]) || 0,
-      Number(array![2]) || 0,
-      Number(array![3]) || 0,
-      Number(array![4]) || 0,
-    ];
-  };
-
-  const nodeUpdateFilter = (node: Konva.Node) => {
-    node.cache();
-    const rgba = getRGBANum(shopData.value.bgColor);
-    node.red(rgba[0]);
-    node.green(rgba[1]);
-    node.blue(rgba[2]);
-    node.alpha(rgba[3]);
-  };
-
-  const getPointCurvConfig = () => {
-    return {
-      x: 0,
-      y: 0,
-      width: 32,
-      height: 39,
-      // fill: shopData.value.bgColor,
-      image: curvImage.value,
-    };
-  };
-
-  const getRectCurConfig = () => {
-    return {
-      x: 53,
-      y: 0,
-      width: 160,
-      height: 38,
-      // fill: shopData.value.bgColor,
-      image: rectImage.value,
-    };
-  };
-
-  const getTextConfig = () => {
-    return {
-      x: 53,
-      y: 0,
-      text: shopData.value.name,
-      fontSize: shopData.value.fontSize,
-      fontFamily: 'TRENDS',
-      fill: shopData.value.fontColor,
-      width: 160,
-      height: 32,
-      align: 'center',
-      verticalAlign: 'middle',
-    };
-  };
-
-  const shineConfig = computed(() => {
-    return {
-      x: 0,
-      y: 0,
-      width: 213,
-      height: 38,
-      // fill: shopData.value.bgColor,
-      image: shineImage.value,
-    };
-  });
-
-  watch(
-    shopData.value,
-    () => {
-      console.log('pointRef.value!.getNode()', pointRef.value!.getNode());
-      nextTick(() => {
-        console.log('pointRef.value!.getNode()', pointRef.value!.getNode());
-        nodeUpdateFilter(pointRef.value!.getNode());
-
-        nodeUpdateFilter(rectRef.value!.getNode());
-      });
-    },
-    { deep: true },
-  );
-
-  onMounted(() => {
-    const svgImg = new Image();
-    svgImg.onload = () => {
-      curvImage.value = svgImg;
-      nextTick(() => {
-        nodeUpdateFilter(pointRef.value?.getNode());
-      });
-    };
-    svgImg.src = pointCurv;
-
-    const rectImg = new Image();
-    rectImg.onload = () => {
-      rectImage.value = rectImg;
-      nextTick(() => {
-        nodeUpdateFilter(rectRef.value?.getNode());
-      });
-    };
-    rectImg.src = rectBlock;
-
-    const shineImg = new Image();
-    shineImg.onload = () => {
-      shineImage.value = shineImg;
-    };
-    shineImg.src = shine;
-
-    rectRef.value?.getNode().filters([Konva.Filters.RGBA]);
-    pointRef.value?.getNode().filters([Konva.Filters.RGBA]);
-  });
-</script>
-
-<style scoped></style>

+ 24 - 202
src/views/page-config/component/mapContainer/LabelItem.vue

@@ -1,39 +1,37 @@
 <template>
-  <v-image ref="pointRef" :config="getPointCurvConfig()" />
-  <v-image ref="rectRef" :config="getRectCurConfig()" />
-  <v-text :config="getTextConfig()" />
-  <v-image :config="shineConfig()" />
+  <v-image ref="pointRef" :config="getPointCurvConfig(props.shop.posType, curvImage)" />
+  <v-image :config="getCirConfig(props.shop.posType, cirImage)" />
+  <v-image ref="rectRef" :config="getRectCurConfig(props.shop.posType, rectImage)" />
+  <v-text :config="getTextConfig(props.shop)" />
+  <v-image :config="shineConfig(props.shop.posType, shineImage)" />
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, nextTick, computed, watch } from 'vue';
+  import { ref, onMounted, nextTick, watch } from 'vue';
   import rectBlock from '@/assets/test/2-rect.svg';
   import pointCurv from '@/assets/test/1-curv2.svg';
-  import shine from '@/assets/test/2-shine.svg';
+  import shine from '@/assets/test/2-shining.svg';
+  import circle from '@/assets/test/1-cir.svg';
   import Konva from 'konva';
-  import { MapWorkShopInfoItem, LabelPositionEnum } from '../../stores/useMapEditor';
-  // import { LabelPositionEnum, MapWorkShopInfoItem } from '../stores/useMapEditor';
+  import { MapWorkShopInfoItem } from '../../stores/useMapEditor';
+  import {
+    getRGBANum,
+    getPointCurvConfig,
+    getCirConfig,
+    getRectCurConfig,
+    getTextConfig,
+    shineConfig,
+  } from './labelConfig';
 
   const props = defineProps<{ shop: MapWorkShopInfoItem }>();
 
   const curvImage = ref<HTMLImageElement>(new Image());
   const rectImage = ref<HTMLImageElement>(new Image());
   const shineImage = ref<HTMLImageElement>(new Image());
+  const cirImage = ref<HTMLImageElement>(new Image());
   const rectRef = ref<Konva.Image>();
   const pointRef = ref<Konva.Image>();
 
-  const getRGBANum = (color: string) => {
-    if (!color) return [0, 0, 0, 0];
-    const pattern = /\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)$/;
-    const array = color.match(pattern);
-    return [
-      Number(array![1]) || 0,
-      Number(array![2]) || 0,
-      Number(array![3]) || 0,
-      Number(array![4]) || 0,
-    ];
-  };
-
   const nodeUpdateFilter = (node: Konva.Node) => {
     node.cache();
     const rgba = getRGBANum(props.shop.bgColor);
@@ -43,188 +41,6 @@
     node.alpha(rgba[3]);
   };
 
-  // const getPointCurvConfig = () => {
-  //   return {
-  //     x: 65,
-  //     y: 35,
-  //     width: 32,
-  //     height: 39,
-  //     image: curvImage.value,
-  //   };
-  // };
-
-  const getPointCurvConfig = () => {
-    if (props.shop.posType === LabelPositionEnum.LEFT) {
-      return {
-        x: 0,
-        y: 0,
-        width: 32,
-        height: 39,
-        image: curvImage.value,
-      };
-    } else if (props.shop.posType === LabelPositionEnum.RIGHT) {
-      return {
-        x: 183,
-        y: 0,
-        width: 32,
-        height: 39,
-        image: curvImage.value,
-      };
-    } else {
-      return {
-        x: 65,
-        y: 35,
-        width: 32,
-        height: 39,
-        image: curvImage.value,
-      };
-    }
-  };
-
-  // const getRectCurConfig = () => {
-  //   return {
-  //     x: 0,
-  //     y: 0,
-  //     width: 160,
-  //     height: 38,
-  //     image: rectImage.value,
-  //   };
-  // };
-
-  const getRectCurConfig = () => {
-    if (props.shop.posType === LabelPositionEnum.LEFT) {
-      return {
-        x: 53,
-        y: 0,
-        width: 160,
-        height: 38,
-        image: rectImage.value,
-      };
-    } else if (props.shop.posType === LabelPositionEnum.RIGHT) {
-      return {
-        x: 0,
-        y: 0,
-        width: 160,
-        height: 38,
-        image: rectImage.value,
-      };
-    } else {
-      return {
-        x: 0,
-        y: 0,
-        width: 160,
-        height: 38,
-        image: rectImage.value,
-      };
-    }
-  };
-
-  // const getTextConfig = () => {
-  //   return {
-  //     x: 0,
-  //     y: 0,
-  //     text: props.shop.name,
-  //     fontSize: props.shop.fontSize,
-  //     fontFamily: 'TRENDS',
-  //     fill: props.shop.fontColor,
-  //     width: 160,
-  //     height: 32,
-  //     align: 'center',
-  //     verticalAlign: 'middle',
-  //   };
-  // };
-
-  const getTextConfig = () => {
-    if (props.shop.posType === LabelPositionEnum.LEFT) {
-      return {
-        x: 53,
-        y: 0,
-        text: props.shop.name,
-        fontSize: props.shop.fontSize,
-        fontFamily: 'TRENDS',
-        fill: props.shop.fontColor,
-        width: 160,
-        height: 32,
-        align: 'center',
-        verticalAlign: 'middle',
-      };
-    } else if (props.shop.posType === LabelPositionEnum.RIGHT) {
-      return {
-        x: 0,
-        y: 0,
-        text: props.shop.name,
-        fontSize: props.shop.fontSize,
-        fontFamily: 'TRENDS',
-        fill: props.shop.fontColor,
-        width: 160,
-        height: 32,
-        align: 'center',
-        verticalAlign: 'middle',
-      };
-    } else {
-      return {
-        x: 0,
-        y: 0,
-        text: props.shop.name,
-        fontSize: props.shop.fontSize,
-        fontFamily: 'TRENDS',
-        fill: props.shop.fontColor,
-        width: 160,
-        height: 32,
-        align: 'center',
-        verticalAlign: 'middle',
-      };
-    }
-  };
-
-  // const shineConfig = () => {
-  //   return {
-  //     x: 0,
-  //     y: 0,
-  //     width: 163,
-  //     height: 38,
-  //     image: shineImage.value,
-  //   };
-  // };
-
-  const shineConfig = () => {
-    // if (props.shop.posType === LabelPositionEnum.LEFT) {
-    return {
-      x: 0,
-      y: 0,
-      width: 213,
-      height: 38,
-      image: shineImage.value,
-    };
-    // } else if (props.shop.posType === LabelPositionEnum.RIGHT) {
-    //   return {
-    //     x: 0,
-    //     y: 0,
-    //     width: 213,
-    //     height: 38,
-    //     image: shineImage.value,
-    //   };
-    // } else {
-    //   return {
-    //     x: 0,
-    //     y: 0,
-    //     width: 213,
-    //     height: 38,
-    //     image: shineImage.value,
-    //   };
-    // }
-  };
-
-  // const shineConfig = computed(() => {
-  //   return {
-  //     x: 0,
-  //     y: 0,
-  //     width: 213,
-  //     height: 38,
-  //     image: shineImage.value,
-  //   };
-  // });
-
   watch(
     () => props.shop,
     () => {
@@ -261,6 +77,12 @@
     };
     shineImg.src = shine;
 
+    const cirImg = new Image();
+    cirImg.onload = () => {
+      cirImage.value = cirImg;
+    };
+    cirImg.src = circle;
+
     rectRef.value?.getNode().filters([Konva.Filters.RGBA]);
     pointRef.value?.getNode().filters([Konva.Filters.RGBA]);
   });

+ 0 - 114
src/views/page-config/component/mapContainer/MapContainer copy.vue

@@ -1,114 +0,0 @@
-<template>
-  <div>
-    <v-stage
-      ref="stageRef"
-      :config="stageSize"
-      @mousedown="handleStageMouseDown"
-      @touchstart="handleStageMouseDown"
-    >
-      <v-layer ref="layerRef">
-        <v-image :config="bgConfig" />
-        <v-group
-          v-for="item in showShops"
-          :key="item.id"
-          :config="getGroupConfig(item)"
-          @transformend="handleTransformEnd"
-        >
-          <LabelItem :shop="item" />
-        </v-group>
-        <v-transformer ref="transformerRef" :config="transformerConfig" />
-      </v-layer>
-    </v-stage>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, ref } from 'vue';
-  import LabelItem from './LabelItem.vue';
-  import { storeToRefs } from 'pinia';
-  import useMapEditor, { MapWorkShopInfoItem } from '../../stores/useMapEditor';
-  import Konva from 'konva';
-
-  const mapEditor = useMapEditor();
-  const { mapWidth, mapHeight, showShops, bgImage } = storeToRefs(mapEditor);
-
-  const stageRef = ref<Konva.Stage>();
-  const layerRef = ref<Konva.Layer>();
-  const transformerRef = ref<Konva.Transformer>();
-
-  let selectedShape = -1;
-
-  const stageSize = computed(() => {
-    return {
-      // width: mapWidth.value,
-      // height: mapHeight.value,
-      width: 1920,
-      height: 1080,
-    };
-  });
-
-  const bgConfig = computed(() => {
-    return {
-      width: 1920,
-      height: 1080,
-      image: bgImage.value,
-      name: 'bg',
-    };
-  });
-
-  const getGroupConfig = (shop: MapWorkShopInfoItem) => {
-    return {
-      x: shop.x,
-      y: shop.y,
-      id: shop.id + '',
-      draggable: true,
-      name: 'group',
-    };
-  };
-
-  const transformerConfig = {
-    keepRatio: true,
-    rotateEnabled: false,
-    enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
-  };
-
-  const handleStageMouseDown = (e) => {
-    if (e.target.attrs.name === 'bg') {
-      selectedShape = -1;
-      updateTransformer();
-    }
-
-    if (e.target.parent.attrs.name === 'group') {
-      if (e.target.parent.id() === selectedShape) {
-        return;
-      }
-      selectedShape = e.target.parent.id();
-
-      updateTransformer();
-    }
-  };
-
-  const handleTransformEnd = (e) => {};
-
-  const updateTransformer = () => {
-    const transformerNode = transformerRef.value!.getNode();
-    const layer = layerRef.value!.getNode().getLayer();
-
-    if (selectedShape >= 0) {
-      const selectedNode = layer.findOne('#' + selectedShape);
-      (transformerNode as Konva.Transformer).nodes([selectedNode!]);
-    } else {
-      (transformerNode as Konva.Transformer).nodes([]);
-    }
-  };
-
-  const getLayout = () => {
-    const json = stageRef.value?.getStage().toJSON();
-
-    return json;
-  };
-
-  defineExpose({ getLayout });
-</script>
-
-<style scoped></style>

+ 20 - 18
src/views/page-config/component/mapContainer/MapContainer.vue

@@ -12,8 +12,7 @@
           v-for="item in showShops"
           :key="item.id"
           :config="getGroupConfig(item)"
-          @transformend="handleTransformEnd"
-          @click="handleClick"
+          @dblclick="handleClick"
         >
           <LabelItem :shop="item" />
         </v-group>
@@ -29,7 +28,6 @@
   import { storeToRefs } from 'pinia';
   import useMapEditor, { MapWorkShopInfoItem } from '../../stores/useMapEditor';
   import Konva from 'konva';
-  // import { nextTick } from 'process';
 
   const mapEditor = useMapEditor();
   const { showShops, bgImage, activeShopId } = storeToRefs(mapEditor);
@@ -40,13 +38,8 @@
   const layerRef = ref<Konva.Layer>();
   const transformerRef = ref<Konva.Transformer>();
 
-  // let selectedShape = -1;
-  const selectedShape = ref<number>(-1);
-
   const stageSize = computed(() => {
     return {
-      // width: mapWidth.value,
-      // height: mapHeight.value,
       width: 1920,
       height: 1080,
     };
@@ -65,6 +58,8 @@
     return {
       x: shop.x,
       y: shop.y,
+      scaleX: shop.scaleX,
+      scaleY: shop.scaleY,
       id: shop.id + '',
       draggable: true,
       name: 'group',
@@ -79,41 +74,48 @@
 
   const handleStageMouseDown = (e) => {
     if (e.target.attrs.name === 'bg') {
-      selectedShape.value = -1;
+      activeShopId.value = -1;
       updateTransformer();
     }
 
     if (e.target.parent.attrs.name === 'group') {
-      if (e.target.parent.id() === selectedShape.value) {
+      if (e.target.parent.id() === activeShopId.value) {
         return;
       }
       activeShopId.value = e.target.parent.id();
-      selectedShape.value = e.target.parent.id();
       updateTransformer();
     }
   };
 
-  const handleTransformEnd = (e) => {};
-
   const updateTransformer = () => {
     const transformerNode = transformerRef.value!.getNode();
     const layer = layerRef.value!.getNode().getLayer();
-
-    if (selectedShape.value >= 0) {
-      const selectedNode = layer.findOne('#' + selectedShape.value);
+    if (activeShopId.value! >= 0) {
+      const selectedNode = layer.findOne('#' + activeShopId.value);
       (transformerNode as Konva.Transformer).nodes([selectedNode!]);
     } else {
       (transformerNode as Konva.Transformer).nodes([]);
     }
   };
 
+  const updateLayoutTransformer = () => {
+    const transformerNode = transformerRef.value!.getNode();
+    const layer = layerRef.value!.getNode().getLayer();
+    (transformerNode as Konva.Transformer).nodes([]);
+    const selectedNode = layer.findOne('#' + activeShopId.value);
+    if (selectedNode) {
+      nextTick(() => {
+        (transformerNode as Konva.Transformer)?.nodes([selectedNode!]);
+      });
+    }
+  };
+
   const handleClick = () => {
     emit('onOpen');
   };
 
   watch(activeShopId, () => {
     nextTick(() => {
-      selectedShape.value = activeShopId.value!;
       updateTransformer();
     });
   });
@@ -124,7 +126,7 @@
     return json;
   };
 
-  defineExpose({ getLayout });
+  defineExpose({ getLayout, updateLayoutTransformer });
 </script>
 
 <style scoped></style>

+ 168 - 0
src/views/page-config/component/mapContainer/labelConfig.ts

@@ -0,0 +1,168 @@
+import { LabelPositionEnum } from '../../stores/useMapEditor';
+
+export const getRGBANum = (color: string) => {
+  if (!color) return [0, 0, 0, 0];
+  const pattern = /\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)$/;
+  const array = color.match(pattern);
+  return [
+    Number(array![1]) || 0,
+    Number(array![2]) || 0,
+    Number(array![3]) || 0,
+    Number(array![4]) || 0,
+  ];
+};
+
+export const getPointCurvConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 0,
+      y: 0,
+      width: 32,
+      height: 39,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 183,
+      y: 0,
+      width: 32,
+      height: 39,
+      image: image,
+    };
+  } else {
+    return {
+      x: 65,
+      y: 35,
+      width: 32,
+      height: 39,
+      image: image,
+    };
+  }
+};
+
+export const getCirConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 0,
+      y: 0,
+      width: 32,
+      height: 32,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 183,
+      y: 0,
+      width: 32,
+      height: 32,
+      image: image,
+    };
+  } else {
+    return {
+      x: 65,
+      y: 35,
+      width: 32,
+      height: 32,
+      image: image,
+    };
+  }
+};
+
+export const getRectCurConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 53,
+      y: 0,
+      width: 160,
+      height: 38,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 0,
+      y: 0,
+      width: 160,
+      height: 38,
+      image: image,
+    };
+  } else {
+    return {
+      x: 0,
+      y: 0,
+      width: 160,
+      height: 38,
+      image: image,
+    };
+  }
+};
+
+export const getTextConfig = (shop: any) => {
+  if (shop.posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 53,
+      y: 0,
+      text: shop.name,
+      fontSize: shop.fontSize,
+      fontFamily: 'TRENDS',
+      fill: shop.fontColor,
+      width: 160,
+      height: 32,
+      align: 'center',
+      verticalAlign: 'middle',
+    };
+  } else if (shop.posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 0,
+      y: 0,
+      text: shop.name,
+      fontSize: shop.fontSize,
+      fontFamily: 'TRENDS',
+      fill: shop.fontColor,
+      width: 160,
+      height: 32,
+      align: 'center',
+      verticalAlign: 'middle',
+    };
+  } else {
+    return {
+      x: 0,
+      y: 0,
+      text: shop.name,
+      fontSize: shop.fontSize,
+      fontFamily: 'TRENDS',
+      fill: shop.fontColor,
+      width: 160,
+      height: 32,
+      align: 'center',
+      verticalAlign: 'middle',
+    };
+  }
+};
+
+export const shineConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 100,
+      y: 0,
+      width: 107,
+      height: 38,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 55,
+      y: 0,
+      width: 107,
+      height: 38,
+      image: image,
+    };
+  } else {
+    return {
+      x: 55,
+      y: 0,
+      width: 107,
+      height: 38,
+      image: image,
+    };
+  }
+};

+ 0 - 124
src/views/page-config/stores/useMapEditor copy 2.ts

@@ -1,124 +0,0 @@
-import { ref } from 'vue';
-import { defineStore } from 'pinia';
-import { WorkShopInfoItem } from '@/api/scene/scene';
-import { cloneDeep } from 'lodash-es';
-import { useGlobSetting } from '@/hooks/setting';
-import safeParse from '@/utils/safeParse';
-import urlJoin from 'url-join';
-import emptyImg from '@/assets/images/table/table-empty.png';
-
-export enum LabelPositionEnum {
-  LEFT = 'left',
-  RIGHT = 'right',
-  TOP = 'top',
-}
-
-export type EditStyle = {
-  x: number;
-  y: number;
-  scale: number;
-  thumbnail?: string;
-  bgColor: string;
-  fontSize: number;
-  fontColor: string;
-  posType: LabelPositionEnum;
-};
-
-export type MapWorkShopInfoItem = WorkShopInfoItem & EditStyle;
-
-export const useMapEditor = defineStore('home-map-ediotr', () => {
-  const globSetting = useGlobSetting();
-
-  const bgImg = ref('');
-  const mapWidth = ref(0);
-  const mapHeight = ref(0);
-  const addedShops = ref<MapWorkShopInfoItem[]>([]);
-  const showShops = ref<MapWorkShopInfoItem[]>([]);
-  const activeShopId = ref<number>();
-
-  /** konva elements refs */
-  const bgImage = ref<HTMLImageElement>(new Image());
-
-  const addBg = () => {
-    const imgUrl = urlJoin(globSetting.imgUrl!, bgImg.value);
-    console.log(imgUrl);
-
-    const tempImg = new Image();
-    tempImg.onload = () => {
-      mapWidth.value = tempImg.width;
-      mapHeight.value = tempImg.height;
-      bgImage.value = tempImg;
-    };
-    tempImg.src = imgUrl;
-  };
-
-  const addShop = (shop: MapWorkShopInfoItem) => {
-    activeShopId.value = shop.id;
-    addedShops.value.push(cloneDeep(shop));
-    showShops.value.push(cloneDeep(shop));
-  };
-
-  const calcLayout = (json: string) => {
-    const mapJson = safeParse(json);
-    const mapData = mapJson.children[0].children;
-    const layout = {
-      bgInfo: {
-        width: mapWidth.value,
-        height: mapHeight.value,
-        img: bgImg.value,
-      },
-      shopList: addedShops.value.map((shop) => {
-        const mapAttr = mapData.find((item) => item.id === shop.id + '')!.attrs;
-        const temp = cloneDeep(shop) as any;
-        delete temp.children;
-        temp.x = mapAttr.x;
-        temp.y = mapAttr.y;
-        temp.scale = mapAttr.scaleX || 1;
-        return temp;
-      }),
-    };
-
-    return JSON.stringify(layout);
-  };
-
-  const createMap = (layout) => {
-    bgImg.value = layout.bgInfo.img;
-    mapWidth.value = layout.bgInfo.width;
-    mapHeight.value = layout.bgInfo.height;
-    addedShops.value = cloneDeep(layout.shopList);
-    showShops.value = cloneDeep(layout.shopList);
-  };
-
-  const deleteShop = () => {
-    addedShops.value = addedShops.value.filter((item) => item.id !== activeShopId.value);
-    showShops.value = showShops.value.filter((item) => item.id !== activeShopId.value);
-    activeShopId.value = undefined;
-  };
-
-  const resetMap = () => {
-    bgImg.value = '';
-    mapWidth.value = 0;
-    mapHeight.value = 0;
-    addedShops.value = [];
-    showShops.value = [];
-    activeShopId.value = undefined;
-  };
-
-  return {
-    bgImg,
-    mapWidth,
-    mapHeight,
-    addedShops,
-    showShops,
-    activeShopId,
-    bgImage,
-    addShop,
-    addBg,
-    calcLayout,
-    createMap,
-    deleteShop,
-    resetMap,
-  };
-});
-
-export default useMapEditor;

+ 0 - 111
src/views/page-config/stores/useMapEditor copy.ts

@@ -1,111 +0,0 @@
-import { ref } from 'vue';
-import { defineStore } from 'pinia';
-import { WorkShopInfoItem } from '@/api/scene/scene';
-import { cloneDeep } from 'lodash-es';
-import { useGlobSetting } from '@/hooks/setting';
-import urlJoin from 'url-join';
-
-export enum LabelPositionEnum {
-  LEFT = 'left',
-  RIGHT = 'right',
-  TOP = 'top',
-}
-
-export type EditStyle = {
-  x: number;
-  y: number;
-  scale: number;
-  thumbnail?: string;
-  bgColor: string;
-  fontSize: number;
-  fontColor: string;
-  posType: LabelPositionEnum;
-};
-
-export type MapWorkShopInfoItem = WorkShopInfoItem & EditStyle;
-
-export const useMapEditor = defineStore('home-map-ediotr', () => {
-  const globSetting = useGlobSetting();
-
-  const bgImg = ref('');
-  const mapWidth = ref(0);
-  const mapHeight = ref(0);
-  const addedShops = ref<MapWorkShopInfoItem[]>([]);
-  const showShops = ref<MapWorkShopInfoItem[]>([]);
-  const activeShop = ref<MapWorkShopInfoItem>({} as MapWorkShopInfoItem);
-
-  const addBg = () => {
-    const imgUrl = urlJoin(globSetting.imgUrl!, bgImg.value);
-    console.log(imgUrl);
-
-    const img = new Image();
-    img.onload = () => {
-      mapWidth.value = img.width;
-      mapHeight.value = img.height;
-    };
-    img.src = imgUrl;
-  };
-
-  const addShop = (shop: MapWorkShopInfoItem) => {
-    activeShop.value = shop;
-    addedShops.value.push(cloneDeep(shop));
-    showShops.value.push(cloneDeep(shop));
-  };
-
-  const toJson = () => {
-    const layout = {
-      bgInfo: {
-        width: mapWidth.value,
-        height: mapHeight.value,
-        img: bgImg.value,
-      },
-      shopList: addedShops.value.map((shop) => {
-        const temp = cloneDeep(shop) as any;
-        delete temp.children;
-        return temp;
-      }),
-    };
-
-    return JSON.stringify(layout);
-  };
-
-  const createMap = (layout) => {
-    bgImg.value = layout.bgInfo.img;
-    mapWidth.value = layout.bgInfo.width;
-    mapHeight.value = layout.bgInfo.height;
-    addedShops.value = cloneDeep(layout.shopList);
-    showShops.value = cloneDeep(layout.shopList);
-  };
-
-  const deleteShop = () => {
-    addedShops.value = addedShops.value.filter((item) => item.id !== activeShop.value.id);
-    showShops.value = showShops.value.filter((item) => item.id !== activeShop.value.id);
-    activeShop.value = {} as MapWorkShopInfoItem;
-  };
-
-  const resetMap = () => {
-    bgImg.value = '';
-    mapWidth.value = 0;
-    mapHeight.value = 0;
-    addedShops.value = [];
-    showShops.value = [];
-    activeShop.value = {} as MapWorkShopInfoItem;
-  };
-
-  return {
-    bgImg,
-    mapWidth,
-    mapHeight,
-    addedShops,
-    showShops,
-    activeShop,
-    addShop,
-    addBg,
-    toJson,
-    createMap,
-    deleteShop,
-    resetMap,
-  };
-});
-
-export default useMapEditor;

+ 7 - 18
src/views/page-config/stores/useMapEditor.ts

@@ -16,7 +16,9 @@ export enum LabelPositionEnum {
 export type EditStyle = {
   x: number;
   y: number;
-  scale: number;
+  // scale: number;
+  scaleX: number;
+  scaleY: number;
   thumbnail?: string;
   bgColor: string;
   fontSize: number;
@@ -52,7 +54,6 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
       mapHeight.value = tempImg.height;
       bgImage.value = tempImg;
     };
-    // console.log('imgUrl.value', imgUrl.value);
     tempImg.src = imgUrl;
   };
 
@@ -60,20 +61,19 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
     activeShopId.value = shop.id;
     addedShops.value.push(cloneDeep(shop));
     showShops.value.push(cloneDeep(shop));
-    console.log('showShops.value', showShops.value);
   };
 
   const calcLayout = (json: string) => {
     const mapJson = safeParse(json);
-    console.log('mapJson', mapJson);
-
     const mapData = mapJson.children[0].children.filter((item) => item.className === 'Group');
+
     const shopListAdded = addedShops.value.map((item, index) => {
       item.x = mapData[index].attrs.x;
       item.y = mapData[index].attrs.y;
+      item.scaleX = mapData[index].attrs.scaleX || 1;
+      item.scaleY = mapData[index].attrs.scaleY || 1;
       return item;
     });
-    console.log('mapData', shopListAdded);
     const layout = {
       bgInfo: {
         width: mapWidth.value,
@@ -81,23 +81,12 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
         img: bgImg.value,
       },
       shopList: shopListAdded,
-      // shopList: addedShops.value.map((shop) => {
-      //   const mapAttr = mapData.find((item) => item.id === shop.id + '')!.attrs;
-      //   const temp = cloneDeep(shop) as any;
-      //   delete temp.children;
-      //   shop.x = mapAttr.x;
-      //   shop.y = mapAttr.y;
-      //   shop.scale = mapAttr.scaleX || 1;
-      //   return shop;
-      // }),
     };
-    console.log('JSON.stringify(layout)', JSON.stringify(layout));
+
     return JSON.stringify(layout);
   };
 
   const createMap = (layout) => {
-    console.log('layout.bgInfo.img', layout.bgInfo.img);
-
     bgImg.value = layout.bgInfo.img;
     mapWidth.value = layout.bgInfo.width;
     mapHeight.value = layout.bgInfo.height;