zhudie пре 2 година
родитељ
комит
74052c9c94

+ 15 - 11
src/views/page-config/ConfigEdit.vue

@@ -87,7 +87,7 @@
             class="camera-item flex justify-start items-center"
             :class="{
               isAdded: isAddedShop(item.id),
-              isActive: item.id === activeShopId,
+              isActive: item.id === Number(activeShopId),
             }"
             @click="handleAddShop(item)"
           >
@@ -97,7 +97,7 @@
       </div>
       <div ref="drawContainer" id="drawContainer" class="draw-container">
         <div id="shopEditContainer" v-moveable:1>
-          <MapContainer ref="mapContainerRef" />
+          <MapContainer ref="mapContainerRef" @on-open="openConfig" />
         </div>
         <el-upload
           v-if="!hasBg"
@@ -211,6 +211,10 @@
     configDrawer.value.openDialog();
   };
 
+  const openConfig = () => {
+    configDrawer.value.openDialog();
+  };
+
   //总体的保存,将整个数据传过去
   const visibleResult = ref(false);
   const configStatus = ref(true);
@@ -226,19 +230,18 @@
   };
 
   const changeShop = () => {
+    hasBg.value = false;
     resetMap();
     getShopContent();
-    hasBg.value = false;
   };
 
   const getShopContent = () => {
     getCompanyLayoutApi({ companyId: selectedCompany.value || 2, labelId: label.value || 1 }).then(
       (res) => {
         if (!res) {
+          layoutId.value = undefined;
           return;
         }
-        console.log('res', res);
-
         layoutId.value = res.id;
         const layoutJSON = res.layout ? safeParse(res.layout) : null;
         if (!layoutJSON) {
@@ -246,6 +249,7 @@
         }
         hasBg.value = true;
         createMap(layoutJSON);
+        // addBg()
       },
     );
   };
@@ -260,6 +264,7 @@
     // 删除键
     if (e.keyCode === 46 || e.code === 'Delete') {
       deleteShop();
+      configDrawer.value.closeDialog();
     }
   };
 
@@ -267,7 +272,6 @@
     const routerParams = router.currentRoute.value.query;
     if (routerParams.companyId) {
       selectedCompany.value = Number(routerParams.companyId);
-      console.log(selectedCompany.value);
     }
 
     window.addEventListener('keydown', handleKeyDown);
