Compare commits
2 Commits
920fecc9a7
...
98b9bbce0d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98b9bbce0d | ||
|
|
da63aa8abe |
@@ -20,6 +20,7 @@ interface State {
|
||||
eventDuration: number;
|
||||
realData: []; //实时数据
|
||||
iframeLoad: boolean;
|
||||
showMap: boolean;
|
||||
}
|
||||
|
||||
// 初始状态
|
||||
@@ -37,13 +38,14 @@ const state: State = {
|
||||
eventValue: 0.7,
|
||||
eventDuration: 5,
|
||||
realData: [], //实时数据
|
||||
iframeLoad: false,
|
||||
iframeLoad: false,//无锡接线图是否加载完成
|
||||
showMap: true,//无锡地图显示
|
||||
};
|
||||
|
||||
// 定义Mutation类型
|
||||
enum Mutations {
|
||||
INCREMENT = "INCREMENT",
|
||||
IFRAMELOAD = "IFRAMELOAD",
|
||||
SET_STATE= "SET_STATE",
|
||||
SET_TOKEN = "SET_TOKEN",
|
||||
SET_TIME = "SET-TIME",
|
||||
SET_CONFIG = "SET-CONFIG-TIME",
|
||||
@@ -55,8 +57,9 @@ export default createStore({
|
||||
[Mutations.INCREMENT](state: State) {
|
||||
state.count++;
|
||||
},
|
||||
[Mutations.IFRAMELOAD](state: State, data: boolean) {
|
||||
state.iframeLoad = data;
|
||||
[Mutations.SET_STATE](state: State, data: any) {
|
||||
console.log("🚀 ~ data:", data)
|
||||
state[data.key] = data.value;
|
||||
},
|
||||
[Mutations.SET_TOKEN](state: State, data: any) {
|
||||
window.sessionStorage.setItem("token", data.token);
|
||||
@@ -103,8 +106,8 @@ export default createStore({
|
||||
increment({ commit }) {
|
||||
commit(Mutations.INCREMENT);
|
||||
},
|
||||
setIframeLoad({ commit }, data: any) {
|
||||
commit(Mutations.IFRAMELOAD,data);
|
||||
setStateKey({ commit }, data: any) {
|
||||
commit(Mutations.SET_STATE,data);
|
||||
},
|
||||
setTimeType({ commit }, data: any) {
|
||||
commit(Mutations.SET_TIME, data);
|
||||
|
||||
472
src/views/SagTraceResult_WX/components/bdMap.vue
Normal file
472
src/views/SagTraceResult_WX/components/bdMap.vue
Normal file
@@ -0,0 +1,472 @@
|
||||
<template>
|
||||
<div v-loading="loading" element-loading-background="#343849c7">
|
||||
<div class="iconBox">
|
||||
<div class="div">
|
||||
<img src="@/assets/jcd.png" alt="" />
|
||||
<span>变电站</span>
|
||||
</div>
|
||||
|
||||
<div class="div">
|
||||
<img src="@/assets/txycyzj.gif" alt="" />
|
||||
<span>暂降监测点</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bmSelect">
|
||||
<el-select
|
||||
v-model="value"
|
||||
@change="setIcon"
|
||||
placeholder="变电站筛选"
|
||||
filterable
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in siteList"
|
||||
:key="item.stationName"
|
||||
:label="item.stationName"
|
||||
:value="item.stationName"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<baidu-map
|
||||
ref="mapRef"
|
||||
class="bm-view"
|
||||
:max-zoom="15"
|
||||
:min-zoom="10"
|
||||
:zoom="zoom"
|
||||
@zoomend="syncCenterAndZoom"
|
||||
@moveend="checkMapData"
|
||||
@ready="handler"
|
||||
:center="center"
|
||||
:scroll-wheel-zoom="false"
|
||||
:double-click-zoom="false"
|
||||
>
|
||||
<!-- 线-->
|
||||
<div v-if="zoom > 13">
|
||||
<bm-polyline
|
||||
:path="path"
|
||||
v-for="(path, index) in polyline"
|
||||
:key="index"
|
||||
></bm-polyline>
|
||||
</div>
|
||||
|
||||
<!-- 变电站-->
|
||||
<template v-if="zoom > 13">
|
||||
<bm-marker
|
||||
:position="path"
|
||||
v-for="path in siteList"
|
||||
:key="path.subId"
|
||||
:icon="path.icon"
|
||||
@click="markerClick(path)"
|
||||
></bm-marker>
|
||||
</template>
|
||||
<!-- 点 -->
|
||||
<div maxZoom="12">
|
||||
<bm-marker
|
||||
:position="path"
|
||||
v-for="path in areaLineInfo"
|
||||
:key="path.lineId"
|
||||
:icon="path.icon"
|
||||
@click="markerClick(path)"
|
||||
></bm-marker>
|
||||
</div>
|
||||
<bm-marker
|
||||
:position="infoWindowPoint"
|
||||
:icon="{ url: '1', size: { width: 0, height: 0 } }"
|
||||
>
|
||||
<bm-info-window
|
||||
:show="infoWindowPoint.show"
|
||||
@close="infoWindowPoint.show = false"
|
||||
>
|
||||
<el-descriptions
|
||||
:title="infoWindowPoint.lineName"
|
||||
style="min-width: 250px"
|
||||
:column="1"
|
||||
border
|
||||
v-if="infoWindowPoint.lineId"
|
||||
label-width="90px"
|
||||
>
|
||||
<el-descriptions-item label="供电区域">{{
|
||||
infoWindowPoint.gdName
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="上级电站">{{
|
||||
infoWindowPoint.stationName
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="上级母线">{{
|
||||
infoWindowPoint.busBarName
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="暂降次数">{{
|
||||
infoWindowPoint.eventCount
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="用户"
|
||||
v-if="infoWindowPoint.objName == null"
|
||||
>/</el-descriptions-item
|
||||
>
|
||||
<template v-else>
|
||||
<el-descriptions-item label="用户">
|
||||
<div class="descriptionsBox">
|
||||
<div
|
||||
v-for="(value, index) in infoWindowPoint.objName.split(
|
||||
';'
|
||||
)"
|
||||
style="white-space: nowrap"
|
||||
>
|
||||
{{ value }}
|
||||
</div>
|
||||
</div></el-descriptions-item
|
||||
>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
<el-descriptions
|
||||
:title="infoWindowPoint.stationName"
|
||||
:column="1"
|
||||
v-else
|
||||
style="min-width: 250px"
|
||||
border
|
||||
>
|
||||
<!-- <el-descriptions-item
|
||||
:label="index == 0 ? '母线' : ''"
|
||||
v-for="(value, index) in infoWindowPoint.lineEventDetails"
|
||||
>
|
||||
{{ value.busBarName + `-` + value.lineName }}
|
||||
</el-descriptions-item> -->
|
||||
|
||||
<el-descriptions-item label="母线"
|
||||
><div class="descriptionsBox">
|
||||
<div
|
||||
v-for="(value, index) in infoWindowPoint.lineEventDetails"
|
||||
style="white-space: nowrap"
|
||||
>
|
||||
{{ value.busBarName + `-` + value.lineName }}
|
||||
</div>
|
||||
</div></el-descriptions-item
|
||||
>
|
||||
|
||||
<el-descriptions-item label="暂降次数">{{
|
||||
infoWindowPoint.eventCount
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</bm-info-window>
|
||||
</bm-marker>
|
||||
</baidu-map>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from "vue";
|
||||
import { substationCount } from "@/api/statistics/index";
|
||||
import { useStore } from "vuex";
|
||||
// import { BmlMarkerClusterer } from "vue-baidu-map-3x";
|
||||
const store = useStore();
|
||||
const mapRef = ref<any>(null); // 地图容器的ref
|
||||
const mapInstance: any = ref(null); // 百度地图实例
|
||||
const BMapInstance: any = ref(null); // BMap对象
|
||||
const loading = ref(false);
|
||||
const dataList: any = ref([]);
|
||||
const polyline = ref<any>([]);
|
||||
const zoom = ref(11);
|
||||
const areaLineInfo = ref<any>([]);
|
||||
const siteList = ref<any>([]);
|
||||
const infoWindowPoint = ref<any>({
|
||||
lng: 0,
|
||||
lat: 0,
|
||||
show: false,
|
||||
});
|
||||
const center = ref({
|
||||
lng: 120.12,
|
||||
lat: 31.55,
|
||||
});
|
||||
const value = ref("");
|
||||
const handler = async ({ BMap, map }: any) => {
|
||||
if (!BMap.MarkerClusterer) {
|
||||
// await import("/offline/libs/MarkerClusterer_min.js");
|
||||
}
|
||||
mapInstance.value = map;
|
||||
BMapInstance.value = BMap;
|
||||
|
||||
// 监听地图容器的鼠标滚轮事件
|
||||
const mapDom = mapRef.value.$el; // 获取地图DOM元素
|
||||
mapDom.addEventListener("mousewheel", handleMapWheel, { passive: false });
|
||||
};
|
||||
|
||||
// 点击变电站\监测点
|
||||
const markerClick = (e: any) => {
|
||||
zoom.value = 15;
|
||||
infoWindowPoint.value = e;
|
||||
infoWindowPoint.value.show = true;
|
||||
center.value.lng = 116.404367;
|
||||
center.value.lat = 39.915421;
|
||||
|
||||
setTimeout(() => {
|
||||
center.value.lng = e.lng;
|
||||
center.value.lat = e.lat + 0.01;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
loading.value = true;
|
||||
siteList.value = [];
|
||||
polyline.value = [];
|
||||
dataList.value = [];
|
||||
areaLineInfo.value = [];
|
||||
substationCount({
|
||||
deptId: store.state.deptId,
|
||||
type: store.state.timeType,
|
||||
startTime: store.state.timeValue[0],
|
||||
endTime: store.state.timeValue[1],
|
||||
}).then((res: any) => {
|
||||
dataList.value = res.data;
|
||||
let data = dataList.value;
|
||||
let r = 0.0035;
|
||||
let list = data.filter((item: any) => item.latitude != 0);
|
||||
list.forEach((item: any) => {
|
||||
// 变电站图标
|
||||
item.icon = {
|
||||
url: new URL("@/assets/jcd.png", import.meta.url).href,
|
||||
size: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
},
|
||||
};
|
||||
if (
|
||||
item.lineEventDetails?.length > 10 &&
|
||||
item.lineEventDetails?.length < 100
|
||||
) {
|
||||
r = 0.0055;
|
||||
} else if (item.lineEventDetails.length >= 100) {
|
||||
r = 0.01055;
|
||||
}
|
||||
item.lng = item.longitude;
|
||||
item.lat = item.latitude;
|
||||
item.lineEventDetails.forEach((val: any, i: number) => {
|
||||
val.lng =
|
||||
item.longitude +
|
||||
r * Math.cos((2 * Math.PI * i) / item.lineEventDetails.length);
|
||||
val.lat =
|
||||
item.latitude +
|
||||
r * Math.sin((2 * Math.PI * i) / item.lineEventDetails.length);
|
||||
// 监测点图标
|
||||
val.icon = {
|
||||
url: "",
|
||||
size: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
},
|
||||
};
|
||||
|
||||
val.icon.url = new URL("@/assets/txycyzj.gif", import.meta.url).href;
|
||||
polyline.value.push([
|
||||
{
|
||||
lng: item.lng,
|
||||
lat: item.lat,
|
||||
},
|
||||
{
|
||||
lng: val.lng,
|
||||
lat: val.lat,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
areaLineInfo.value.push(...item.lineEventDetails);
|
||||
});
|
||||
|
||||
siteList.value = list;
|
||||
|
||||
zoom.value = 12;
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
const moveenFlag = ref(true);
|
||||
|
||||
const checkMapData = () => {
|
||||
if (!mapInstance.value || !BMapInstance.value || !moveenFlag.value) return;
|
||||
|
||||
// 获取地图容器
|
||||
const container = mapInstance.value.getContainer();
|
||||
|
||||
setTimeout(() => {
|
||||
try {
|
||||
// 1. 获取所有图片瓦片
|
||||
const tiles = Array.from(container.querySelectorAll("img"));
|
||||
|
||||
// 2. 检查是否有离线地图瓦片
|
||||
const hasOfflineTiles = tiles.some((tile: any) => {
|
||||
// 确保tile是有效的DOM元素
|
||||
if (!tile || !tile.src) return false;
|
||||
|
||||
// 检查是否是离线瓦片
|
||||
return tile.src.includes("/plugin/offline/tiles/");
|
||||
});
|
||||
|
||||
// 3. 如果没有离线瓦片,回到默认位置
|
||||
if (!hasOfflineTiles) {
|
||||
console.warn("当前区域无离线地图数据,将返回默认位置");
|
||||
|
||||
// 使用正确的BMap.Point创建方式
|
||||
const point = new BMapInstance.value.Point(116.404367, 39.915421);
|
||||
|
||||
// 平滑移动并设置合适缩放级别
|
||||
mapInstance.value.panTo(point);
|
||||
mapInstance.value.setZoom(12);
|
||||
// zoom.value = 12;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("地图检测出错:", error);
|
||||
}
|
||||
}, 1000); // 适当缩短延迟时间
|
||||
};
|
||||
|
||||
// 处理地图滚轮缩放,修正scale导致的坐标偏移
|
||||
const handleMapWheel = (e: WheelEvent) => {
|
||||
e.preventDefault();
|
||||
if (!mapInstance.value || !BMapInstance.value) return;
|
||||
|
||||
// 1. 获取当前缩放比例(假设你通过scale变量控制,需替换为你的实际scale值)
|
||||
const scaleWidth: any = window.sessionStorage.getItem("scaleWidth"); // 你的水平缩放比例
|
||||
const scaleHeight: any = window.sessionStorage.getItem("scaleheight"); // 你的垂直缩放比例
|
||||
|
||||
// 2. 获取地图容器的位置和尺寸(原始DOM尺寸,未被scale影响)
|
||||
const rect = mapRef.value.$el.getBoundingClientRect();
|
||||
|
||||
// 3. 计算鼠标在地图容器内的原始坐标(未修正)
|
||||
const mouseXRaw = e.clientX - rect.left;
|
||||
const mouseYRaw = e.clientY - rect.top;
|
||||
|
||||
// 4. 修正坐标:除以缩放比例,得到scale前的原始坐标(地图实际识别的坐标)
|
||||
const mouseX = mouseXRaw / scaleWidth;
|
||||
const mouseY = mouseYRaw / scaleHeight;
|
||||
|
||||
// 5. 将修正后的坐标转换为百度地图的经纬度
|
||||
const point = new BMapInstance.value.Pixel(mouseX, mouseY);
|
||||
const lngLat = mapInstance.value.pixelToPoint(point); // 像素坐标转经纬度
|
||||
|
||||
// 6. 执行缩放(滚轮向上放大,向下缩小)
|
||||
const zoomDelta = e.deltaY < 0 ? 1 : -1; // 滚轮方向
|
||||
const newZoom = mapInstance.value.getZoom() + zoomDelta;
|
||||
if (newZoom < 10 || newZoom > 15) return; // 限制缩放范围(百度地图默认范围)
|
||||
|
||||
// 7. 缩放时保持鼠标指向的位置不变(核心:先缩放再移中心点)
|
||||
mapInstance.value.setZoom(newZoom);
|
||||
mapInstance.value.setCenter(lngLat); // 让鼠标指向的位置成为新中心
|
||||
};
|
||||
const syncCenterAndZoom = (e: any) => {
|
||||
zoom.value = e.target.getZoom();
|
||||
checkMapData();
|
||||
};
|
||||
//点击过滤位置
|
||||
const setIcon = (e: string) => {
|
||||
moveenFlag.value = false;
|
||||
siteList.value.forEach((item: any) => {
|
||||
if (item.stationName == e) {
|
||||
// center.value.lng = item.lng;
|
||||
// center.value.lat = item.lat + 0.01;
|
||||
infoWindowPoint.value = item;
|
||||
infoWindowPoint.value.show = true;
|
||||
zoom.value = 15;
|
||||
}
|
||||
});
|
||||
setTimeout(() => {
|
||||
moveenFlag.value = true;
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
setIcon,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@use "@/assets/scss/index.scss";
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 600px;
|
||||
}
|
||||
.bm-view {
|
||||
width: 99%;
|
||||
height: 980px;
|
||||
}
|
||||
.iconBox {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
z-index: 2000;
|
||||
width: 110px;
|
||||
height: 70px;
|
||||
padding: 10px;
|
||||
background: #ffffff10 !important;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
|
||||
font-size: 12px;
|
||||
|
||||
.div {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
|
||||
img {
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-descriptions__title) {
|
||||
color: #fff;
|
||||
}
|
||||
:deep(.el-descriptions__content) {
|
||||
color: #fff;
|
||||
// width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions__body) {
|
||||
color: #fff;
|
||||
background-color: rgb(0 0 0 / 0%) !important;
|
||||
}
|
||||
:deep(.el-descriptions__label) {
|
||||
color: #fff;
|
||||
// display: inline-block;
|
||||
width: 80px;
|
||||
text-align: right; /* 右对齐 */
|
||||
}
|
||||
:deep(.BMap_pop .BMap_center) {
|
||||
background-color: #343849c7;
|
||||
}
|
||||
.descriptionsBox {
|
||||
max-height: 100px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.BMap_cpyCtrl {
|
||||
display: none;
|
||||
}
|
||||
.anchorBL {
|
||||
display: none;
|
||||
} /* 地图容器样式 */
|
||||
.baidu-map-container {
|
||||
/* 消除可能的缝隙 */
|
||||
line-height: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
/* .BMap_pop div {
|
||||
background-color: #343849c7 !important;
|
||||
} */
|
||||
|
||||
.bmSelect {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
z-index: 2000;
|
||||
}
|
||||
.bm-view {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
@@ -1,14 +1,10 @@
|
||||
<template>
|
||||
<div class="plan">
|
||||
<!-- src=" http://192.168.1.128:3001/zutai/?id=44368e72a2e594d14ebaf317f0f6ad00&&name=decodeURI(APP测试项目)&&flag=true&&wxqr=true#/" -->
|
||||
<!-- <iframe
|
||||
src="http://192.168.1.62:8088/zutai/?id=0944fe372e90daeefd040916a105ac8b&&name=测试组态编辑器&&preview=true#/preview"
|
||||
width="100%"
|
||||
height="100%"
|
||||
frameborder="0"
|
||||
></iframe> -->
|
||||
<bdMap v-show="store.state.showMap" width="100%" height="100%"></bdMap>
|
||||
|
||||
<!-- 添加加载事件监听 -->
|
||||
<iframe
|
||||
v-if="!store.state.showMap"
|
||||
:src="iframeSrc"
|
||||
width="100%"
|
||||
height="100%"
|
||||
@@ -23,6 +19,7 @@
|
||||
import { ref, watch, onMounted, onUnmounted } from "vue";
|
||||
import { getActive } from "@/api/manage_wx/index";
|
||||
import { useStore } from "vuex";
|
||||
import bdMap from "./bdMap.vue";
|
||||
const store = useStore();
|
||||
const props = defineProps<{
|
||||
project: { id: string; name: string } | null;
|
||||
@@ -50,6 +47,7 @@ watch(
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// store.dispatch("setStateKey", { key: "showMap", value: false });
|
||||
// 监听来自 eventStatistics 组件的消息
|
||||
window.addEventListener("message", handleMessage);
|
||||
getActive({}).then((res: any) => {
|
||||
@@ -65,12 +63,13 @@ onMounted(() => {
|
||||
});
|
||||
// 子页面
|
||||
const iframe = document.getElementById("iframeLeft");
|
||||
|
||||
// 监听 iframe 加载完成事件
|
||||
iframe.addEventListener("load", function () {
|
||||
// 通知父页面:我已加载完毕
|
||||
store.dispatch("setIframeLoad", true);
|
||||
});
|
||||
if (iframe) {
|
||||
// 监听 iframe 加载完成事件
|
||||
iframe.addEventListener("load", function () {
|
||||
// 通知父页面:我已加载完毕
|
||||
store.dispatch("setStateKey", { key: "iframeLoad", value: true });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user