报警照片
85.5%
布控照片本章介绍地图组件的范围点位的图层过滤
<template>
<div style="position: relative; width: 100%; height: 500px; overflow: hidden">
<minemap
ref="mineMapRef"
map-dom-id="build-filter"
:map2D3D="map2D3D"
:map-edit-data="mapEditDataFilter"
:point-build-list="pointBuildListFilter"
:alarm-point-list="alarmPointList"
:get-message-popupBg="getMessagePopupBg"
@closeWarningPopup="closeWarningPopup"
/>
<div class="map-options">
<div class="options-type">
<div>
<i class="iconfont icon-tuceng mr-xs" />
<span class="inline vt-middle">图层</span>
</div>
<div>
<Dropdown trigger="click" transfer @on-click="switchMap">
<i class="iconfont icon-ditu mr-xs" />
<span class="inline vt-middle">地图</span>
<template #list>
<DropdownMenu>
<DropdownItem name="2D">
<i class="iconfont icon-wanggekai mr-xs" />
<span class="inline vt-middle">二维</span>
</DropdownItem>
<DropdownItem name="3D">
<i class="iconfont icon-d mr-xs" />
<span class="inline vt-middle">三维</span>
</DropdownItem>
</DropdownMenu>
</template>
</Dropdown>
</div>
</div>
<div class="options-detail">
<div class="options-content layer" v-show="activeOption === 'layer'">
<div class="layer-border top-left" />
<div class="layer-border top-right" />
<div class="layer-border bottom-left" />
<div class="layer-border bottom-right" />
<div class="all-layer">
<Checkbox
:indeterminate="indeterminate"
:model-value="checkAllLayer"
@on-change="handleCheckAllLayer"
>
<span style="color: #fff">全部图层</span>
</Checkbox>
</div>
<Checkbox
class="option-item"
v-for="(layer, index) in layerTypeList"
:key="index"
v-model="layer.checked"
@on-change="(val) => checkLayerChange(val, layer)"
>
<img class="layer-icon" v-if="layer.icon" :src="layer.icon" />
<span v-else class="layer-sign" :style="{ backgroundColor: layer.color }" />
<span style="color: #fff">{{ layer.layerName }}</span>
</Checkbox>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import minemap from './components/index.vue';
import { deepCopy } from '@web-basic-doc/utils';
import {
mapEditDataMock,
pointBuildListMock,
alarmPointListMock,
layerTypeListMock,
} from './example.mock';
const mineMapRef = ref(null);
let activeOption = ref('layer');
// 全选图层状态
let checkAllLayer = ref(true);
// 全选图层半选状态
let indeterminate = ref(false);
// 地图处于2D还是3D
let map2D3D = ref('3D');
const layerTypeList = reactive(layerTypeListMock);
const mapEditData = mapEditDataMock;
const pointBuildList = pointBuildListMock;
const alarmPointList = ref(alarmPointListMock);
let mapEditDataFilter = ref(deepCopy(mapEditDataMock));
let pointBuildListFilter = ref(deepCopy(pointBuildListMock));
// 转换地图2D3D
const switchMap = (type) => {
map2D3D.value = type;
};
// 全选/取消全选 所有图层分类
const handleCheckAllLayer = (val) => {
mineMapRef.value.messagePopupRef.length = 0;
if (val) {
checkAllLayer.value = true;
indeterminate.value = false;
layerTypeList.forEach((layer) => {
layer.checked = true;
});
// 建筑图层
if (pointBuildList.length) {
pointBuildListFilter.value = deepCopy(pointBuildList);
}
// 编辑池图层
if (map2D3D.value === '3D' && mapEditData.length) {
mapEditDataFilter.value = deepCopy(mapEditData);
mineMapRef.value.addFence(mapEditDataFilter.value);
}
} else {
checkAllLayer.value = false;
indeterminate.value = false;
layerTypeList.forEach((layer) => {
layer.checked = false;
removePrimitiveByLayer(layer);
});
pointBuildListFilter.value = [];
mapEditDataFilter.value = [];
}
if (alarmPointList.value.length) {
checkWarningPopup(val);
}
};
// 点选报警弹框图层
const checkWarningPopup = (val) => {
if (val) {
mineMapRef.value.addAlarmMarker(alarmPointList.value);
} else {
alarmPointList.value.forEach((row) => {
mineMapRef.value.closeWarningPopup(row.id, { isRemove: false });
});
}
};
const closeWarningPopup = (pointId) => {
const index = alarmPointList.value.findIndex((point) => point.id === pointId);
if (index !== -1) {
alarmPointList.value.splice(index, 1);
}
};
const checkLayerChange = (val, layer) => {
if (layer.layerType === 'warningInfo') {
checkWarningPopup(val);
return;
}
// 点选其他图层
mineMapRef.value.messagePopupRef.length = 0;
const checkedLayer = layerTypeList.filter((row) => row.checked);
// 全选的情况下
if (checkedLayer.length === layerTypeList.length) {
indeterminate.value = false;
checkAllLayer.value = true;
pointBuildListFilter.value = deepCopy(pointBuildList);
mapEditDataFilter.value = deepCopy(mapEditData);
// 区域范围
if (map2D3D.value === '3D' && mapEditData.length) {
const addEditList = mapEditData.filter((edit) => edit.kind === layer.layerType);
mineMapRef.value.addFence(addEditList);
}
// 没有全选的情况下
} else if (checkedLayer.length > 0) {
indeterminate.value = true;
checkAllLayer.value = false;
if (val) {
// 建筑点位加载
if (pointBuildList.length) {
pointBuildListFilter.value = pointBuildList.filter(
(point) => checkedLayer.findIndex((row) => row.layerType === point.kind) !== -1,
);
}
// 区域范围
if (mapEditData.length) {
mapEditDataFilter.value = mapEditData.filter(
(edit) => checkedLayer.findIndex((row) => row.layerType === edit.kind) !== -1,
);
if (map2D3D.value === '3D') {
mineMapRef.value.addFence(mapEditDataFilter.value);
}
}
} else {
// 移除点位
if (pointBuildList.length) {
const removePointList = pointBuildListFilter.value.filter(
(point) => point.kind === layer.layerType,
);
removePointList.forEach((removePoint) => {
const pointIndex = pointBuildListFilter.value.findIndex(
(point) => point.id === removePoint.id,
);
pointIndex !== -1 && pointBuildListFilter.value.splice(pointIndex, 1);
});
}
// 移除围栏
removePrimitiveByLayer(layer);
if (mapEditData.length) {
// 移除框选范围
const removeEditList = mapEditDataFilter.value.filter(
(edit) => edit.kind === layer.layerType,
);
removeEditList.forEach((removeEdit) => {
const editIndex = mapEditDataFilter.value.findIndex(
(edit) => edit.id === removeEdit.id,
);
mapEditDataFilter.value.splice(editIndex, 1);
});
}
}
// 全不选的情况下
} else {
indeterminate.value = false;
checkAllLayer.value = false;
removePrimitiveByLayer(layer);
pointBuildListFilter.value = [];
mapEditDataFilter.value = [];
}
};
// 找到对应的围栏的Primitive并移除
const removePrimitiveByLayer = (layer) => {
if (map2D3D.value === '3D' && mapEditData.length) {
const editData = mapEditData.filter((edit) => edit.kind === layer.layerType);
editData.forEach((edit) => {
mineMapRef.value.removePrimitiveById(edit.id);
});
}
};
const getMessagePopupBg = (point) => {
return point.kind;
};
</script>
<style lang="scss" scoped>
.map-options {
position: absolute;
top: 10px;
right: 20px;
z-index: 3;
.options-type {
display: flex;
width: 210px;
height: 30px;
color: #fff;
background-color: rgb(8 86 189 / 40%);
justify-content: space-between;
align-items: center;
> div {
position: relative;
display: flex;
width: 33.33%;
cursor: pointer;
align-items: center;
justify-content: center;
&:hover {
color: #1acbfe;
}
}
}
.options-detail {
position: relative;
margin-top: 15px;
color: #fff;
background-color: transparent;
.layer-border {
position: absolute;
width: 17px;
height: 17px;
&.top-left {
top: -6px;
left: -6px;
border-top: 2px solid #14ccff;
border-left: 2px solid #14ccff;
}
&.top-right {
top: -6px;
right: -6px;
border-top: 2px solid #14ccff;
border-right: 2px solid #14ccff;
}
&.bottom-left {
bottom: -6px;
left: -6px;
border-bottom: 2px solid #14ccff;
border-left: 2px solid #14ccff;
}
&.bottom-right {
right: -6px;
bottom: -6px;
border-right: 2px solid #14ccff;
border-bottom: 2px solid #14ccff;
}
}
.options-content {
background-color: rgb(2 11 44 / 70%);
border: 1px solid #083d7d;
box-shadow: inset 0 0 20px rgb(0 85 255 / 50%);
}
.all-layer {
position: relative;
display: flex;
height: 44px;
padding: 0 15px;
border-bottom: 1px solid rgb(6 128 251 / 40%);
align-items: center;
&::after,
&::before {
position: absolute;
right: 0;
bottom: 0;
display: inline-block;
width: 10px;
height: 1px;
background-color: #0680fb;
content: '';
}
&::before {
left: 0;
}
}
.option-item {
display: flex;
height: 40px;
padding: 0 15px;
align-items: center;
:deep(.ivu-checkbox-label-text) {
display: flex;
justify-content: center;
align-items: center;
}
.layer-sign {
display: inline-block;
width: 26px;
height: 2px;
margin-right: 10px;
margin-left: 5px;
border-radius: 1px;
}
.layer-icon {
width: 26px;
height: 30px;
margin-right: 10px;
margin-left: 5px;
}
}
}
}
</style>
import redFence from '/images/map/minemap/red-fence.png';
import greenFence from '/images/map/minemap/green-fence.png';
import blueFence from '/images/map/minemap/blue-fence.png';
import warningPosition from '/images/map/minemap/warning-position.png';
const mapEditDataMock = [
{
id: 1,
type: 'Feature',
kind: 'red',
properties: {
lineColor: '#F61C35',
fillColor: '#F61C35',
fillOpacity: 0.2,
fillOutlineColor: '#F61C35',
fillOutlineWidth: 2,
isLock: true,
custom_style: 'true',
},
geometry: {
type: 'Polygon',
coordinates: [
[
[120.465828, 32.533069],
[120.468515, 32.534381],
[120.46998, 32.532282],
[120.467324, 32.530908],
[120.465828, 32.533069],
],
],
},
fenceImgUrl: redFence,
},
{
id: 2,
type: 'Feature',
kind: 'green',
properties: {
lineColor: '#49FBD3',
fillColor: '#49FBD3',
fillOpacity: 0.2,
fillOutlineColor: '#49FBD3',
fillOutlineWidth: 2,
isLock: true,
custom_style: 'true',
},
geometry: {
type: 'Polygon',
coordinates: [
[
[120.466307, 32.537685],
[120.469146, 32.539252],
[120.469523, 32.53875],
[120.469523, 32.53875],
[120.471136, 32.538194],
[120.467354, 32.536174],
[120.466307, 32.537685],
],
],
},
fenceImgUrl: greenFence,
},
{
id: 3,
type: 'Feature',
kind: 'blue',
properties: {
lineColor: '#37E5FF',
fillColor: '#37E5FF',
fillOpacity: 0.2,
fillOutlineColor: '#37E5FF',
fillOutlineWidth: 2,
isLock: true,
custom_style: 'true',
},
geometry: {
type: 'Polygon',
coordinates: [
[
[120.46706, 32.556076],
[120.469683, 32.55657],
[120.4713, 32.55479],
[120.467761, 32.554341],
[120.46706, 32.556076],
],
],
},
fenceImgUrl: blueFence,
},
{
id: 4,
type: 'Feature',
kind: 'blue',
properties: {
lineColor: '#37E5FF',
fillColor: '#37E5FF',
fillOpacity: 0.2,
fillOutlineColor: '#37E5FF',
fillOutlineWidth: 2,
isLock: true,
custom_style: 'true',
},
geometry: {
type: 'Polygon',
coordinates: [
[
[120.490838, 32.538595],
[120.491557, 32.538888],
[120.491611, 32.538439],
[120.491103, 32.538237],
[120.490838, 32.538595],
],
],
},
fenceImgUrl: blueFence,
},
{
id: 5,
type: 'Feature',
kind: 'blue',
properties: {
lineColor: '#37E5FF',
fillColor: '#37E5FF',
fillOpacity: 0.2,
fillOutlineColor: '#37E5FF',
fillOutlineWidth: 2,
isLock: true,
custom_style: 'true',
},
geometry: {
type: 'Polygon',
coordinates: [
[
[120.47087, 32.537774],
[120.471112, 32.537877],
[120.471413, 32.537302],
[120.471413, 32.537302],
[120.47087, 32.537774],
],
],
},
fenceImgUrl: blueFence,
},
{
id: 7,
type: 'Feature',
kind: 'red',
properties: {
lineColor: '#F61C35',
fillColor: '#F61C35',
fillOpacity: 0.2,
fillOutlineColor: '#F61C35',
fillOutlineWidth: 2,
isLock: true,
custom_style: 'true',
},
geometry: {
coordinates: [
[
[120.46610539854002, 32.53577955594519],
[120.46610539854002, 32.53107386514961],
[120.47901921613597, 32.53107386514961],
[120.47901921613597, 32.53577955594519],
[120.46610539854002, 32.53577955594519],
],
],
type: 'Polygon',
},
fenceImgUrl: redFence,
},
];
const pointBuildListMock = [
{
id: 1,
title: '海安市政府',
kind: 'red',
lng: 120.467735,
lat: 32.532712,
icon: 'redPoint',
},
{
id: 2,
title: '书香园小区',
kind: 'green',
lng: 120.468946,
lat: 32.537649,
icon: 'greenPoint',
},
{
id: 3,
title: '江苏省海安高级中学',
kind: 'blue',
lng: 120.468851,
lat: 32.555493,
icon: 'bluePoint',
},
{
id: 4,
title: '王府大酒店',
kind: 'blue',
lng: 120.491374,
lat: 32.538508,
icon: 'bluePoint',
},
{
id: 5,
title: '智达教育(海安校区)',
kind: 'blue',
lng: 120.471218,
lat: 32.537631,
icon: 'bluePoint',
},
{
id: 7,
title: '123',
kind: 'red',
lng: 120.472562307338,
lat: 32.5334267105474,
icon: 'redPoint',
},
];
const alarmPointListMock = [
{
lnglat: [120.456101, 32.53736],
id: '1',
title: `一级`,
similarity: 85.5,
alarmLevel: '一级',
name: '陶尚华',
taskLibName: '人脸测试布控库001',
alarmTime: '2023-11-23 09:24:09',
deviceName: 'B_QN1077延安路东南(结构化2)_(一期)',
alarmPicUrl: '/images/map/minemap/default-photo.png',
taskPicUrl: '/images/map/minemap/default-photo.png',
messageType: 'faceAlarms',
},
];
const layerTypeListMock = [
{ layerName: '蓝色图层', layerType: 'blue', color: '#37E5FF', checked: true },
{ layerName: '红色图层', layerType: 'red', color: '#FF7979', checked: true },
{ layerName: '绿色图层', layerType: 'green', color: '#49FBD3', checked: true },
{ layerName: '预警信息', layerType: 'warningInfo', icon: warningPosition, checked: true },
];
export { mapEditDataMock, pointBuildListMock, alarmPointListMock, layerTypeListMock };