@@ -279,12 +283,15 @@
 
   const filterShopList = computed(() => {
     const k = searchKey.value.trim();
-    console.log('shopList.value', shopList.value);
     if (!k) return shopList.value;
     return shopList.value?.filter((x) => x.name?.includes(k));
   });
 
   const handleAddShop = (shop: WorkShopInfoItem) => {
+    //如果已经存在车间,则禁止加入
+    const existingCamera = addedShops.value.find((item) => item.id === shop.id);
+    if (existingCamera) return;
+    // activeShopId.value = shop.id;
     if (!hasBg.value) {
       ElMessage.warning({
         message: '请先添加背景图片',
@@ -315,14 +322,11 @@
     };
     if (!layoutId.value) {
       uploadCompanyLayout(param).then((res) => {
-        console.log('uploadCompanyLayout', res);
         layoutId.value = res;
         ElMessage.success('保存成功');
       });
     } else {
-      updateCompanyLayout({ ...param, id: layoutId.value }).then((res) => {
-        console.log('updateCompanyLayout', res);
-        layoutId.value = res;
+      updateCompanyLayout({ ...param, id: layoutId.value }).then((_res) => {
         ElMessage.success('更新成功');
       });
     }

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

@@ -0,0 +1,318 @@
+<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>

+ 37 - 12
src/views/page-config/component/ConfigDrawer.vue

@@ -28,8 +28,8 @@
             list-type="picture-card"
             :action="
               editShop.thumbnail
-                ? '/api/homepageConfig/updateWorkshopPicture'
-                : '/api/homepageConfig/uploadWorkshopPicture'
+                ? '/skyeye-admin-api/homepageConfig/updateWorkshopPicture'
+                : '/skyeye-admin-api/homepageConfig/uploadWorkshopPicture'
             "
             :show-file-list="false"
             :with-credentials="true"
@@ -37,7 +37,7 @@
             :on-success="handleAvatarSuccess"
             :data="
               editShop.thumbnail
-                ? { workshopId: editShop.id, deleteFileName: editShop.thumbnail }
+                ? { workshopId: editShop.id, deleteFileName: thumbnailChange }
                 : { workshopId: editShop.id }
             "
           >
@@ -103,9 +103,24 @@
             <!-- //这里要变选值 -->
             <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="" />
+              <img
+                src="~@/assets/icons/layout-left.png"
+                alt=""
+                @click="posAdj(LabelPositionEnum.LEFT)"
+                style="margin-right: 19px; cursor: pointer"
+              />
+              <img
+                src="~@/assets/icons/layout-right.png"
+                alt=""
+                @click="posAdj(LabelPositionEnum.RIGHT)"
+                style="margin-right: 17px; cursor: pointer"
+              />
+              <img
+                src="~@/assets/icons/layout-top.png"
+                alt=""
+                style="cursor: pointer"
+                @click="posAdj(LabelPositionEnum.TOP)"
+              />
             </div>
           </div>
         </div>
@@ -119,7 +134,7 @@
   import { Plus, RefreshRight } from '@element-plus/icons-vue';
   import { ElMessage } from 'element-plus';
   import { colorRGB2Hex } from '@/utils';
-  import useMapEditor, { MapWorkShopInfoItem } from '../stores/useMapEditor';
+  import useMapEditor, { LabelPositionEnum, MapWorkShopInfoItem } from '../stores/useMapEditor';
   import { storeToRefs } from 'pinia';
   import { cloneDeep } from 'lodash-es';
   import { useGlobSetting } from '@/hooks/setting';
@@ -129,11 +144,15 @@
   const { addedShops, showShops, activeShopId } = storeToRefs(mapEditor);
 
   const globSetting = useGlobSetting();
+  const thumbnailChange = ref('');
 
-  const editShop = computed(
-    () =>
-      showShops.value.find((item) => item.id === activeShopId.value) || ({} as MapWorkShopInfoItem),
-  );
+  const editShop = computed(() => {
+    const val =
+      showShops.value.find((item) => {
+        return item.id === Number(activeShopId.value);
+      }) || ({} as MapWorkShopInfoItem);
+    return val;
+  });
 
   const emit = defineEmits(['onClose', 'saveConfig']);
 
@@ -149,6 +168,7 @@
   };
 
   const handleAvatarSuccess = (e) => {
+    thumbnailChange.value = e.data;
     editShop.value.thumbnail = urlJoin(globSetting.imgUrl!, e.data);
   };
 
@@ -162,13 +182,18 @@
     emit('onClose', true);
   };
 
+  const posAdj = (pos: LabelPositionEnum) => {
+    editShop.value.posType = pos;
+  };
+
   const fontSizeList = Array.from({ length: 11 }, (_, index) => index + 10);
 
   const saveWorkshopConfig = () => {
     addedShops.value = cloneDeep(showShops.value);
+    closeDialog();
   };
 
-  defineExpose({ openDialog });
+  defineExpose({ openDialog, closeDialog });
 </script>
 
 <style lang="scss" scoped>

+ 170 - 40
src/views/page-config/component/mapContainer/LabelItem.vue

@@ -2,7 +2,7 @@
   <v-image ref="pointRef" :config="getPointCurvConfig()" />
   <v-image ref="rectRef" :config="getRectCurConfig()" />
   <v-text :config="getTextConfig()" />
-  <v-image :config="shineConfig" />
+  <v-image :config="shineConfig()" />
 </template>
 
 <script setup lang="ts">
@@ -11,12 +11,11 @@
   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';
+  import { MapWorkShopInfoItem, LabelPositionEnum } from '../../stores/useMapEditor';
+  // import { LabelPositionEnum, 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());
@@ -37,69 +36,200 @@
 
   const nodeUpdateFilter = (node: Konva.Node) => {
     node.cache();
-    const rgba = getRGBANum(shopData.value.bgColor);
+    const rgba = getRGBANum(props.shop.bgColor);
     node.red(rgba[0]);
     node.green(rgba[1]);
     node.blue(rgba[2]);
     node.alpha(rgba[3]);
   };
 
+  // const getPointCurvConfig = () => {
+  //   return {
+  //     x: 65,
+  //     y: 35,
+  //     width: 32,
+  //     height: 39,
+  //     image: curvImage.value,
+  //   };
+  // };
+
   const getPointCurvConfig = () => {
-    return {
-      x: 0,
-      y: 0,
-      width: 32,
-      height: 39,
-      // fill: shopData.value.bgColor,
-      image: curvImage.value,
-    };
+    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 = () => {
-    return {
-      x: 53,
-      y: 0,
-      width: 160,
-      height: 38,
-      // fill: shopData.value.bgColor,
-      image: rectImage.value,
-    };
+    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 = () => {
-    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',
-    };
+    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 = computed(() => {
+  // 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,
-      // fill: shopData.value.bgColor,
       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(
-    shopData.value,
+    () => props.shop,
     () => {
-      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());
       });
     },

+ 25 - 9
src/views/page-config/component/mapContainer/MapContainer.vue

@@ -13,6 +13,7 @@
           :key="item.id"
           :config="getGroupConfig(item)"
           @transformend="handleTransformEnd"
+          @click="handleClick"
         >
           <LabelItem :shop="item" />
         </v-group>
@@ -23,20 +24,24 @@
 </template>
 
 <script setup lang="ts">
-  import { computed, ref } from 'vue';
+  import { computed, ref, watch, nextTick } from 'vue';
   import LabelItem from './LabelItem.vue';
   import { storeToRefs } from 'pinia';
   import useMapEditor, { MapWorkShopInfoItem } from '../../stores/useMapEditor';
   import Konva from 'konva';
+  // import { nextTick } from 'process';
 
   const mapEditor = useMapEditor();
-  const { mapWidth, mapHeight, showShops, bgImage } = storeToRefs(mapEditor);
+  const { showShops, bgImage, activeShopId } = storeToRefs(mapEditor);
+
+  const emit = defineEmits(['onOpen']);
 
   const stageRef = ref<Konva.Stage>();
   const layerRef = ref<Konva.Layer>();
   const transformerRef = ref<Konva.Transformer>();
 
-  let selectedShape = -1;
+  // let selectedShape = -1;
+  const selectedShape = ref<number>(-1);
 
   const stageSize = computed(() => {
     return {
@@ -74,16 +79,16 @@
 
   const handleStageMouseDown = (e) => {
     if (e.target.attrs.name === 'bg') {
-      selectedShape = -1;
+      selectedShape.value = -1;
       updateTransformer();
     }
 
     if (e.target.parent.attrs.name === 'group') {
-      if (e.target.parent.id() === selectedShape) {
+      if (e.target.parent.id() === selectedShape.value) {
         return;
       }
-      selectedShape = e.target.parent.id();
-
+      activeShopId.value = e.target.parent.id();
+      selectedShape.value = e.target.parent.id();
       updateTransformer();
     }
   };
@@ -94,14 +99,25 @@
     const transformerNode = transformerRef.value!.getNode();
     const layer = layerRef.value!.getNode().getLayer();
 
-    if (selectedShape >= 0) {
-      const selectedNode = layer.findOne('#' + selectedShape);
+    if (selectedShape.value >= 0) {
+      const selectedNode = layer.findOne('#' + selectedShape.value);
       (transformerNode as Konva.Transformer).nodes([selectedNode!]);
     } else {
       (transformerNode as Konva.Transformer).nodes([]);
     }
   };
 
+  const handleClick = () => {
+    emit('onOpen');
+  };
+
+  watch(activeShopId, () => {
+    nextTick(() => {
+      selectedShape.value = activeShopId.value!;
+      updateTransformer();
+    });
+  });
+
   const getLayout = () => {
     const json = stageRef.value?.getStage().toJSON();
 

+ 32 - 15
src/views/page-config/stores/useMapEditor.ts

@@ -5,7 +5,7 @@ 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';
+// import emptyImg from '@/assets/images/table/table-empty.png';
 
 export enum LabelPositionEnum {
   LEFT = 'left',
@@ -39,9 +39,12 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
   /** konva elements refs */
   const bgImage = ref<HTMLImageElement>(new Image());
 
+  const clearBg = () => {
+    bgImage.value.src = '';
+  };
+
   const addBg = () => {
     const imgUrl = urlJoin(globSetting.imgUrl!, bgImg.value);
-    console.log(imgUrl);
 
     const tempImg = new Image();
     tempImg.onload = () => {
@@ -49,6 +52,7 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
       mapHeight.value = tempImg.height;
       bgImage.value = tempImg;
     };
+    // console.log('imgUrl.value', imgUrl.value);
     tempImg.src = imgUrl;
   };
 
@@ -61,38 +65,50 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
 
   const calcLayout = (json: string) => {
     const mapJson = safeParse(json);
-    const mapData = mapJson.children[0].children;
+    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;
+      return item;
+    });
+    console.log('mapData', shopListAdded);
     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;
-      }),
+      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;
     addedShops.value = cloneDeep(layout.shopList);
     showShops.value = cloneDeep(layout.shopList);
+    addBg();
   };
 
   const deleteShop = () => {
-    addedShops.value = addedShops.value.filter((item) => item.id !== activeShopId.value);
-    showShops.value = showShops.value.filter((item) => item.id !== activeShopId.value);
+    addedShops.value = addedShops.value.filter((item) => item.id !== Number(activeShopId.value));
+    showShops.value = showShops.value.filter((item) => item.id !== Number(activeShopId.value));
     activeShopId.value = undefined;
   };
 
@@ -103,6 +119,7 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
     addedShops.value = [];
     showShops.value = [];
     activeShopId.value = undefined;
+    clearBg();
   };
 
   return {