chauncey пре 1 година
родитељ
комит
1b16026686

+ 6 - 7
src/api/camera/camera-overview.ts

@@ -102,9 +102,9 @@ export const deleteCameraItems = (data: number[]) => {
 };
 
 /**
- * v4:根据相机code查询相机联网状态
- * @param data 
- * @returns 
+ * 通过codes获取相机状态。后期会废弃。建议使用 ids 获取
+ * @param data 
+ * @returns
  */
 export const getCameraStateByCodes = (data: { cameraCodeList: string[] }) => {
   return http.request<CameraStatus[]>({
@@ -114,13 +114,12 @@ export const getCameraStateByCodes = (data: { cameraCodeList: string[] }) => {
   });
 };
 
-
 /**
  * v4: 根据相机 id 查询相机联网状态
- * @param data 
- * @returns 
+ * @param data
+ * @returns
  */
-export const getCameraStateByIds = (data: { cameraIdList: number[] }) => {
+export const getCameraStateByIds = (data: { cameraIdList: number[] | string[] }) => {
   return http.request<CameraStatus[]>({
     url: '/admin/cameraConfig/queryCameraStatusListByCameraIds',
     method: 'post',

+ 39 - 8
src/views/cameras/preview/store/useCameraStatus.ts

@@ -1,4 +1,4 @@
-import { getCameraStateByCodes } from '@/api/camera/camera-overview';
+import { getCameraStateByCodes, getCameraStateByIds } from '@/api/camera/camera-overview';
 import { ref } from 'vue';
 
 /** 轮询相机异常的频率,5s */
@@ -7,23 +7,52 @@ const INTERVAL_TIME = 5000;
 export const useCameraStatus = () => {
   const noNetworkingNum = ref<number>(0);
   let interval;
-
-  const getState = (codeList, callback) => {
+  /**
+   * v3 旧获取方式,通过codes 获取。后期会废弃
+   * @description
+   */
+  const getStateByCodes = (codeList, callback) => {
     if (codeList.length === 0) return;
     getCameraStateByCodes({ cameraCodeList: codeList }).then((res) => {
-      const filterData = res.filter((item) => item.status === 1);
+      const filterData = res.filter((item) => item.networkingState === 1);
       noNetworkingNum.value = filterData.length;
       callback(res);
     });
   };
-
+  /**
+   * v4 接口,通过 ids 获取状态
+   * @description
+   */
+  const getStateByIds = (idList, callback) => {
+    if (idList.length === 0) return;
+    getCameraStateByIds({ cameraIdList: idList }).then((res) => {
+      const filterData = res.filter((item) => item.networkingState === 1);
+      noNetworkingNum.value = filterData.length;
+      callback(res);
+    });
+  };
+  /**
+   * @description --deprecated
+   */
   const openInterval = (codeList, callback) => {
     clearInterval(interval);
     setTimeout(() => {
-      getState(codeList, callback);
+      getStateByCodes(codeList, callback);
+    }, 500);
+    interval = setInterval(() => {
+      getStateByCodes(codeList, callback);
+    }, INTERVAL_TIME);
+  };
+  /**
+   * @description --new
+   */
+  const openIntervalNew = (idList, callback) => {
+    clearInterval(interval);
+    setTimeout(() => {
+      getStateByIds(idList, callback);
     }, 500);
     interval = setInterval(() => {
-      getState(codeList, callback);
+      getStateByIds(idList, callback);
     }, INTERVAL_TIME);
   };
 
@@ -34,8 +63,10 @@ export const useCameraStatus = () => {
   return {
     noNetworkingNum,
     openInterval,
+    openIntervalNew,
     closeInterval,
-    getState,
+    getStateByCodes,
+    getStateByIds,
   };
 };
 

+ 459 - 475
src/views/map-config/mini-map/MapBase/KonvaMap.vue

@@ -3,522 +3,506 @@
     <v-stage ref="stageAll" :config="stageConfig" @click="handleStageClick">
       <v-layer ref="layer">
         <v-image :config="bgConfig" v-show="bgImgUrl" />
-        <v-group
-          v-for="camera in cameras"
-          :key="camera.id"
-          :id="camera.id"
-          :config="camera.groupConfig"
-          @click="handleCameraClick(camera)"
-          @mouseover="(e) => handleMouseOver(e)"
-          @mouseleave="handleMouseLeave()"
-          @dragstart="handleDragStart()"
-        >
+        <v-group v-for="camera in cameras" :key="camera.id" :id="camera.id" :config="camera.groupConfig"
+          @click="handleCameraClick(camera)" @mouseover="(e) => handleMouseOver(e)" @mouseleave="handleMouseLeave()"
+          @dragstart="handleDragStart()">
           <v-image :config="camera.config" />
           <v-image v-if="camera.isDefault" ref="defaultIcon" :config="defaultIconConfig" />
         </v-group>
         <v-transformer :config="transformerConfig" ref="transformer" />
       </v-layer>
     </v-stage>
-    <div
-      v-show="defaultShow"
-      class="opt-container"
-      :style="{ position: 'absolute', left: posX + 'px', top: posY + 'px' }"
-    >
-      <div class="opt-item" :class="{ disabled: disabledSet }" @click="setDefaultCamera"
-        >设为默认相机</div
-      >
+    <div v-show="defaultShow" class="opt-container"
+      :style="{ position: 'absolute', left: posX + 'px', top: posY + 'px' }">
+      <div class="opt-item" :class="{ disabled: disabledSet }" @click="setDefaultCamera">设为默认相机</div>
       <div class="opt-item" @click="previewCamera">预览相机</div>
     </div>
 
-    <CameraPreview
-      v-if="isShow"
-      :last-pos-x="posX!"
-      :last-pos-y="posY!"
-      :video-url="videoUrl"
-      @close="closePreview"
-    />
-
-    <DefaultTip
-      v-show="tipShow"
-      :position="pos"
-      :style="{ position: 'absolute', left: posTipX + 'px', top: posTipY + 'px' }"
-    />
+    <CameraPreview v-if="isShow" :last-pos-x="posX!" :last-pos-y="posY!" :video-url="videoUrl" @close="closePreview" />
+
+    <DefaultTip v-show="tipShow" :position="pos"
+      :style="{ position: 'absolute', left: posTipX + 'px', top: posTipY + 'px' }" />
   </div>
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import DefaultTip from '../components/DefaultTip.vue';
-  import cameraImgSrc from '@/assets/camera/cameraImg.png';
-  import favoritesImgSrc from '@/assets/camera/favorites.png';
-  import { TipPositionEnum, camerasGroupType } from '../type';
-  import { cloneDeep } from 'lodash-es';
-  import useMiniMap from '../use-mini-map';
-  import { storeToRefs } from 'pinia';
-  import { updateMinMapViewLayoutApi } from '@/api/scene/scene';
-  import CameraPreview from './CameraPreview.vue';
-  import { ShopMapCamera } from '@/types/scene/type'
-
-  const miniMap = useMiniMap();
-  const { shopCameraList } = storeToRefs(miniMap);
-
-  const emit = defineEmits(['changeDefaultCamera', 'sendCameraId', 'change']);
-  const props = defineProps<{ filterData: ShopMapCamera[] }>();
-  const camImg = new Image();
-
-  const stageConfig = ref({
-    width: 800,
-    height: 600,
-  });
-
-  const bgImg = new Image();
-  const favoritesImg = new Image();
-  favoritesImg.src = favoritesImgSrc;
-
-  //右键点击是否出现
-  const defaultShow = ref<boolean>(false);
-  const posX = ref<number>();
-  const posY = ref<number>();
-  const posTipX = ref<number>();
-  const posTipY = ref<number>();
-  const pos = ref(TipPositionEnum.TOP);
-  //上一次点击的相机
-  const lastClickedGroupId = ref<string | null>(null);
-  const lastClickedVideoUrl = ref<string | null>(null);
-
-  const bgImgUrl = ref<string | null>('');
-  const cameras = ref<camerasGroupType[]>([]);
-  //默认相机id
-  const defaultCameraId = ref('');
-  const tipShow = ref(false);
-  const disabledSet = ref(false);
-  const videoUrl = ref<string>('');
-
-  const cameraIconSize = { width: 52, height: 52 };
-
-  //标签
-  const layer = ref();
-  const transformer = ref();
-  const defaultIcon = ref();
-
-  function addIntegrationState(data: camerasGroupType[], updateData: ShopMapCamera[]) {
-    for (let i = 0; i < data.length; i++) {
-      const camera = data[i];
-      const matchedCamera = updateData.find((item) => item.code === camera.id);
-      if (matchedCamera) {
-        camera.groupConfig.visible = matchedCamera.integrationState === 0 ? true : false;
-      }
+import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import DefaultTip from '../components/DefaultTip.vue';
+import cameraImgSrc from '@/assets/camera/cameraImg.png';
+import favoritesImgSrc from '@/assets/camera/favorites.png';
+import { TipPositionEnum, camerasGroupType } from '../type';
+import { cloneDeep } from 'lodash-es';
+// import useMiniMap from '../use-mini-map';
+// import { storeToRefs } from 'pinia';
+import { updateMinMapViewLayoutApi } from '@/api/scene/scene';
+import CameraPreview from './CameraPreview.vue';
+import { ShopMapCamera } from '@/types/scene/type'
+
+// const miniMap = useMiniMap();
+// const { shopCameraList } = storeToRefs(miniMap);
+
+const emit = defineEmits(['changeDefaultCamera', 'sendCameraId', 'change']);
+const props = defineProps<{ filterData: ShopMapCamera[], cameraList: ShopMapCamera[] }>();
+const camImg = new Image();
+
+const stageConfig = ref({
+  width: 800,
+  height: 600,
+});
+
+const bgImg = new Image();
+const favoritesImg = new Image();
+favoritesImg.src = favoritesImgSrc;
+
+//右键点击是否出现
+const defaultShow = ref<boolean>(false);
+const posX = ref<number>();
+const posY = ref<number>();
+const posTipX = ref<number>();
+const posTipY = ref<number>();
+const pos = ref(TipPositionEnum.TOP);
+//上一次点击的相机
+const lastClickedGroupId = ref<string | null>(null);
+const lastClickedVideoUrl = ref<string | null>(null);
+
+const bgImgUrl = ref<string | null>('');
+const cameras = ref<camerasGroupType[]>([]);
+//默认相机id
+const defaultCameraId = ref('');
+const tipShow = ref(false);
+const disabledSet = ref(false);
+const videoUrl = ref<string>('');
+
+const cameraIconSize = { width: 52, height: 52 };
+
+//标签
+const layer = ref();
+const transformer = ref();
+const defaultIcon = ref();
+
+function addIntegrationState(data: camerasGroupType[], updateData: ShopMapCamera[]) {
+  for (let i = 0; i < data.length; i++) {
+    const camera = data[i];
+    const matchedCamera = updateData.find((item) => item.code === camera.id);
+    if (matchedCamera) {
+      camera.groupConfig.visible = matchedCamera.integrationState === 0 ? true : false;
     }
   }
-
-  const bgConfig = ref({
-    x: 0,
-    y: 0,
-    id: 'bgImg',
-    width: bgImg.width,
-    height: bgImg.height,
-    image: bgImg,
-    name: 'bgImg',
-    backgroundSize: 'cover',
-  });
-
-  //待修改
-  const transformerConfig = ref({
-    keepRatio: true,
-    rotateAnchorOffset: 30,
-    enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
-  });
-
-  //背景大小变换
-  const resizeContainer = (width, height) => {
-    stageConfig.value.width = width;
-    stageConfig.value.height = height;
-    layer.value.getNode().draw();
+}
+
+const bgConfig = ref({
+  x: 0,
+  y: 0,
+  id: 'bgImg',
+  width: bgImg.width,
+  height: bgImg.height,
+  image: bgImg,
+  name: 'bgImg',
+  backgroundSize: 'cover',
+});
+
+//待修改
+const transformerConfig = ref({
+  keepRatio: true,
+  rotateAnchorOffset: 30,
+  enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
+});
+
+//背景大小变换
+const resizeContainer = (width, height) => {
+  stageConfig.value.width = width;
+  stageConfig.value.height = height;
+  layer.value.getNode().draw();
+};
+
+const defaultIconConfig = ref({
+  x: 18,
+  y: -16,
+  width: 16,
+  height: 16,
+  id: 'defaultIcon',
+  image: favoritesImg,
+});
+
+//取消
+const handleMouseOver = (e) => {
+  document.oncontextmenu = () => {
+    return false;
   };
 
-  const defaultIconConfig = ref({
-    x: 18,
-    y: -16,
-    width: 16,
-    height: 16,
-    id: 'defaultIcon',
-    image: favoritesImg,
-  });
-
-  //取消
-  const handleMouseOver = (e) => {
-    document.oncontextmenu = () => {
-      return false;
-    };
-
-    const group = e.target.parent;
-    if (group.id() === defaultCameraId.value) {
-      tipShow.value = true;
-      const stage = transformer.value.getNode().getStage();
-      const defaultNode = stage.findOne('#defaultIcon');
-      const tipPosition = defaultNode.absolutePosition();
-      posTipX.value = Number(tipPosition?.x.toFixed(2)) || 0;
-      posTipY.value = Number(tipPosition?.y.toFixed(2)) || 0;
-      const angle = group.rotation() >= 0 ? group.rotation() : group.rotation() + 360;
-      if (angle >= 30) {
-        if (angle <= 150) {
-          pos.value = TipPositionEnum.RIGHT;
-          posTipX.value += 26;
-          posTipY.value -= 17;
-        } else if (angle <= 210) {
-          pos.value = TipPositionEnum.BOTTOM;
-          posTipY.value += 26;
-          posTipX.value -= 50;
-        } else {
-          pos.value = TipPositionEnum.LEFT;
-          posTipX.value -= 121; 
-          posTipY.value -= 25;
-        }
+  const group = e.target.parent;
+  if (group.id() === defaultCameraId.value) {
+    tipShow.value = true;
+    const stage = transformer.value.getNode().getStage();
+    const defaultNode = stage.findOne('#defaultIcon');
+    const tipPosition = defaultNode.absolutePosition();
+    posTipX.value = Number(tipPosition?.x.toFixed(2)) || 0;
+    posTipY.value = Number(tipPosition?.y.toFixed(2)) || 0;
+    const angle = group.rotation() >= 0 ? group.rotation() : group.rotation() + 360;
+    if (angle >= 30) {
+      if (angle <= 150) {
+        pos.value = TipPositionEnum.RIGHT;
+        posTipX.value += 26;
+        posTipY.value -= 17;
+      } else if (angle <= 210) {
+        pos.value = TipPositionEnum.BOTTOM;
+        posTipY.value += 26;
+        posTipX.value -= 50;
       } else {
-        posTipY.value -= 61;
-        posTipX.value -= 43;
+        pos.value = TipPositionEnum.LEFT;
+        posTipX.value -= 121;
+        posTipY.value -= 25;
       }
+    } else {
+      posTipY.value -= 61;
+      posTipX.value -= 43;
     }
+  }
+};
+// 还原浏览器默认鼠标事件
+const handleMouseLeave = () => {
+  document.oncontextmenu = () => {
+    return true;
   };
-  // 还原浏览器默认鼠标事件
-  const handleMouseLeave = () => {
-    document.oncontextmenu = () => {
-      return true;
-    };
-    tipShow.value = false;
+  tipShow.value = false;
+};
+
+const handleDragStart = () => {
+  tipShow.value = false;
+  emit('change', true);
+};
+
+const handleStageClick = (e: any) => {
+  defaultShow.value = false;
+  disabledSet.value = false;
+  document.oncontextmenu = () => {
+    return false;
   };
-
-  const handleDragStart = () => {
-    tipShow.value = false;
+  const parent = e.target.parent;
+  //判断是否点击相机组
+  if (parent.hasName('group')) {
+    lastClickedGroupId.value = parent.id();
     emit('change', true);
-  };
-
-  const handleStageClick = (e: any) => {
-    defaultShow.value = false;
-    disabledSet.value = false;
-    document.oncontextmenu = () => {
-      return false;
-    };
-    const parent = e.target.parent;
-    //判断是否点击相机组
-    if (parent.hasName('group')) {
+    // 判断是否为右键点击
+    if (e.evt.button === 2) {
       lastClickedGroupId.value = parent.id();
-      emit('change', true);
-      // 判断是否为右键点击
-      if (e.evt.button === 2) {
-        lastClickedGroupId.value = parent.id();
-        const clickedVideoUrl = props.filterData.find(
-          (item) => item.code === lastClickedGroupId.value,
-        );
-        if (clickedVideoUrl) {
-          lastClickedVideoUrl.value = clickedVideoUrl.pushstreamIp;
-        }
-        isShow.value = false;
-        posX.value = e.evt.offsetX + 20;
-        posY.value = e.evt.offsetY;
-        disabledSet.value = defaultCameraId.value === parent.id();
-        defaultShow.value = true;
+      const clickedVideoUrl = props.filterData.find(
+        (item) => item.code === lastClickedGroupId.value,
+      );
+      if (clickedVideoUrl) {
+        lastClickedVideoUrl.value = clickedVideoUrl.pushStreamDTO.videoUrls;
       }
-    } else {
-      lastClickedGroupId.value = null;
-      //取消transformer选择
-      const transformerNode = transformer.value.getNode();
-      transformerNode.nodes([]);
-    }
-  };
-
-  const handleCameraClick = (camera) => {
-    tipShow.value = false;
-    const transformerNode = transformer.value.getNode();
-    const stage = transformerNode.getStage();
-    const cameraNode = stage.findOne('#' + camera.id);
-    // 将变换器附加到点击的相机
-    transformerNode.nodes([cameraNode]);
-    transformerNode.moveToTop();
-    emit('change', true);
-  };
-
-  //添加相机
-  const addCamera = (id: string) => {
-    const existingCamera = cameras.value.find((camera) => camera.id === id);
-    if (existingCamera) return;
-    const config = {
-      width: cameraIconSize.width,
-      height: cameraIconSize.height,
-      image: camImg,
-      name: 'image',
-      id: id,
-    };
-    const groupConfig = {
-      x: 50,
-      y: 50,
-      draggable: true,
-      name: 'group',
-    };
-    const cameraDetail = {
-      id,
-      groupConfig,
-      config,
-      isDefault: false,
-    };
-    cameras.value.push(cameraDetail);
-    //当只有一个相机时,自动设置默认相机
-    if (cameras.value.length === 1) {
-      cameras.value[0].isDefault = true;
-      defaultCameraId.value = id;
+      isShow.value = false;
+      posX.value = e.evt.offsetX + 20;
+      posY.value = e.evt.offsetY;
+      disabledSet.value = defaultCameraId.value === parent.id();
+      defaultShow.value = true;
     }
-    emit('change', true);
-  };
-
-  //设置默认相机
-  const setDefaultCamera = () => {
-    //选中的相机id号
-    defaultCameraId.value = lastClickedGroupId.value!;
-    cameras.value.forEach((item) => {
-      if (item.id === defaultCameraId.value) {
-        item.isDefault = true;
-      } else {
-        item.isDefault = false;
-      }
-    });
+  } else {
+    lastClickedGroupId.value = null;
+    //取消transformer选择
     const transformerNode = transformer.value.getNode();
-    const stage = transformerNode.getStage();
     transformerNode.nodes([]);
-    const cameraNode = stage.findOne('#' + defaultCameraId.value);
-    // 将变换器附加到点击的相机
-    transformerNode.nodes([cameraNode]);
-    defaultShow.value = false;
-    emit('change', true);
-  };
-
-  const isShow = ref<boolean>(false);
-
-  const previewCamera = () => {
-    videoUrl.value = lastClickedVideoUrl.value!;
-    isShow.value = true;
-    defaultShow.value = false;
-  };
-
-  const closePreview = () => {
-    isShow.value = false;
-    defaultShow.value = false;
-  };
-
-  watch(
-    lastClickedGroupId,
-    () => {
-      emit('changeDefaultCamera', lastClickedGroupId.value);
-    },
-    { immediate: true },
-  );
-
-  watch(
-    () => cameras.value,
-    () => {
-      emit('sendCameraId', cameras.value);
-    },
-    { immediate: true, deep: true },
-  );
-
-  watch(
-    () => props.filterData,
-    () => {
-      addIntegrationState(cameras.value, props.filterData);
-    },
-    { immediate: true, deep: true },
-  );
-
-  const clearBg = () => {
-    bgImg.src = null as any as string;
-    layer.value.getNode().draw();
+  }
+};
+
+const handleCameraClick = (camera) => {
+  tipShow.value = false;
+  const transformerNode = transformer.value.getNode();
+  const stage = transformerNode.getStage();
+  const cameraNode = stage.findOne('#' + camera.id);
+  // 将变换器附加到点击的相机
+  transformerNode.nodes([cameraNode]);
+  transformerNode.moveToTop();
+  emit('change', true);
+};
+
+//添加相机
+const addCamera = (id: string) => {
+  const existingCamera = cameras.value.find((camera) => camera.id === id);
+  if (existingCamera) return;
+  const config = {
+    width: cameraIconSize.width,
+    height: cameraIconSize.height,
+    image: camImg,
+    name: 'image',
+    id: id,
   };
-
-  //添加背景
-  const addBg = (imgBg) => {
-    return new Promise((resolve) => {
-      bgImgUrl.value = imgBg;
-      bgImg.src = imgBg;
-      bgImg.onload = () => {
-        bgConfig.value.width = bgImg.width;
-        bgConfig.value.height = bgImg.height;
-        resizeContainer(bgImg.width, bgImg.height);
-        resolve(null);
-      };
-    });
+  const groupConfig = {
+    x: 50,
+    y: 50,
+    draggable: true,
+    name: 'group',
   };
-
-  //根据id找到对应的相机
-  const findCamera = (cameraId: string) => {
-    const camera = cameras.value.find((item) => item.id === cameraId);
-    return camera;
+  const cameraDetail = {
+    id,
+    groupConfig,
+    config,
+    isDefault: false,
   };
-
-  //保存布局
-  const saveLayout = () => {
-    const stage = transformer.value.getNode().getStage();
-    const groups = stage.find('.group');
-    const tempList = cloneDeep(cameras.value);
-    const camerasLists = tempList.map((item, index) => {
-      item.groupConfig.x = groups[index].attrs.x;
-      item.groupConfig.y = groups[index].attrs.y;
-      item.groupConfig.rotation = groups[index].attrs.rotation || 0;
-      item.groupConfig.scaleX = groups[index].attrs.scaleX || 1;
-      item.groupConfig.scaleY = groups[index].attrs.scaleY || 1;
-      // item.config.url = cameraImgSrc;
-      return item;
-    });
-    const layout = {
-      stageConfig: stageConfig.value,
-      bgConfig: bgConfig.value,
-      bgImgUrl: bgImgUrl.value,
-      defaultCameraId: defaultCameraId.value,
-      cameraList: camerasLists,
+  cameras.value.push(cameraDetail);
+  //当只有一个相机时,自动设置默认相机
+  if (cameras.value.length === 1) {
+    cameras.value[0].isDefault = true;
+    defaultCameraId.value = id;
+  }
+  emit('change', true);
+};
+
+//设置默认相机
+const setDefaultCamera = () => {
+  //选中的相机id号
+  defaultCameraId.value = lastClickedGroupId.value!;
+  cameras.value.forEach((item) => {
+    if (item.id === defaultCameraId.value) {
+      item.isDefault = true;
+    } else {
+      item.isDefault = false;
+    }
+  });
+  const transformerNode = transformer.value.getNode();
+  const stage = transformerNode.getStage();
+  transformerNode.nodes([]);
+  const cameraNode = stage.findOne('#' + defaultCameraId.value);
+  // 将变换器附加到点击的相机
+  transformerNode.nodes([cameraNode]);
+  defaultShow.value = false;
+  emit('change', true);
+};
+
+const isShow = ref<boolean>(false);
+
+const previewCamera = () => {
+  videoUrl.value = lastClickedVideoUrl.value!;
+  if (!videoUrl.value) {
+    ElMessage.warning('视频流不存在!');
+    return
+  }
+  isShow.value = true;
+  defaultShow.value = false;
+};
+
+const closePreview = () => {
+  isShow.value = false;
+  defaultShow.value = false;
+};
+
+watch(
+  lastClickedGroupId,
+  () => {
+    emit('changeDefaultCamera', lastClickedGroupId.value);
+  },
+  { immediate: true },
+);
+
+watch(
+  () => cameras.value,
+  () => {
+    emit('sendCameraId', cameras.value);
+  },
+  { immediate: true, deep: true },
+);
+
+watch(
+  () => props.filterData,
+  () => {
+    addIntegrationState(cameras.value, props.filterData);
+  },
+  { immediate: true, deep: true },
+);
+
+const clearBg = () => {
+  bgImg.src = null as any as string;
+  layer.value.getNode().draw();
+};
+
+//添加背景
+const addBg = (imgBg) => {
+  return new Promise((resolve) => {
+    bgImgUrl.value = imgBg;
+    bgImg.src = imgBg;
+    bgImg.onload = () => {
+      bgConfig.value.width = bgImg.width;
+      bgConfig.value.height = bgImg.height;
+      resizeContainer(bgImg.width, bgImg.height);
+      resolve(null);
     };
-    emit('change', false);
-    return JSON.stringify(layout);
-  };
-
-  //删除相机
-  // const handleKeyDown = (e) => {
-  //   if (e.keyCode === 46 || e.code === 'Delete' || e.keyCode === 8 || e.code === 'Backspace') {
-  //     if (lastClickedGroupId.value === defaultCameraId.value) {
-  //       // ElMessage.error({
-  //       //   message: '无法删除默认相机',
-  //       // });
-  //       // return;
-  //       ElMessageBox.confirm('此相机为默认相机,您确认要删除此相机?', 'Warning', {
-  //         confirmButtonText: '确认',
-  //         cancelButtonText: '取消',
-  //         type: 'warning',
-  //       })
-  //         .then(() => {
-  //           const index = cameras.value.findIndex((item) => item.id === lastClickedGroupId.value);
-  //           index >= 0 && cameras.value.splice(index, 1);
-  //           lastClickedGroupId.value = '';
-
-  //           //取消transformer
-  //           const transformerNode = transformer.value.getNode();
-  //           transformerNode.nodes([]);
-  //         })
-  //         .catch(() => {});
-  //     } else {
-  //       const index = cameras.value.findIndex((item) => item.id === lastClickedGroupId.value);
-  //       index >= 0 && cameras.value.splice(index, 1);
-  //       lastClickedGroupId.value = '';
-
-  //       //取消transformer
-  //       const transformerNode = transformer.value.getNode();
-  //       transformerNode.nodes([]);
-  //     }
-  //     emit('change', true);
-  //   }
-  // };
-
-  //重置
-  const resetMap = () => {
-    bgImgUrl.value = null;
-    clearBg();
-    cameras.value = [];
-    lastClickedGroupId.value = null;
-    lastClickedGroupId.value = null;
-    videoUrl.value = '';
-    isShow.value = false;
-    defaultCameraId.value = '';
+  });
+};
+
+//根据id找到对应的相机
+const findCamera = (cameraId: string) => {
+  const camera = cameras.value.find((item) => item.id === cameraId);
+  return camera;
+};
+
+//保存布局
+const saveLayout = () => {
+  const stage = transformer.value.getNode().getStage();
+  const groups = stage.find('.group');
+  const tempList = cloneDeep(cameras.value);
+  const camerasLists = tempList.map((item, index) => {
+    item.groupConfig.x = groups[index].attrs.x;
+    item.groupConfig.y = groups[index].attrs.y;
+    item.groupConfig.rotation = groups[index].attrs.rotation || 0;
+    item.groupConfig.scaleX = groups[index].attrs.scaleX || 1;
+    item.groupConfig.scaleY = groups[index].attrs.scaleY || 1;
+    // item.config.url = cameraImgSrc;
+    return item;
+  });
+  const layout = {
+    stageConfig: stageConfig.value,
+    bgConfig: bgConfig.value,
+    bgImgUrl: bgImgUrl.value,
+    defaultCameraId: defaultCameraId.value,
+    cameraList: camerasLists,
   };
-
-  /** 导入布局json */
-  const createMap = (layout, selectId) => {
-    addBg(layout.bgImgUrl).then((_res) => {
-      const unExitList = [] as any[];
-      stageConfig.value = layout.stageConfig;
-      defaultCameraId.value = layout.defaultCameraId;
-      layout.cameraList = layout.cameraList
-        ?.map((item) => {
-          item.config.image = camImg;
-          const width = item.config.width;
-          const height = item.config.height;
-          const ratio = width / height;
-          /** 老版本的相机icon比例在1.4左右,新icon已经更新,比例是1:1,为了避免新icon渲染出来变形,需要调整icon大小
-           * 如果图标的比例在该范围,那么会将它设置为新图标的icon大小 */
-          if (1.3 < ratio && ratio < 1.5) {
-            item.config.width = cameraIconSize.width;
-            item.config.height = cameraIconSize.height;
-          }
-
-          return item;
+  emit('change', false);
+  return JSON.stringify(layout);
+};
+
+//删除相机
+const handleKeyDown = (e) => {
+  console.log(e)
+  if (e.keyCode === 46 || e.code === 'Delete' || e.keyCode === 8 || e.code === 'Backspace') {
+    if (lastClickedGroupId.value === defaultCameraId.value) {
+      // ElMessage.error({
+      //   message: '无法删除默认相机',
+      // });
+      // return;
+      ElMessageBox.confirm('此相机为默认相机,您确认要删除此相机?', 'Warning', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+        .then(() => {
+          const index = cameras.value.findIndex((item) => item.id === lastClickedGroupId.value);
+          index >= 0 && cameras.value.splice(index, 1);
+          lastClickedGroupId.value = '';
+
+          //取消transformer
+          const transformerNode = transformer.value.getNode();
+          transformerNode.nodes([]);
         })
-        ?.filter((cam) => {
-          if (shopCameraList.value.findIndex((x) => x.code === cam.id) >= 0) {
-            return true;
-          } else {
-            unExitList.push(cam.code);
-            return false;
-          }
-        });
-      if (unExitList.length > 0) {
-        ElMessage.warning('部分相机不存在,已为您删除!');
-
-        const layoutNew = cloneDeep(layout);
-        updateMinMapViewLayoutApi({
-          layout: JSON.stringify({ ...layoutNew, isUploadBg: true }),
-          targetId: String(selectId),
-          viewType: 2
-        });
-      }
+        .catch(() => { });
+    } else {
+      const index = cameras.value.findIndex((item) => item.id === lastClickedGroupId.value);
+      index >= 0 && cameras.value.splice(index, 1);
+      lastClickedGroupId.value = '';
 
-      cameras.value = layout.cameraList;
-    });
-  };
+      //取消transformer
+      const transformerNode = transformer.value.getNode();
+      transformerNode.nodes([]);
+    }
+    emit('change', true);
+  }
+};
+
+//重置
+const resetMap = () => {
+  bgImgUrl.value = null;
+  clearBg();
+  cameras.value = [];
+  lastClickedGroupId.value = null;
+  lastClickedGroupId.value = null;
+  videoUrl.value = '';
+  isShow.value = false;
+  defaultCameraId.value = '';
+};
+
+/** 导入布局json */
+const createMap = (layout, selectId) => {
+  addBg(layout.bgImgUrl).then((_res) => {
+    const unExitList = [] as any[];
+    stageConfig.value = layout.stageConfig;
+    defaultCameraId.value = layout.defaultCameraId;
+    layout.cameraList = layout.cameraList
+      ?.map((item) => {
+        item.config.image = camImg;
+        const width = item.config.width;
+        const height = item.config.height;
+        const ratio = width / height;
+        /** 老版本的相机icon比例在1.4左右,新icon已经更新,比例是1:1,为了避免新icon渲染出来变形,需要调整icon大小
+         * 如果图标的比例在该范围,那么会将它设置为新图标的icon大小 */
+        if (1.3 < ratio && ratio < 1.5) {
+          item.config.width = cameraIconSize.width;
+          item.config.height = cameraIconSize.height;
+        }
 
-  defineExpose({
-    addBg,
-    createMap,
-    handleCameraClick,
-    findCamera,
-    resetMap,
-    addCamera,
-    resizeContainer,
-    saveLayout,
-  });
+        return item;
+      })
+      ?.filter((cam) => {
+        if (shopCameraList.value.findIndex((x) => x.code === cam.id) >= 0) {
+          return true;
+        } else {
+          unExitList.push(cam.code);
+          return false;
+        }
+      });
+    if (unExitList.length > 0) {
+      ElMessage.warning('部分相机不存在,已为您删除!');
+
+      const layoutNew = cloneDeep(layout);
+      updateMinMapViewLayoutApi({
+        layout: JSON.stringify({ ...layoutNew, isUploadBg: true }),
+        targetId: String(selectId),
+        viewType: 2
+      });
+    }
 
-  onMounted(() => {
-    // window.addEventListener('keydown', handleKeyDown);
-    camImg.src = cameraImgSrc;
+    cameras.value = layout.cameraList;
   });
-
-  // onBeforeUnmount(() => {
-  //   window.removeEventListener('keydown', handleKeyDown);
-  // });
+};
+
+defineExpose({
+  addBg,
+  createMap,
+  handleCameraClick,
+  findCamera,
+  resetMap,
+  addCamera,
+  resizeContainer,
+  saveLayout,
+});
+onMounted(() => {
+  camImg.src = cameraImgSrc;
+  // stageAll.value.addEventListener('keydown', handleKeyDown);
+});
+
+// onBeforeUnmount(() => {
+//   stageAll.value.removeEventListener('keydown', handleKeyDown);
+// });
 </script>
 
 <style scoped lang="scss">
-  .opt-container {
-    width: 160px;
-    padding: 10px;
-    border-radius: 5px;
-    background-color: #ffffff;
-    box-shadow: 5px 5px 5px #a3a5a5;
-  }
-  .opt-item {
-    height: 30px;
-    font-size: 14px;
-    color: #404040;
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
-    padding-left: 8px;
-    border-radius: 3px;
-    cursor: pointer;
-
-    &:hover {
-      background-color: #f1f2f5;
-    }
-  }
-
-  .disabled {
+.opt-container {
+  width: 160px;
+  padding: 10px;
+  border-radius: 5px;
+  background-color: #ffffff;
+  box-shadow: 5px 5px 5px #a3a5a5;
+}
+
+.opt-item {
+  height: 30px;
+  font-size: 14px;
+  color: #404040;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  padding-left: 8px;
+  border-radius: 3px;
+  cursor: pointer;
+
+  &:hover {
     background-color: #f1f2f5;
-    color: #bcbdc0;
-    cursor: not-allowed;
   }
+}
+
+.disabled {
+  background-color: #f1f2f5;
+  color: #bcbdc0;
+  cursor: not-allowed;
+}
 </style>

+ 22 - 21
src/views/map-config/mini-map/MiniMapConfig.vue

@@ -68,8 +68,8 @@
       </div>
       <div ref="drawContainer" v-show="isUploadBg || shopCameraList.length !== 1" class="draw-container"
         :class="{ 'bg-background': hasBg ? true : false }">
-        <KonvaMap ref="konvaMap" :filter-data="filterShopCameraList" @change-default-camera="changeDefault"
-          @send-camera-id="sendCameras" @change="changeMap" v-moveable:1 />
+        <KonvaMap ref="konvaMap" :filter-data="filterShopCameraList" :camera-list="shopCameraList"
+          @change-default-camera="changeDefault" @send-camera-id="sendCameras" @change="changeMap" v-moveable:1 />
         <div id="editContainer" v-moveable:1></div>
         <el-upload v-if="!hasBg" class="upload-icon flex justify-center items-center" :action="actionUrl"
           :show-file-list="false" :before-upload="handleBeforeUpload" :on-success="handleAvatarSuccess"
@@ -100,7 +100,7 @@ import rollback from '@/assets/rollback.png'
 import router from '@/router';
 import { ShopMapCamera } from '@/types/scene/type'
 const cameraStatus = useCameraStatus();
-const { openInterval, closeInterval } = cameraStatus;
+const { openIntervalNew, closeInterval } = cameraStatus;
 
 // const miniMap = useMiniMap();
 // const { scenesTree, selectedShopCode, selectedShopDetail } = storeToRefs(miniMap);
@@ -196,7 +196,7 @@ const getMapLayout = async (id: number) => {
 }
 const getShopContent = async (id: number) => {
   await getShowCameras(id);
-  // const idList = filterShopCameraList.value.map((item) => item.id);
+  const idList = filterShopCameraList.value.map((item) => item.id);
   const res = await getMapLayout(id);
   if (!res) return;
   hasBg.value = true;
@@ -208,23 +208,24 @@ const getShopContent = async (id: number) => {
     hasBg.value = false;
     isUploadBg.value = res.isUploadBg;
   }
-  // openInterval(codeList, (targetData) => {
-  //   updataState(filterShopCameraList.value, targetData);
-  // });
-  // getMapLayout(code).then((res) => {
-  //   if (!res) {
-  //     return;
-  //   }
-  //   hasBg.value = true;
-  //   isMap.value = res.isUploadBg;
-  //   if (res.isUploadBg) {
-  //     isUploadBg.value = true;
-  //     konvaMap.value.createMap(res, selectedShopDetail.value?.id);
-  //   } else {
-  //     hasBg.value = false;
-  //     isUploadBg.value = res.isUploadBg;
-  //   }
-  // });
+  openIntervalNew(idList, (targetData) => {
+    updataState(filterShopCameraList.value, targetData);
+  });
+  getMapLayout(id).then((res) => {
+    if (!res) {
+      return;
+    }
+    hasBg.value = true;
+    isMap.value = res.isUploadBg;
+    if (res.isUploadBg) {
+      isUploadBg.value = true;
+      console.log(res)
+      konvaMap.value.createMap(res, selectedShopId.value);
+    } else {
+      hasBg.value = false;
+      isUploadBg.value = res.isUploadBg;
+    }
+  });
 };
 const selectedShopId = ref();
 const selectedName = ref();

+ 41 - 41
src/views/map-config/mini-map/use-mini-map.ts

@@ -19,58 +19,58 @@ export const useMiniMap = defineStore('mini-map', () => {
   const { scenesTree, flattenedWorkshops } = toRefs(sceneInfos);
   const { getScenesTree } = sceneInfos;
 
-  const selectedShopCode = ref<string>();
-  const selectedShopDetail = computed(() =>
-    flattenedWorkshops.value.find((space) => space.code === selectedShopCode.value),
-  );
+  // const selectedShopCode = ref<string>();
+  // const selectedShopDetail = computed(() =>
+  //   flattenedWorkshops.value.find((space) => space.code === selectedShopCode.value),
+  // );
 
-  const getShopDetailByCode = (code: string) => {
-    return flattenedWorkshops.value.find((space) => space.code === code);
-  };
+  // const getShopDetailByCode = (code: string) => {
+  //   return flattenedWorkshops.value.find((space) => space.code === code);
+  // };
   const bgImgUrl = ref('');
 
-  const shopCameraList = ref<ShopMapCamera[]>([]);
+  // const shopCameraList = ref<ShopMapCamera[]>([]);
 
-  const getShowCameras = (code: string) => {
-    shopCameraList.value = [];
-    const id = getShopDetailByCode(code)?.id;
+  // const getShowCameras = (code: string) => {
+  //   shopCameraList.value = [];
+  //   const id = getShopDetailByCode(code)?.id;
 
-    if (!id) {
-      ElMessage.error('摄像头code未找到对应信息');
-      return Promise.resolve();
-    }
-    return getCamerasByWorkShopId({ workshopId: id }).then((res) => {
-      res.children?.forEach((space) => {
-        if (space.children && space.children.length > 0) {
-          space.children.forEach((camera) => {
-            shopCameraList.value.push({ ...camera, isSet: 0, workSpaceName: space.name });
-          });
-        }
-      });
-    });
-  };
+  //   if (!id) {
+  //     ElMessage.error('摄像头code未找到对应信息');
+  //     return Promise.resolve();
+  //   }
+  //   return getCamerasByWorkShopId({ workshopId: id }).then((res) => {
+  //     res.children?.forEach((space) => {
+  //       if (space.children && space.children.length > 0) {
+  //         space.children.forEach((camera) => {
+  //           shopCameraList.value.push({ ...camera, isSet: 0, workSpaceName: space.name });
+  //         });
+  //       }
+  //     });
+  //   });
+  // };
 
-  const getMapLayout = (code: string) => {
-    const shopId = getShopDetailByCode(code)?.id || '';
-    if (!shopId) {
-      ElMessage.error('摄像头code未找到对应信息');
-      return Promise.reject();
-    }
-    return getWorkshopMiniMapLayoutApi(shopId).then((res) => {
-      const layoutJSON = res?.layout ? safeParse(res.layout) : null;
-      return layoutJSON;
-    });
-  };
+  // const getMapLayout = (code: string) => {
+  //   const shopId = getShopDetailByCode(code)?.id || '';
+  //   if (!shopId) {
+  //     ElMessage.error('摄像头code未找到对应信息');
+  //     return Promise.reject();
+  //   }
+  //   return getWorkshopMiniMapLayoutApi(shopId).then((res) => {
+  //     const layoutJSON = res?.layout ? safeParse(res.layout) : null;
+  //     return layoutJSON;
+  //   });
+  // };
 
   return {
-    selectedShopDetail,
+    // selectedShopDetail,
     bgImgUrl,
     scenesTree,
-    shopCameraList,
+    // shopCameraList,
     getScenesTree,
-    getShowCameras,
-    getMapLayout,
-    selectedShopCode,
+    // getShowCameras,
+    // getMapLayout,
+    // selectedShopCode,
   };
 });
 

+ 8 - 5
src/views/page-config/component/BasicLayoutEntry.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="page-config-content">
     <main class="main__config">
-      <div class="card--default" @click="toLayout(ViewType.companyHomepage_PC)">
+      <div class="card--default" @click="toLayout('PC')">
         <section class="card__left">
           <img :src="PCIcon" />
         </section>
@@ -10,7 +10,7 @@
           <span class="span__card--describe"> {{ describeDefault }} PC端生效 </span>
         </section>
       </div>
-      <div class="card--default" @click="toLayout(ViewType.companyHomepage_phone)">
+      <div class="card--default" @click="toLayout('Phone')">
         <section class="card__left">
           <img :src="PhoneIcon" />
         </section>
@@ -45,12 +45,15 @@ const generateContentDefault = (layoutType: LayoutConfigType.scene | LayoutConfi
       break;
   }
 }
-const toLayout = (type: ViewType.companyHomepage_PC | ViewType.companyHomepage_phone) => {
+const toLayout = (type: 'PC' | 'Phone') => {
+  let viewType;
   if (props.layoutType === LayoutConfigType.scene) {
-    router.push(`/layout/scene-list?viewType=${type}`);
+    viewType = type === 'PC' ? ViewType.companyHomepage_PC : ViewType.companyHomepage_phone
+    router.push(`/layout/scene-list?viewType=${viewType}`);
     return;
   }
-  router.push(`/layout/camera-list?viewType=${type}`);
+  viewType = type === 'PC' ? ViewType.minimap_PC : ViewType.minimap_phone
+  router.push(`/layout/camera-list?viewType=${viewType}`);
 };
 onMounted(() => {
   generateContentDefault(props.layoutType);

+ 3 - 3
src/views/page-config/component/BasicLayoutList.vue

@@ -112,15 +112,15 @@ const scenePlatformApiMap = {
   [ViewType.companyHomepage_phone]: getMobileCompanyLayoutList,
 };
 const cameraPlatformApiMap = {
-  [ViewType.companyHomepage_PC]: getPcCameraLayoutList,
-  [ViewType.companyHomepage_phone]: getMobileCameraLayoutList,
+  [ViewType.minimap_PC]: getPcCameraLayoutList,
+  [ViewType.minimap_phone]: getMobileCameraLayoutList,
 };
 const getLayoutInfoImg = (layoutType: LayoutConfigType.scene | LayoutConfigType.camera, viewType: number, idList: number[]) => {
   switch (layoutType) {
     case LayoutConfigType.scene:
       scenePlatformApiMap[viewType]({ companyIds: idList }).then((res) => {
         res.map((companyWithLayout) => {
-          layoutList.value.find((company) => company.id === companyWithLayout.id)!.layout =
+          layoutList.value.find((company) => company.id === companyWithLayout.targetId)!.layout =
             JSON.parse(companyWithLayout.layout).bgInfo.img;
         });
       });