<template>
|
<BaseMap></BaseMap>
|
<div class="wrap p-events-none">
|
<el-row class="p-events-none top-left-wrap">
|
<FYOptionScene
|
class="p-events-auto"
|
label=""
|
:allOption="true"
|
:type="2"
|
v-model:value="scenetype"
|
></FYOptionScene>
|
<div class="p-events-auto">
|
<slot name="left-top"></slot>
|
</div>
|
</el-row>
|
<el-row
|
class="p-events-none bottom-left-wrap"
|
align="middle"
|
:style="leftCardWrapStyle"
|
>
|
<div class="card-left" ref="refLeftCard">
|
<div v-show="leftCardShow" class="p-events-auto">
|
<el-row ref="refLeftCardTitle" class="p-8" justify="space-between">
|
<el-text size="large">场景列表</el-text>
|
<el-input
|
v-model="filterText"
|
icon="Search"
|
style="width: 250px"
|
placeholder="输入关键字,按回车键搜索"
|
clearable
|
/>
|
<!-- <el-badge
|
ref="sampleBadgeRef"
|
:value="1"
|
type="success"
|
:offset="[-2, 2]"
|
>
|
<img
|
style="width: 30px; height: 30px"
|
:src="sceneIcon(1)"
|
alt="工地"
|
/>
|
<template #content="{ value }">
|
<div class="custom-content">
|
<el-icon :size="8"><Select /></el-icon>
|
</div>
|
</template>
|
</el-badge> -->
|
</el-row>
|
<el-scrollbar :height="scrollHeight" class="scrollbar">
|
<el-row
|
v-for="s in filteredSceneList"
|
:key="s.guid"
|
justify="space-between"
|
class="p-v-4 scene-item"
|
>
|
<el-text truncated style="width: 100%">
|
{{ s.index + '. ' + s.name }}
|
</el-text>
|
<el-row justify="space-between" style="margin-top: 4px">
|
<el-space>
|
<el-tag type="info" effect="plain" size="small">
|
{{ s.type }}
|
</el-tag>
|
<el-tag
|
:type="s.extension1 == '0' ? 'info' : 'success'"
|
size="small"
|
>
|
{{ onlineFormat(s.extension1) }}
|
</el-tag>
|
</el-space>
|
</el-row>
|
<el-space>
|
<el-icon
|
class="cursor-p"
|
:color="
|
s._checked ? 'rgb(121, 187, 255)' : 'rgb(200, 201, 204)'
|
"
|
@click="locateTo(s)"
|
>
|
<LocationInformation />
|
</el-icon>
|
<el-icon
|
class="cursor-p"
|
:color="
|
s._visible ? 'rgb(121, 187, 255)' : 'rgb(200, 201, 204)'
|
"
|
@click="handleVisibleChange(s)"
|
>
|
<View />
|
</el-icon>
|
</el-space>
|
</el-row>
|
</el-scrollbar>
|
</div>
|
</div>
|
<el-button
|
class="close-btn-right p-events-auto"
|
type="success"
|
size="small"
|
:icon="leftCardShow ? 'ArrowLeft' : 'ArrowRight'"
|
@click="leftCardShow = !leftCardShow"
|
></el-button>
|
</el-row>
|
</div>
|
</template>
|
<script setup>
|
import { ref, watch, computed, onMounted } from 'vue';
|
import { map, onMapMounted } from '@/utils/map/index';
|
import marks from '@/utils/map/marks';
|
import mapUtil from '@/utils/map/util';
|
import { sceneIcon } from '@/assets/scene-icon';
|
|
const startHtml = `<div class="el-badge">`;
|
const endHtml = `<sup
|
class="el-badge__content el-badge__content--success is-fixed"
|
style="margin-top: 2px; margin-right: 2px"
|
>
|
<div class="custom-content">
|
<i class="el-icon" style="font-size: 8px">
|
<svg
|
xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 1024 1024"
|
>
|
<path
|
fill="currentColor"
|
d="M77.248 415.04a64 64 0 0 1 90.496 0l226.304 226.304L846.528 188.8a64 64 0 1 1 90.56 90.496l-543.04 543.04-316.8-316.8a64 64 0 0 1 0-90.496"
|
></path>
|
</svg>
|
</i>
|
</div>
|
</sup>
|
</div>`;
|
//
|
const markContentHtml = (sceneType, checked) => {
|
const imgHtml = `<img
|
style="width: 30px; height: 30px"
|
src="${sceneIcon(sceneType)}"
|
/>`;
|
if (checked) {
|
return startHtml + imgHtml + endHtml;
|
} else {
|
return imgHtml;
|
}
|
};
|
|
const props = defineProps({
|
// 选中的场景
|
modelValue: {
|
type: Array,
|
default: () => []
|
},
|
// 场景点位信息
|
data: Array
|
});
|
|
const emits = defineEmits(['update:modelValue']);
|
|
onMounted(() => {
|
setTimeout(() => {
|
scrollHeight.value =
|
refLeftCard.value.offsetHeight -
|
refLeftCardTitle.value.offsetHeight +
|
'px';
|
}, 500);
|
});
|
|
const refLeftCard = ref();
|
const refLeftCardTitle = ref();
|
|
const leftCardShow = ref(true);
|
const leftCardWrapStyle = ref();
|
const scrollHeight = ref('400px');
|
|
let allMarkViews = [];
|
let markViewList = [];
|
|
const scenetype = ref();
|
|
// 选中的场景
|
const selectedSceneList = ref(props.modelValue);
|
|
const allSceneList = computed(() => props.data);
|
const filterText = ref('');
|
// 根据场景类型筛选场景列表
|
const filteredSceneList = computed(() => {
|
return allSceneList.value.filter((v) => {
|
v._visible = true;
|
return (
|
(scenetype.value == undefined ||
|
scenetype.value.value == null ||
|
v.typeid + '' == scenetype.value.value) &&
|
(v.name.indexOf(filterText.value) != -1 ||
|
v.index + '' == filterText.value)
|
);
|
});
|
});
|
|
watch(
|
() => props.data,
|
(nV, oV) => {
|
if (nV != oV) {
|
createSceneMarks();
|
filterMarkViews(true);
|
}
|
},
|
{ immediate: true }
|
);
|
|
watch(scenetype, (nV, oV) => {
|
if (nV != oV) {
|
filterMarkViews(true);
|
}
|
});
|
|
// 监听外部选中或移除场景变化
|
watch(
|
() => props.modelValue,
|
(nV, oV) => {
|
if (nV != oV) {
|
// 外部选中场景变化时,更新内部选中场景列表
|
selectedSceneList.value = nV;
|
// 外部选中场景变化时,更新地图标注内容
|
allMarkViews.forEach((mv) => {
|
const scene = mv.getExtData();
|
const findOne = selectedSceneList.value.some((s) => {
|
return s.guid == scene.guid;
|
});
|
if (findOne) {
|
changeSceneMark(mv, true);
|
} else {
|
changeSceneMark(mv, false);
|
}
|
});
|
}
|
}
|
);
|
|
function handleVisibleChange(scene) {
|
const mv = markViewList.find((v) => {
|
return scene.guid == v.getExtData().guid;
|
});
|
scene._visible = !scene._visible;
|
if (scene._visible) {
|
map.add(mv);
|
} else {
|
map.remove(mv);
|
}
|
}
|
|
function locateTo(scene) {
|
const mv = markViewList.find((v) => {
|
return scene.guid == v.getExtData().guid;
|
});
|
if (mv) {
|
// mapUtil.setFitView(mv);
|
mapUtil.setCenter(mv.getPosition());
|
}
|
}
|
|
// 创建场景地图标注,添加鼠标事件和点击事件
|
function createSceneMarks() {
|
onMapMounted(() => {
|
allMarkViews = [];
|
props.data.forEach((d) => {
|
// 创建场景地图标注
|
const mark = marks.createMarker({
|
position: [d.longitude, d.latitude],
|
// img: sceneIcon(d.typeid),
|
content: markContentHtml(d.typeid),
|
label: d.index,
|
title: d.name,
|
extData: d
|
});
|
// 鼠标事件
|
// onMouseOverListener(mark);
|
onClickListener(mark);
|
|
allMarkViews.push(mark);
|
});
|
});
|
}
|
|
/**
|
* 筛选所选类型的场景
|
*/
|
function filterMarkViews(setFitView) {
|
onMapMounted(() => {
|
if (markViewList.length > 0) {
|
map.remove(markViewList);
|
}
|
// 1. 筛选场景类型
|
if (scenetype.value == undefined) {
|
markViewList = allMarkViews;
|
} else {
|
markViewList = allMarkViews.filter((v) => {
|
return (
|
scenetype.value.value == null ||
|
v.getExtData().typeid + '' == scenetype.value.value
|
);
|
});
|
}
|
map.add(markViewList);
|
if (setFitView) {
|
setTimeout(() => {
|
map.setFitView(markViewList);
|
}, 1000);
|
}
|
});
|
}
|
|
function onlineFormat(s) {
|
if (s == '0') {
|
return '下线';
|
} else {
|
return '上线';
|
}
|
}
|
|
/** 地图场景标记鼠标事件 *********************************************/
|
const onMouseOverListener = (mark) => {
|
let timeout;
|
// 添加点击事件
|
mark.on('mouseover', (ev) => {
|
if (timeout) {
|
clearTimeout(timeout);
|
}
|
const _mark = ev.target;
|
const _extData = _mark.getExtData();
|
_mark.setLabel({
|
content: _extData.name
|
});
|
timeout = setTimeout(() => {
|
_mark.setLabel({
|
content: ''
|
});
|
}, 2000);
|
});
|
};
|
const onClickListener = (mark) => {
|
mark.on('click', (ev) => {
|
const _mark = ev.target;
|
const extData = _mark.getExtData();
|
const index = selectedSceneList.value.indexOf(extData);
|
if (index == -1) {
|
selectedSceneList.value.push(extData);
|
changeSceneMark(_mark, true);
|
} else {
|
selectedSceneList.value.splice(index, 1);
|
changeSceneMark(_mark, false);
|
}
|
emits('update:modelValue', selectedSceneList.value);
|
});
|
};
|
/********************************************************************/
|
|
/**
|
* 根据选中状态修改地图标记的样式
|
* @param {AMap.Marker} mark 地图标记
|
* @param checked
|
*/
|
function changeSceneMark(mark, checked) {
|
const scene = mark.getExtData();
|
if (checked && !scene._checked) {
|
scene._checked = true;
|
mark.setContent(markContentHtml(scene.typeid, true));
|
} else if (!checked && scene._checked) {
|
scene._checked = false;
|
mark.setContent(markContentHtml(scene.typeid, false));
|
}
|
}
|
</script>
|
<style scoped>
|
.wrap {
|
position: absolute;
|
left: 0px;
|
top: 0;
|
width: 100%;
|
height: 100%;
|
}
|
.top-left-wrap {
|
position: absolute;
|
left: 0px;
|
top: 1px;
|
}
|
.bottom-left-wrap {
|
position: absolute;
|
left: 0px;
|
bottom: 1px;
|
}
|
|
.card-left {
|
background-color: rgba(255, 255, 255, 0.8);
|
border-radius: 4px;
|
/* width: 350px; */
|
height: 50vh;
|
box-shadow: var(--el-box-shadow);
|
z-index: 0;
|
/* padding: 8px; */
|
}
|
|
.scrollbar {
|
padding-right: 8px;
|
width: 350px;
|
}
|
|
.close-btn-right {
|
/* margin-left: -3px; */
|
height: 60px;
|
width: 20px;
|
}
|
|
.p-events-auto {
|
pointer-events: auto;
|
}
|
|
.p-events-none {
|
pointer-events: none;
|
}
|
|
.scene-item {
|
/* background-color: aliceblue; */
|
padding: 8px;
|
border-radius: 8px;
|
border: 1px solid var(--el-border-color);
|
box-shadow: var(--el-box-shadow-lighter);
|
margin-bottom: 6px;
|
}
|
|
.custom-content {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
</style>
|