| | |
| | | <template> |
| | | <div style="width: 70vw; height: 500px; background-color: aliceblue"> |
| | | <BaseMap></BaseMap> |
| | | <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></style> |
| | | <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> |