|
@@ -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>
|