Ver código fonte

feat: 相机预览功能优化

bxy 1 ano atrás
pai
commit
9dd5c29788

+ 24 - 3
src/api/camera/camera-preview.ts

@@ -26,13 +26,26 @@ export interface CameraTree {
   integrationState: number;
   integrationState: number;
 }
 }
 
 
+export interface CameraQueryForm {
+  isEnableAlgo: boolean; // 是否添加算法:0-未勾选该条件、1-已添加
+  isEnableRender: boolean; // 是否开启渲染:0-未勾选该条件、1-已开启
+  queryString: string; // 搜索条件
+}
+
 /** 获取摄像头所在的树状结构 */
 /** 获取摄像头所在的树状结构 */
-export const getCameraTree = () => {
+export const getCameraTree = (param?: CameraQueryForm) => {
   return http.request<CameraTree[]>({
   return http.request<CameraTree[]>({
-    url: '/cameraPreview/getList',
-    method: 'get',
+    url: '/cameraPreview/queryCameraListByCondition',
+    method: 'post',
+    data: param,
   });
   });
 };
 };
+// export const getCameraTree = () => {
+//   return http.request<CameraTree[]>({
+//     url: '/cameraPreview/getList',
+//     method: 'get',
+//   });
+// };
 
 
 /** 算法是否启用 */
 /** 算法是否启用 */
 export enum ALGO_ENABLED_STATUS {
 export enum ALGO_ENABLED_STATUS {
@@ -389,3 +402,11 @@ export const updateFenceDisplayStatus = (data: UpdateFenceType) => {
     data,
     data,
   });
   });
 };
 };
+
+// 根据相机id查询相机detail
+export const getCameraDeatilById = (id: number) => {
+  return http.request({
+    url: `/cameraPreview/queryCameraDetailById?id=${id}`,
+    method: 'post',
+  });
+};

+ 11 - 104
src/views/cameras/preview/CameraPreview.vue

@@ -2,13 +2,7 @@
   <div>
   <div>
     <div class="cameraMain">
     <div class="cameraMain">
       <div class="cameraTree">
       <div class="cameraTree">
-        <CameraTreeCom
-          :loading="presetListStore.loading"
-          :camera-tree="cameraTree || []"
-          :total="codeShowList.length"
-          :no-integration-num="noIntegrationNum"
-          :no-networking-num="noNetworkingNum"
-        />
+        <CameraTreeCom />
       </div>
       </div>
       <div class="cameraSettingWrapper">
       <div class="cameraSettingWrapper">
         <div class="cameraView">
         <div class="cameraView">
@@ -21,21 +15,16 @@
 </template>
 </template>
 
 
 <script lang="ts" setup>
 <script lang="ts" setup>
-  import { onUnmounted, ref, watch } from 'vue';
+  import { onMounted, ref, watch } from 'vue';
+  import { storeToRefs } from 'pinia';
   import CameraTreeCom from './components/CameraTree/CameraTree.vue';
   import CameraTreeCom from './components/CameraTree/CameraTree.vue';
   import CameraViewSetting from './components/CameraViewSetting/CameraViewSetting.vue';
   import CameraViewSetting from './components/CameraViewSetting/CameraViewSetting.vue';
   import useCameraDetailStore from './store/useCameraDetailStore';
   import useCameraDetailStore from './store/useCameraDetailStore';
   import useCameraAlgoStore from './store/useCameraAlgoStore';
   import useCameraAlgoStore from './store/useCameraAlgoStore';
   import usePresetListStore from './store/usePresetListStore';
   import usePresetListStore from './store/usePresetListStore';
   import useFenceStore from './store/useFenceStore';
   import useFenceStore from './store/useFenceStore';
-  import { onMounted } from 'vue';
   import { IsPtz } from '@/api/camera/camera-overview';
   import { IsPtz } from '@/api/camera/camera-overview';
-  import { CameraTree, getCameraTree } from '@/api/camera/camera-preview';
-  import useCameraStatus from './store/useCameraStatus';
-  import { storeToRefs } from 'pinia';
-
-  const cameraStatus = useCameraStatus();
-  const { noNetworkingNum, openInterval, closeInterval } = cameraStatus;
+  import { CameraTree, getCameraTree, getCameraDeatilById } from '@/api/camera/camera-preview';
 
 
   const cameraDetailStore = useCameraDetailStore();
   const cameraDetailStore = useCameraDetailStore();
   const { isShowFence } = storeToRefs(cameraDetailStore);
   const { isShowFence } = storeToRefs(cameraDetailStore);
