فهرست منبع

Merge branch 'all-v4-fjc' into 'all-v4'

feat: 布局管理-场景布局 更新画布和编辑区逻辑

See merge request skyeye/skyeye_frontend/skyeye-admin!204
Fei Liu 1 سال پیش
والد
کامیت
768a41ecc4

+ 22 - 5
src/api/scene/scene.ts

@@ -71,7 +71,7 @@ export const uploadCompanyLayout = (
 /** 更新公司主页配置 */
 export const updateCompanyLayoutApi = (data: SceneTypes.UpdateCompanyLayoutParam) => {
   return http.request({
-    url: '/homepageConfig/updateCompanyLayout',
+    url: '/admin/homepageConfig/updateCompanyLayout',
     method: 'put',
     data,
   });
@@ -85,11 +85,11 @@ export const updateCompanyLayout = (
 };
 
 /** 查询公司主页配置 */
-export const getCompanyLayoutApi = (params: { companyId: number; labelId: number }) => {
+// export const getCompanyLayoutApi = (params: { companyId: number }) => {
+export const getCompanyLayoutApi = () => {
   return http.request({
-    url: '/homepageConfig/getCompanyLayoutByCompanyLabel',
+    url: '/admin/homepageConfig/getPcCompanyLayout',
     method: 'get',
-    params,
   });
 };
 
@@ -105,7 +105,7 @@ export const getCompanyLayoutApi = (params: { companyId: number; labelId: number
 /** 查询所有公司主页配置 */
 export const getCompanyLayoutList = (params: { name: string }) => {
   return http.request({
-    url: '/homepageConfig/getCompanyLayoutList',
+    url: '/admin/homepageConfig/getCompanyLayoutList',
     method: 'get',
     params,
   });
@@ -119,6 +119,23 @@ export const delCompanyLayout = (params: number) => {
   });
 };
 
+/** 查询公司列表 */
+export const queryCompanyListApi = () => {
+  return http.request({
+    url: '/admin/workshop/queryCompanyList',
+    method: 'get',
+  });
+};
+
+/** 查询车间列表 */
+export const getWorkshopListApi = (params: { companyId: number }) => {
+  return http.request({
+    url: '/admin/workshop/queryWorkshopListByCompanyId',
+    method: 'get',
+    params,
+  });
+};
+
 /**
  * @description: 添加公司
  * @modifications

+ 90 - 0
src/types/page-config/type.ts

@@ -0,0 +1,90 @@
+export interface companyType {
+  code: string;
+  createdAt: string;
+  createdBy: number;
+  id: number;
+  isDisabled: 0 | 1;
+  latitude: number;
+  longitude: number;
+  name: string;
+  orderNum: number;
+  parentId: number;
+  regionCode: string;
+  remark: string;
+  tenantId: number;
+  thumbnail: string;
+  updatedAt: string;
+  updatedBy: number;
+}
+
+export interface companyLayoutType {
+  id: number;
+  viewName: string;
+  viewType: number;
+  viewCode: string;
+  targetId: number;
+  layout: string;
+  version: string;
+  isDisabled: 0 | 1;
+  createdAt: string;
+  updatedAt: string;
+  tenantId: number;
+}
+
+export type LayoutType = {
+  bgInfo: {
+    height: number;
+    width: number;
+    img: string;
+  };
+  shopList: ShopType[];
+};
+
+export interface ShopType {
+  id: number;
+  companyId: number;
+  sceneLabelId: number;
+  name: string;
+  code: string;
+  remark: string;
+  status: number;
+  createdAt: string;
+  updatedAt: string;
+  isDeleted: 0 | 1;
+  serial: number;
+  tenantId: number;
+  labelName: string;
+  workshopModule: {
+    id: number;
+    name: string;
+    code: string;
+    remark: string;
+    status: number;
+    createdAt: string;
+    updatedAt: string;
+    isDeleted: 0 | 1;
+    tenantId: number;
+  };
+  children?: {
+    id: number;
+    workshopId: number;
+    name: string;
+    code: string;
+    remark: string;
+    principal: string;
+    status: number;
+    createdAt: string;
+    updatedAt: string;
+    isDeleted: 0 | 1;
+    serial: number;
+    tenantId: number;
+  }[];
+  x: number;
+  y: number;
+  scaleX: number;
+  scaleY: number;
+  bgColor: string;
+  fontSize: number;
+  fontColor: string;
+  posType: string;
+}

+ 130 - 81
src/views/page-config/ConfigEdit.vue

@@ -4,7 +4,7 @@
       <div class="head-opt flex-1 flex justify-between items-center" style="margin-left: 0px">
         <div>
           <!-- <span>场景:</span> -->
-          <el-select
+          <!-- <el-select
             v-model="selectedCompany"
             class="m-2"
             placeholder="请选择相关公司"
@@ -17,9 +17,9 @@
               :label="item.name"
               :value="item.id"
             />
-          </el-select>
+          </el-select> -->
         </div>
-        <div v-if="selectedCompany" style="display: flex">
+        <!-- <div v-if="selectedCompany" style="display: flex">
           <div style="display: flex">
             <div class="label-workshop" style="margin-left: 0px">选择标签:</div>
             <div>
@@ -39,14 +39,8 @@
               </el-radio-group></div
             >
           </div>
-          <!-- <div v-if="false" style="display: flex">
-            <div class="label-workshop" style="margin-left: 10px">是否开启移动端视角</div>
-            <div>
-              <el-switch v-model="isMobileView" style="margin-left: 10px" />
-            </div>
-          </div> -->
-        </div>
-        <div class="flex">
+        </div> -->
+        <div class="top-bar">
           <!-- <el-button @click="toJson">tojson</el-button> -->
           <el-upload
             class="avatar-uploader flex justify-center items-center"
@@ -56,18 +50,16 @@
             :before-upload="handleBeforeUpload"
             :with-credentials="true"
             name="file"
-            :data="{ companyId: selectedCompany, labelId: label, deleteFileName: bgImg }"
+            :data="{ companyId, deleteFileName: bgImg }"
             :headers="getHeaders()"
           >
             <el-button :icon="Refresh" :disabled="!hasBg"> 替换照片 </el-button>
           </el-upload>
 
-          <el-button
-            @click="handleSave"
-            style="margin-left: 40px"
-            type="primary"
-            :disabled="!selectedCompany && !label"
-            >保存为布局
+          <el-button :icon="Refresh" @click="clearLayout"> 重置 </el-button>
+
+          <el-button @click="handleSave" type="primary" :disabled="!companyId && !label">
+            保存
           </el-button>
         </div>
       </div>
@@ -84,10 +76,10 @@
             :suffix-icon="Search"
           />
         </div>
-        <span v-if="filterShopList.length == 0" class="ml-1" style="color: #3f3f3f">
+        <!-- <span v-if="filterShopList.length == 0" class="ml-1" style="color: #3f3f3f">
           提示:请先选择相应公司和图片
-        </span>
-        <el-scrollbar v-else style="position: relative; height: calc(100% - 90px)">
+        </span> -->
+        <el-scrollbar style="position: relative; height: calc(100% - 90px)">
           <div
             v-for="item in filterShopList"
             :key="item.code"
@@ -103,11 +95,12 @@
         </el-scrollbar>
       </div>
       <div ref="drawContainer" id="drawContainer" class="draw-container">
-        <div id="shopEditContainer" v-moveable:1>
+        <div id="shopEditContainer" v-moveable:1 class="shop-edit-container">
           <MapContainer
             ref="mapContainerRef"
             :is-mobile-view="isMobileView"
             :module-code="labelMouduleCode"
+            :stageSize="mapContainerStageSize"
             @on-open="openConfig"
           />
         </div>
@@ -120,17 +113,20 @@
           :on-success="handleAvatarSuccess"
           :with-credentials="true"
           name="file"
-          :data="{ companyId: selectedCompany, labelId: label }"
+          :data="{ companyId }"
           :headers="getHeaders()"
         >
           <img src="~@/assets/images/img-upload.png" />
         </el-upload>
       </div>
+      <div class="shop-tag-edit-area" v-if="hasBg">
+        <ShopTagEditArea @transformer-change="transformChange" />
+      </div>
     </div>
-    <el-tooltip
+    <!-- <el-tooltip
       class="box-item position-tooltip"
       effect="dark"
-      content="显示侧边栏"
+      content="显示侧边栏" 
       :offset="12"
       placement="left"
     >
@@ -145,15 +141,15 @@
         <el-icon class="left-icon" size="16px"><ArrowLeftBold /></el-icon>
         <el-icon style="margin-top: 7px" size="16px"><ArrowLeftBold /></el-icon>
       </div>
-    </el-tooltip>
+    </el-tooltip> -->
 
-    <ConfigDialog
+    <!-- <ConfigDialog
       v-if="!isMobileView"
       ref="configDrawer"
       @on-close="onClose"
       @transformer-change="transformChange"
       class="drawer-position"
-    />
+    /> -->
 
     <ConfigFinish
       :visible="visibleResult"
@@ -168,9 +164,9 @@
   import ConfigDialog from './component/ConfigDrawer.vue';
   import ConfigFinish from './component/ConfigFinish.vue';
   import { storeToRefs } from 'pinia';
-  import { ElMessage, ElInput, ElSwitch } from 'element-plus';
-  import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
-  import { WorkShopInfoItem } from '@/types/scene/type.ts';
+  import { ElMessage, ElInput, ElSwitch, ElMessageBox } from 'element-plus';
+  import { onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
+  import { WorkShopInfoItem, getWorkshopListApi } from '@/api/scene/scene';
   import { computed } from 'vue';
   import { Search, Refresh, ArrowLeftBold } from '@element-plus/icons-vue';
   import usePageConfig from './usePageConfig';
@@ -182,6 +178,8 @@
   import urlJoin from 'url-join';
   import { useGlobSetting } from '@/hooks/setting';
   import { getHeaders } from '@/utils/http/axios';
+  import { companyLayoutType, LayoutType, ShopType } from '@/types/page-config/type';
+  import ShopTagEditArea from './component/ShopTagEditArea.vue';
 
   const mapEditor = useMapEditor();
   const { bgImg, addedShops, activeShopId, showShops } = storeToRefs(mapEditor);
@@ -190,7 +188,7 @@
   const router = useRouter();
 
   const pageConfig = usePageConfig();
-  const { selectedCompany, scenesInfos, label, labelList, shopList, layoutId } = pageConfig;
+  const { scenesInfos, label, labelList, layoutId } = pageConfig;
   const { urlPrefix } = useGlobSetting();
   const drawContainer = ref<HTMLDivElement>();
   const mapContainerRef = ref();
@@ -202,13 +200,20 @@
   // 是否开启移动端视图
   const isMobileView = ref(false);
 
+  const companyId = ref<number>();
+
+  const shopList = ref<ShopType[]>([]); // 车间列表
+
+  // mapContainer宽高
+  const mapContainerStageSize = reactive({ height: 0, width: 777 });
+
   const handleBeforeUpload = (rawFile) => {
-    if (!selectedCompany.value || !label.value) {
-      ElMessage.error({
-        message: '请先选择公司和标签',
-      });
-      return false;
-    }
+    // if (!selectedCompany.value || !label.value) {
+    //   ElMessage.error({
+    //     message: '请先选择公司和标签',
+    //   });
+    //   return false;
+    // }
     if (
       rawFile.type !== 'image/jpg' &&
       rawFile.type !== 'image/jpeg' &&
@@ -236,7 +241,8 @@
   };
 
   const actionUrl = computed(() => {
-    return urlJoin(urlPrefix, '/homepageConfig/updateCompanyPicture');
+    // return urlJoin(urlPrefix, '/homepageConfig/updateCompanyPicture');
+    return urlJoin(urlPrefix, '/admin/homepageConfig/uploadCompanyPicture');
   });
 
   watch(
@@ -273,6 +279,8 @@
   /** ------------- */
 
   const handleAvatarSuccess = (e) => {
+    console.log('handleAvatarSuccess', e);
+
     bgImg.value = e.data;
     hasBg.value = true;
     addBg();
@@ -281,7 +289,7 @@
   const labelMouduleCode = computed(() => {
     return (
       scenesInfos.value
-        .find((item) => item.id === selectedCompany.value)
+        .find((item) => item.id === companyId.value)
         ?.labelModuleList.find((item) => item.sceneLabel.id === label.value)?.sceneModule.code ||
       'default'
     );
@@ -294,28 +302,42 @@
   };
 
   const getShopContent = () => {
-    getCompanyLayoutApi({ companyId: selectedCompany.value || 2, labelId: label.value || 1 }).then(
-      (res) => {
-        if (!res) {
-          layoutId.value = undefined;
-          return;
-        }
-        layoutId.value = res.id;
-        const layoutJSON = res.layout ? safeParse(res.layout) : null;
-
-        if (!layoutJSON) {
-          return;
-        }
-        hasBg.value = true;
-        createMap(layoutJSON);
-      },
-    );
+    // getCompanyLayoutApi({ companyId: selectedCompany.value || 2 }).then((res) => {
+    getWorkshopListApi({ companyId: companyId.value! }).then((res) => {
+      shopList.value = res;
+    });
+
+    getCompanyLayoutApi().then((res) => {
+      console.log('res', res);
+      console.log('layout', JSON.parse(res.layout));
+
+      if (!res) {
+        layoutId.value = undefined;
+        return;
+      }
+      layoutId.value = res.id;
+      const layoutJSON = res.layout ? safeParse(res.layout) : null;
+
+      if (!layoutJSON) {
+        return;
+      }
+      hasBg.value = true;
+      createMap(layoutJSON);
+    });
   };
 
-  const changeCompany = () => {
-    label.value = undefined;
-    resetMap();
-    hasBg.value = false;
+  // const changeCompany = () => {
+  const clearLayout = () => {
+    // label.value = undefined;
+
+    ElMessageBox.confirm('是否重置当前设置?', '提示', {
+      confirmButtonText: '确认',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }).then(() => {
+      resetMap();
+      hasBg.value = false;
+    });
   };
 
   const handleKeyDown = (e) => {
@@ -326,29 +348,13 @@
     }
   };
 
-  onMounted(() => {
-    const routerParams = router.currentRoute.value.query;
-    if (routerParams.companyId) {
-      selectedCompany.value = Number(routerParams.companyId);
-    }
-    if (routerParams.labelId) {
-      label.value = Number(routerParams.labelId);
-    }
-
-    window.addEventListener('keydown', handleKeyDown);
-
-    if (selectedCompany.value && label.value) {
-      getShopContent();
-    }
-  });
-
   const filterShopList = computed(() => {
     const k = searchKey.value.trim();
     if (!k) return shopList.value;
     return shopList.value?.filter((x) => x.name?.includes(k));
   });
 
-  const handleAddShop = (shop: WorkShopInfoItem) => {
+  const handleAddShop = (shop: ShopType) => {
     //如果已经存在车间,则禁止加入
     const existingCamera = addedShops.value.find((item) => item.id === shop.id);
     if (existingCamera) return;
@@ -371,7 +377,7 @@
       posType: LabelPositionEnum.LEFT,
     };
     addShop(shopNode);
-    dialogReopen();
+    // dialogReopen();
   };
 
   const handleSave = () => {
@@ -379,7 +385,7 @@
     const layout = calcLayout(json);
     const param = {
       layout,
-      targetId: selectedCompany.value || 2,
+      targetId: companyId.value || 2,
       labelId: label.value || 1,
     };
     if (!layoutId.value) {
@@ -398,6 +404,28 @@
     window.removeEventListener('keydown', handleKeyDown);
     resetMap();
   });
+
+  onMounted(() => {
+    const routerParams = router.currentRoute.value.query;
+
+    if (routerParams.companyId) {
+      companyId.value = Number(routerParams.companyId);
+    }
+    // if (routerParams.labelId) {
+    //   label.value = Number(routerParams.labelId);
+    // }
+
+    window.addEventListener('keydown', handleKeyDown);
+
+    if (companyId.value) {
+      getShopContent();
+    }
+
+    console.log('clientHeight', document.getElementById('shopEditContainer')?.clientHeight);
+    console.log('clientWidth', document.getElementById('shopEditContainer')?.clientWidth);
+    mapContainerStageSize.height = document.getElementById('shopEditContainer')?.clientHeight!;
+    mapContainerStageSize.width = document.getElementById('shopEditContainer')?.clientWidth!;
+  });
 </script>
 
 <style scoped lang="scss">
@@ -490,10 +518,17 @@
   }
 
   .draw-container {
+    height: calc(100vh - 160px);
     position: relative;
-    width: calc(100% - 300px);
-    margin: 20px;
+    width: calc(100% - 600px);
+    margin: 10px;
     overflow: hidden;
+    border: 1px solid #1890ff;
+  }
+
+  .shop-edit-container {
+    height: 100%;
+    border: 1px solid #ff7118;
   }
 
   .drawer-position {
@@ -543,6 +578,20 @@
     z-index: 9999;
   }
 
+  .top-bar {
+    width: 350px;
+    display: flex;
+    // justify-content: space-around;
+    .el-button {
+      margin-left: 20px;
+    }
+  }
+
+  .shop-tag-edit-area {
+    width: 300px;
+    background-color: #ffffff;
+  }
+
   :deep(.search-put .el-input__wrapper) {
     background-color: #f0f2f5;
   }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 112 - 47
src/views/page-config/component/PageMain.vue


+ 264 - 0
src/views/page-config/component/ShopTagEditArea.vue

@@ -0,0 +1,264 @@
+<template>
+  <div class="shop-tag-edit-area">
+    <div>
+      <!-- //这里要变选值 -->
+      <div class="content-title"
+        ><div class="uploader-title"> <div class="block"></div>标签设置</div>
+      </div>
+      <div class="label-setting-item">
+        标签样式
+        <div class="layout-set">
+          <img
+            src="~@/assets/icons/layout-left.png"
+            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>
+      <div class="label-setting-item">
+        标签位置
+        <div class="label-setting-content">
+          <el-input
+            v-model.number="editShop.x"
+            type="number"
+            class="no_number"
+            style="max-width: 100px"
+          >
+            <template #prepend>X</template>
+          </el-input>
+          <el-input
+            v-model.number="editShop.y"
+            type="number"
+            class="no_number"
+            style="max-width: 100px"
+          >
+            <template #prepend>Y</template>
+          </el-input>
+        </div>
+      </div>
+      <div class="label-setting-item">
+        标签大小
+        <div class="label-setting-content">
+          <el-input
+            v-model.number="editShop.scaleX"
+            type="number"
+            class="no_number"
+            style="max-width: 100px"
+          >
+            <template #prepend>W</template>
+          </el-input>
+          <el-input
+            v-model.number="editShop.scaleY"
+            type="number"
+            class="no_number"
+            style="max-width: 100px"
+          >
+            <template #prepend>H</template>
+          </el-input>
+        </div>
+      </div>
+    </div>
+    <div>
+      <div class="content-title">
+        <div class="uploader-title">
+          <div class="block"></div>
+          填充
+        </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 class="block"></div>文字</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="save-wrapper">
+      <!-- <el-button type="primary" @click="saveWorkshopConfig">保存</el-button> -->
+      <el-button type="primary" @click="deleteShop">删除</el-button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { computed, ref } from 'vue';
+  import { storeToRefs } from 'pinia';
+  import { cloneDeep } from 'lodash-es';
+  import { colorRGB2Hex } from '@/utils';
+  import useMapEditor, { LabelPositionEnum, MapWorkShopInfoItem } from '../stores/useMapEditor';
+
+  const emit = defineEmits(['transformerChange']);
+
+  const mapEditor = useMapEditor();
+  const { addedShops, showShops, activeShopId } = storeToRefs(mapEditor);
+  const fontSizeList = Array.from({ length: 11 }, (_, index) => index + 10);
+  const showColor = computed(() => colorRGB2Hex(editShop.value!.bgColor));
+
+  const editShop = computed(() => {
+    const val =
+      showShops.value.find((item) => {
+        return item.id === Number(activeShopId.value);
+      }) || ({} as MapWorkShopInfoItem);
+    return val;
+  });
+
+  const posAdj = (pos: LabelPositionEnum) => {
+    editShop.value.posType = pos;
+    emit('transformerChange');
+  };
+
+  const saveWorkshopConfig = () => {
+    addedShops.value = cloneDeep(showShops.value);
+  };
+
+  const deleteShop = () => {
+    const tempId = editShop.value.id;
+    showShops.value = showShops.value.filter((x) => x.id != tempId);
+    addedShops.value = addedShops.value.filter((x) => x.id != tempId);
+    activeShopId.value = undefined;
+  };
+</script>
+
+<style scoped>
+  .shop-tag-edit-area {
+    padding: 20px;
+  }
+
+  .block {
+    height: 100%;
+    width: 4px;
+    margin-right: 6px;
+    background: #1777ff;
+  }
+
+  .uploader-title {
+    font-size: 12px;
+    margin-bottom: 8px;
+    display: flex;
+  }
+
+  .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;
+  }
+
+  .label-setting-item {
+    margin-left: 34px;
+    margin-bottom: 18px;
+    font-weight: 400;
+    font-size: 10px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+
+  .label-setting-content {
+    display: flex;
+    margin-top: 12px;
+  }
+
+  .layout-set {
+    width: 156px;
+    height: 24px;
+    background: #f5f5f5;
+    border-radius: 2px;
+    display: flex;
+
+    margin-top: 12px;
+  }
+
+  .active {
+    background-color: #cbcdce;
+  }
+
+  .save-wrapper {
+    margin-top: 40px;
+    text-align: center;
+  }
+
+  ::v-deep .no_number input::-webkit-inner-spin-button,
+  ::v-deep .no_number input::-webkit-outer-spin-button {
+    -webkit-appearance: none !important;
+  }
+  ::v-deep .no_number input[type='number'] {
+    appearance: textfield;
+  }
+</style>

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

@@ -3,6 +3,7 @@
     <v-stage
       ref="stageRef"
       :config="stageSize"
+      draggable="true"
       @mousedown="handleStageMouseDown"
       @touchstart="handleStageMouseDown"
     >
@@ -13,6 +14,8 @@
           :key="item.id"
           :config="getGroupConfig(item)"
           @dblclick="handleClick"
+          @dragend="handleGroupDragend"
+          @transform="handleTransform"
         >
           <LabelItemMobile
             v-if="isMobileView"
@@ -29,7 +32,7 @@
 </template>
 
 <script setup lang="ts">
-  import { computed, ref, watch, nextTick } from 'vue';
+  import { computed, ref, watch, nextTick, onMounted } from 'vue';
   import LabelItem from './LabelItem.vue';
   import LabelItemMobile from './LabelItemMobile.vue';
   import { storeToRefs } from 'pinia';
@@ -42,6 +45,7 @@
   const props = defineProps<{
     isMobileView: boolean;
     moduleCode: string;
+    stageSize: { height: number; width: number };
   }>();
 
   const emit = defineEmits(['onOpen']);
@@ -52,6 +56,8 @@
 
   const stageSize = computed(() => {
     return {
+      // width: props.stageSize.width,
+      // height: props.stageSize.height,
       width: 1920,
       height: 1080,
     };
@@ -112,6 +118,24 @@
     }
   };
 
+  // 拖拽回调
+  const handleGroupDragend = (e) => {
+    const activeShop = showShops.value.find((item) => {
+      return item.id === Number(activeShopId.value);
+    });
+    activeShop!.x = e.target.attrs.x;
+    activeShop!.y = e.target.attrs.y;
+  };
+
+  // 调整大小回调
+  const handleTransform = (e) => {
+    const activeShop = showShops.value.find((item) => {
+      return item.id === Number(activeShopId.value);
+    });
+    activeShop!.scaleX = e.target.attrs.scaleX;
+    activeShop!.scaleY = e.target.attrs.scaleY;
+  };
+
   const updateTransformer = () => {
     const transformerNode = transformerRef.value!.getNode();
     const layer = layerRef.value!.getNode().getLayer();

+ 4 - 4
src/views/page-config/component/mapContainer/MapContainerSmall.vue

@@ -28,8 +28,8 @@
   const layerRef = ref<Konva.Layer>();
 
   const stageSize = ref({
-    width: 182,
-    height: 114,
+    width: 282,
+    height: 164,
   });
 
   const bgConfig = ref({
@@ -69,8 +69,8 @@
     const stage = stageRef.value!.getStage();
     if (!stage) return;
 
-    const targetWidth = 182;
-    const targetHeight = 114;
+    const targetWidth = 282;
+    const targetHeight = 164;
     const fixWidth = 1920;
     const fixHeight = 1080;
     //得到缩放比

+ 6 - 1
src/views/page-config/stores/useMapEditor.ts

@@ -6,6 +6,7 @@ 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 { ShopType } from '@/types/page-config/type';
 
 export enum LabelPositionEnum {
   LEFT = 'left',
@@ -26,7 +27,8 @@ export type EditStyle = {
   posType: LabelPositionEnum;
 };
 
-export type MapWorkShopInfoItem = WorkShopInfoItem & EditStyle;
+// export type MapWorkShopInfoItem = WorkShopInfoItem & EditStyle;
+export type MapWorkShopInfoItem = ShopType;
 
 export const useMapEditor = defineStore('home-map-ediotr', () => {
   const globSetting = useGlobSetting();
@@ -58,6 +60,9 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
         bgImage.value = tempImg;
       };
       tempImg.src = imgUrl;
+
+      console.log('tempImg.src', tempImg.src);
+
       resolve(null);
     });
   };