@@ -43,29 +32,6 @@
   const fenceStore = useFenceStore();
   const fenceStore = useFenceStore();
   const presetListStore = usePresetListStore();
   const presetListStore = usePresetListStore();
   const cameraTree = ref<CameraTree[]>([]);
   const cameraTree = ref<CameraTree[]>([]);
-  const codeShowList = ref<string[]>([]);
-  const noIntegrationNum = ref<number>(0);
-
-  function updateNetworkingState(data, targetData) {
-    let integrationCount = 0;
-    for (let i = 0; i < data.length; i++) {
-      const node = data[i];
-      const matchedNode = targetData.find((item) => item.cameraCode === node.code);
-      if (matchedNode) {
-        node.networkingState = matchedNode.status;
-        node.integrationState = matchedNode.integrationState;
-      }
-      if (node.integrationState === 1) {
-        integrationCount++;
-      }
-      if (node.children && node.children.length > 0) {
-        const childIntegrationCount = updateNetworkingState(node.children, targetData);
-        integrationCount += childIntegrationCount;
-      }
-    }
-    noIntegrationNum.value = integrationCount;
-    return integrationCount;
-  }
 
 
   function updateRender(data, targetData, targetVal) {
   function updateRender(data, targetData, targetVal) {
     for (let i = 0; i < data.length; i++) {
     for (let i = 0; i < data.length; i++) {
@@ -79,21 +45,6 @@
     }
     }
   }
   }
 
 
-  function getCameraList(data) {
-    let cameraList = [] as string[];
-    for (let i = 0; i < data.length; i++) {
-      const node = data[i];
-      if (node.nodeType === 'camera') {
-        cameraList.push(node.code);
-      }
-      if (node.children && node.children.length > 0) {
-        const childCameraList = getCameraList(node.children);
-        cameraList.push(...childCameraList);
-      }
-    }
-    return cameraList;
-  }
-
   const changeRender = (render: string | number) => {
   const changeRender = (render: string | number) => {
     updateRender(cameraTree.value, cameraDetailStore.cameraId, render);
     updateRender(cameraTree.value, cameraDetailStore.cameraId, render);
   };
   };
@@ -105,21 +56,13 @@
       fenceStore.clear();
       fenceStore.clear();
       if (cameraId) {
       if (cameraId) {
         const presetList = await presetListStore.getPresetList(cameraId);
         const presetList = await presetListStore.getPresetList(cameraId);
-
-        if (cameraTree.value.length === 0) {
-          /** 如果当前树为空,那么切换相机的时候,要重新请求树结构 */
-          const tree = await getCameraTree();
-          cameraTree.value = tree as unknown as CameraTree[];
-        }
-
-        const detail = getCameraDetail(cameraTree.value, cameraDetailStore.cameraId);
-        if (detail) {
-          cameraDetailStore.setDetail(detail);
+        getCameraDeatilById(cameraId).then((res) => {
+          cameraDetailStore.setDetail(res);
           // 如果isPtz为null,或者为0,都按照枪击相机
           // 如果isPtz为null,或者为0,都按照枪击相机
-          if (detail?.isPtz === IsPtz.disabled || !detail?.isPtz) {
+          if (res.isPtz === IsPtz.disabled || !res.isPtz) {
             presetListStore.currentPresetToken = presetList?.[0].token;
             presetListStore.currentPresetToken = presetList?.[0].token;
           }
           }
-        }
+        });
 
 
         cameraAlgoStore.getCameraAlgoList(cameraId);
         cameraAlgoStore.getCameraAlgoList(cameraId);
         cameraAlgoStore.selectedAlgoId = null;
         cameraAlgoStore.selectedAlgoId = null;
@@ -136,45 +79,9 @@
 
 
   onMounted(() => {
   onMounted(() => {
     cameraAlgoStore.getAllAlgoList();
     cameraAlgoStore.getAllAlgoList();
-    getCameraTree().then((res) => {
-      cameraTree.value = res;
-      codeShowList.value = getCameraList(res);
-      // openInterval(codeShowList.value, cameraTree.value, updateNetworkingState);
-      // (targetData) => { updateNetworkingState(cameraTree.value, targetData) }
-      openInterval(codeShowList.value, (targetData) => {
-        updateNetworkingState(cameraTree.value, targetData);
-      });
-    });
-  });
-
-  onUnmounted(() => {
-    /** 离开页面要清理掉所有的store */
-    cameraDetailStore.clear();
-    cameraAlgoStore.clear();
-    fenceStore.clear();
-    presetListStore.clear();
-    closeInterval();
   });
   });
-
-  function getCameraDetail(tree: CameraTree[], cameraId: number): CameraTree | null {
-    let detail: CameraTree | null = null;
-
-    function getDetail(t: CameraTree[], parent) {
-      t.forEach((x) => {
-        if (x.nodeType === 'camera' && x.id === cameraId) {
-          detail = x;
-          detail.workshopId = parent?.workshopId;
-        } else if (x.children && x.children.length > 0) {
-          getDetail(x.children, x);
-        }
-      });
-    }
-
-    getDetail(tree, null);
-
-    return detail;
-  }
 </script>
 </script>
+
 <style lang="scss" scoped>
 <style lang="scss" scoped>
   .cameraParamsSetting {
   .cameraParamsSetting {
     width: 350px;
     width: 350px;
@@ -199,8 +106,8 @@
     // height: calc(100vh - 90px);
     // height: calc(100vh - 90px);
   }
   }
   .cameraTree {
   .cameraTree {
-    min-width: 250px;
-    max-width: 400px;
+    min-width: 270px;
+    max-width: 600px;
     flex-shrink: 0;
     flex-shrink: 0;
     // height: 800px;
     // height: 800px;
     // border: 1px solid #ccc;
     // border: 1px solid #ccc;

+ 124 - 66
src/views/cameras/preview/components/CameraTree/CameraTree.vue

@@ -2,32 +2,43 @@
   <div class="cameraTreeWrapper">
   <div class="cameraTreeWrapper">
     <div class="cameraTreeTitle">
     <div class="cameraTreeTitle">
       <span>场景树</span>
       <span>场景树</span>
-      <span class="detail-num" v-if="props.total"
-        >(总相机:{{ props.total }} 未联网:{{ props.noNetworkingNum }} 未进入平台:{{
-          props.noIntegrationNum
-        }})</span
-      ></div
-    >
+      <span class="detail-num" v-if="totalNum">
+        (总相机:{{ totalNum }} 未联网:{{ noNetworkingNum }} 未进入平台:{{ noIntegrationNum }})
+      </span>
+    </div>
     <div class="cameraTreeInputWrapper">
     <div class="cameraTreeInputWrapper">
       <el-input
       <el-input
-        v-model="filterText"
-        placeholder="请输入相机的名称进行搜索"
-        :suffix-icon="Search"
         class="filterTextInput"
         class="filterTextInput"
+        v-model="queryForm.queryString"
+        :suffix-icon="Search"
+        placeholder="请输入相机名称/设备ID/算法名称"
+        @keyup.enter.native="handleSearchCamera"
       />
       />
+      <div style="display: flex; justify-content: space-around">
+        <el-checkbox
+          v-model="queryForm.isEnableAlgo"
+          label="已添加算法"
+          @change="handleSearchCamera"
+        />
+        <el-checkbox
+          v-model="queryForm.isEnableRender"
+          label="已开启渲染"
+          @change="handleSearchCamera"
+        />
+      </div>
       <el-scrollbar class="tree-scroll">
       <el-scrollbar class="tree-scroll">
         <el-tree
         <el-tree
-          :data="props.cameraTree"
+          ref="treeRef"
+          node-key="code"
+          :data="cameraTreeTemp"
           :props="defaultProps"
           :props="defaultProps"
           @node-click="handleNodeClick"
           @node-click="handleNodeClick"
-          node-key="code"
-          :default-expand-all="true"
-          :filter-node-method="filterNode"
-          ref="treeRef"
-          v-loading="props.loading"
         >
         >
           <template #default="{ node, data }">
           <template #default="{ node, data }">
-            <span class="flexCenter" :class="{ integrationState: data.integrationState === 1 }">
+            <span
+              class="flexCenter"
+              :class="{ integrationState: data.integrationState === 1, nodeSelect: isSelect(data) }"
+            >
               <span
               <span
                 v-if="data.nodeType === CameraTreeNodeType.camera"
                 v-if="data.nodeType === CameraTreeNodeType.camera"
                 class="iconWrapper flexCenter"
                 class="iconWrapper flexCenter"
@@ -58,42 +69,45 @@
   </div>
   </div>
 </template>
 </template>
 <script lang="ts" setup>
 <script lang="ts" setup>
+  import { onMounted, onUnmounted, ref } from 'vue';
   import { ElMessage, ElTree } from 'element-plus';
   import { ElMessage, ElTree } from 'element-plus';
-  import { ref, watch } from 'vue';
-  import { useRouteQuery } from '@vueuse/router';
   import { Search, VideoCamera, WarningFilled } from '@element-plus/icons-vue';
   import { Search, VideoCamera, WarningFilled } from '@element-plus/icons-vue';
+  import { useRouteQuery } from '@vueuse/router';
+  import useCameraStatus from '../../store/useCameraStatus';
+  import {
+    CameraTree,
+    CameraTreeNodeType,
+    CameraQueryForm,
+    getCameraTree,
+  } from '@/api/camera/camera-preview';
 
 
-  import useCameraDetail from '../../store/useCameraDetailStore';
-  import { CameraTree, CameraTreeNodeType } from '@/api/camera/camera-preview';
-
-  const props = defineProps<{
-    cameraTree: Tree[];
-    loading: boolean;
-    total: number;
-    noNetworkingNum?: number;
-    noIntegrationNum?: number;
-  }>();
-
-  interface Tree {
-    [key: string]: any;
-  }
+  const cameraId = useRouteQuery('cameraId');
+  const cameraStatus = useCameraStatus();
+  const { noNetworkingNum, openInterval, closeInterval } = cameraStatus;
 
 
-  const { setDetail } = useCameraDetail();
+  const queryForm = ref<CameraQueryForm>({
+    isEnableAlgo: false,
+    isEnableRender: false,
+    queryString: '',
+  });
+  const totalNum = ref(0); // 总相机数
+  const noIntegrationNum = ref(0); // 未进入平台相机数
+  const cameraTree = ref<CameraTree[]>([]); // 保存从接口获取的所有树节点信息
+  const cameraTreeTemp = ref<CameraTree[]>([]); // 保存修改name之后的树
+  const codeShowList = ref<string[]>([]); // 保存当前所有相机code列表
 
 
-  const cameraId = useRouteQuery('cameraId');
+  const treeRef = ref<InstanceType<typeof ElTree>>();
   const defaultProps = {
   const defaultProps = {
     children: 'children',
     children: 'children',
     label: 'name',
     label: 'name',
   };
   };
 
 
   const handleNodeClick = (e: CameraTree) => {
   const handleNodeClick = (e: CameraTree) => {
-    console.log('e', e);
     if (e.integrationState === 1) {
     if (e.integrationState === 1) {
       ElMessage.error('该相机未进入平台');
       ElMessage.error('该相机未进入平台');
     } else {
     } else {
       if (e.nodeType === CameraTreeNodeType.camera) {
       if (e.nodeType === CameraTreeNodeType.camera) {
         cameraId.value = String(e.id);
         cameraId.value = String(e.id);
-        setDetail(e);
       }
       }
     }
     }
   };
   };
@@ -101,47 +115,87 @@
   const isSelect = (data) =>
   const isSelect = (data) =>
     data.nodeType === CameraTreeNodeType.camera && data.id === Number(cameraId.value);
     data.nodeType === CameraTreeNodeType.camera && data.id === Number(cameraId.value);
 
 
-  const filterText = ref('');
-  const treeRef = ref<InstanceType<typeof ElTree>>();
-
-  watch(filterText, (val) => {
-    childrenNodeList.value = [];
-    treeRef.value!.filter(val);
-  });
-
-  const childrenNodeList = ref<string[]>([]);
+  const isInvalid = (data) => {
+    return data.networkingState !== 0;
+  };
 
 
-  function extractCodes(data: any[], codes: string[] = []) {
-    data.forEach((item) => {
-      codes.push(item.data.code);
-      if (item.childNodes) {
-        extractCodes(item.childNodes, codes);
+  // 把树节点中所有 nodeType = camera 的 name 替换成 name + code
+  function getCameraNameCode(data) {
+    const cameraNameCode = data;
+    for (let i = 0; i < data.length; i++) {
+      const node = cameraNameCode[i];
+      if (node.nodeType === 'camera') {
+        node.name = node.name + ` [${node.code}] `;
       }
       }
-    });
-    return codes;
+      if (node.children && node.children.length > 0) {
+        getCameraNameCode(node.children);
+      }
+    }
+    return cameraNameCode;
   }
   }
 
 
-  const filterNode = (value: string, data: Tree, node) => {
-    if (!value) return true;
-    // 检查当前节点的 label 是否包含关键词
-    const labelMatch = data.name.includes(value);
-
-    if (labelMatch) {
-      if (node.childNodes && node.childNodes.length > 0) {
-        childrenNodeList.value = extractCodes(node.childNodes, []);
+  // 获取当前树结构下总相机code列表
+  function getCameraList(data) {
+    let cameraList = [] as string[];
+    for (let i = 0; i < data.length; i++) {
+      const node = data[i];
+      if (node.nodeType === 'camera') {
+        cameraList.push(node.code);
+      }
+      if (node.children && node.children.length > 0) {
+        const childCameraList = getCameraList(node.children);
+        cameraList.push(...childCameraList);
       }
       }
     }
     }
+    return cameraList;
+  }
 
 
-    if (childrenNodeList.value.includes(data.code)) {
-      return true;
-    } else {
-      return labelMatch;
+  // 更新/获取未进入平台相机数量
+  function updateNetworkingState(data, targetData) {
+    let integrationCount = 0;
+    for (let i = 0; i < data.length; i++) {
+      const node = data[i];
+      const matchedNode = targetData.find((item) => item.cameraCode === node.code);
+      if (matchedNode) {
+        node.networkingState = matchedNode.status;
+        node.integrationState = matchedNode.integrationState;
+      }
+      if (node.integrationState === 1) {
+        integrationCount++;
+      }
+      if (node.children && node.children.length > 0) {
+        const childIntegrationCount = updateNetworkingState(node.children, targetData);
+        integrationCount += childIntegrationCount;
+      }
     }
     }
+    noIntegrationNum.value = integrationCount;
+    return integrationCount;
+  }
+
+  // 输入框回车搜索 + checkbox 搜索
+  const handleSearchCamera = async () => {
+    await getCameraData(queryForm.value);
   };
   };
 
 
-  const isInvalid = (data) => {
-    return data.networkingState !== 0;
+  const getCameraData = async (tempQuery) => {
+    await getCameraTree(tempQuery).then((res) => {
+      cameraTree.value = res;
+      cameraTreeTemp.value = getCameraNameCode(res);
+      codeShowList.value = getCameraList(res);
+      totalNum.value = codeShowList.value.length;
+      openInterval(codeShowList.value, (targetData) => {
+        updateNetworkingState(cameraTree.value, targetData);
+      });
+    });
   };
   };
+
+  onMounted(() => {
+    getCameraData(queryForm.value);
+  });
+
+  onUnmounted(() => {
+    closeInterval();
+  });
 </script>
 </script>
 <style scoped>
 <style scoped>
   .cameraCommon {
   .cameraCommon {
@@ -210,4 +264,8 @@
     right: 2px;
     right: 2px;
     top: -4px;
     top: -4px;
   }
   }
+
+  .nodeSelect {
+    color: #0052d9;
+  }
 </style>
 </style>

+ 1 - 0
src/views/cameras/preview/store/useCameraStatus.ts

@@ -17,6 +17,7 @@ export const useCameraStatus = () => {
   };
   };
 
 
   const openInterval = (codeList, callback) => {
   const openInterval = (codeList, callback) => {
+    clearInterval(interval);
     setTimeout(() => {
     setTimeout(() => {
       getState(codeList, callback);
       getState(codeList, callback);
     }, 500);
     }, 500);