diff --git a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeVector/index.vue b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeVector/index.vue index b4a65acb..53ea4cae 100644 --- a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeVector/index.vue +++ b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeVector/index.vue @@ -28,20 +28,13 @@ export default { }, created() { this.activeIcon = window.showStakeText ? 'Vector' : null; - if(Vue.prototype.isMapStatck && Vue.prototype.mapIns && Vue.prototype.mapInsOpenLayers && Vue.prototype.mapInsOpenLayers.length > 0){ - for(let i of Vue.prototype.mapInsOpenLayers){ - Vue.prototype.mapIns.pileIsShow(i, Vue.prototype.isMapStatck); - } - } - // Vue.prototype.mapIns.pileIsShow("jhlayers", false); + Vue.prototype.mapIns.pileIsShow("jhlayers", false); }, methods: { handleClick(type) { this.activeIcon = this.activeIcon === type ? null : type; Vue.prototype.isMapStatck = (this.activeIcon === type); - for(let i of Vue.prototype.mapInsOpenLayers){ - Vue.prototype.mapIns.pileIsShow(i, (this.activeIcon === type)); - } + Vue.prototype.mapIns.pileIsShow("jhlayers", (this.activeIcon === type)); if (this.activeIcon) window.showStakeText = true; else window.showStakeText = false; // markerClusterIns.setData(); @@ -58,7 +51,6 @@ div.el-popper.global-input-search-popover { padding-top: 36px; transform: translateY(24px); // margin-top: 6vh; - .body { .title { background: linear-gradient(90deg, @@ -104,4 +96,4 @@ div.el-popper.global-input-search-popover { background: linear-gradient(180deg, #005c79 0%, #009bcc 100%); } } - + \ No newline at end of file diff --git a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/buttonEvent.js b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/buttonEvent.js index 95dcb71d..3e05fe10 100644 --- a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/buttonEvent.js +++ b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/buttonEvent.js @@ -124,7 +124,6 @@ export const DeviceForMap = { }; export const lngLatMap = {}; //优化 缩略图 + 地图 复用lngLatmap - // 根据选中事件获取所在的响应类型对象 export function getHandleDeviceType(item) { if (DeviceForMap[item.title]) return "地图路测设备/map"; @@ -180,7 +179,6 @@ export const eventMap = { // 设备 需要在地图显示的 async "地图路测设备/map"(item, filterData, isDefault, cb) { const config = DeviceForMap[item.title]; - let loadingMessage; if (!isDefault) { loadingMessage = Message.info({ @@ -222,16 +220,14 @@ export const eventMap = { "font-size:15px; background:#83c806; color:#c7ff4a;", removeData ); - const layerId = 'jhlayer1'+config.deviceType; - addDataPreHandle(removeData); - markerClusterIns.addData(layerId,removeData, isDefault); + markerClusterIns.addData(removeData, isDefault); this.emitter.emit("selectedCompleted", item); cacheRemoveFunc[`地图路测设备/${item.title}`] = () => { cbCall(); removeDataPreHandle(removeData); - markerClusterIns.removeData(layerId,removeData); + markerClusterIns.removeData(removeData); }; }, "地图路测设备/map_close"(item) { @@ -284,18 +280,15 @@ export const eventMap = { isDefault ) ); - - const layerId = 'jhlayer2'+deviceType; - addDataPreHandle(removeData); - markerClusterIns.addData(layerId,removeData, isDefault); + markerClusterIns.addData(removeData, isDefault); this.emitter.emit("selectedCompleted", item); cacheRemoveFunc[`地图事件专题/${item.title}`] = () => { cbCall(); removeDataPreHandle(removeData); - markerClusterIns.removeData(layerId,removeData); + markerClusterIns.removeData(removeData); }; }, "地图事件专题/map_close"(item) { @@ -356,16 +349,14 @@ export const eventMap = { isDefault ) ); - const layerId = 'jhlayer3'+deviceType; - addDataPreHandle(removeData); - markerClusterIns.addData(layerId,removeData, isDefault); + markerClusterIns.addData(removeData, isDefault); this.emitter.emit("selectedCompleted", item); cacheRemoveFunc[`路网设施/${item.title}`] = () => { cbCall(); removeDataPreHandle(removeData); - markerClusterIns.removeData(layerId,removeData); + markerClusterIns.removeData(removeData); }; }, "路网设施/map_close"(item) { @@ -413,9 +404,7 @@ export const eventMap = { ); addDataPreHandle(removeData); - const layerId = 'jhlayer4gzsj'; - - markerClusterIns.addData(layerId,removeData, isDefault); + markerClusterIns.addData(removeData, isDefault); this.emitter.emit("selectedCompleted", item); loadingMessage?.close(); @@ -431,7 +420,7 @@ export const eventMap = { this.emitter.emit("updateDialogVisible", false); } else cbCall(); //非误报执行,需更新选中事件集合 removeDataPreHandle(handleData); - markerClusterIns.removeData(layerId,handleData); + markerClusterIns.removeData(handleData); }; }, "事件专题/感知事件_close"(item, filter, type) { @@ -479,4 +468,4 @@ function removeDataPreHandle(markers) { }; lngLatMapHandle(markers, cb); window.renderData?.(window.page); //移除后,重新渲染弹出框更新数据 -} +} \ No newline at end of file diff --git a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/map.js b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/map.js index c7081832..d3ce5953 100644 --- a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/map.js +++ b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/map.js @@ -45,32 +45,74 @@ export class MarkerCluster { infoWindow; mapContainer; data = []; //标注集合 - dataInfo = {}; - vroot; constructor() {} getMap() { return (this.map = Vue.prototype.mapIns); } - async addData(_id, _data, isDefault) { + async addData(data, isDefault) { this.infoWindow?.close?.(); - Vue.prototype.mapInsOpenLayers.push(_id) + //data.forEach(e => { // const lnglat = getLnglat(e.extData); // e.extData.longitude = lnglat[0];//点坐标经度 【必传字段】 // e.extData.latitude = lnglat[1]; //}); - marksAddInGraph(_data); - if (!_data) return; - if (!Array.isArray(_data)) _data = [_data]; + marksAddInGraph(data); + + if (!data) return; + if (!Array.isArray(data)) data = [data]; + + this.data.push(...data); + + if(this.mapContainer === 'BMapContainer'){ + await this.refreshLayer(); + } else { + // 高德地图接口---------------------- + if ( + !this.markerCluster || + this.markerCluster.getMap() !== Vue.prototype.mapIns + ){ + await this.setMarkerCluster(); + } - this.refreshLayer(_id, _data); + // console.log( + // "%c [ data ]-227-「map.js」", + // "font-size:15px; background:#641f14; color:#a86358;" + // ); + this.markerCluster.addData(data); + // console.log( + // "%c [ this.markerCluster ]-234-「map.js」", + // "font-size:15px; background:#fe94d3; color:#ffd8ff;", + // this.markerCluster + // ); + const map = this.getMap(); + map.setZoom(10); + + setTimeout(() => { + map.setFitView([...this.markerCluster.U], false, [0, 0, 0, 0], 10); //自适应. 覆盖物数组, 动画过渡到指定位置, 周围边距,上、下、左、右, 最大 zoom 级别 + }, 150); + } + } - refreshLayer(_id,_data){ + async refreshLayer(){ + const map2d = Vue.prototype.mapIns + // map2d.addPointByArr( + // {pointList:[]}, // 点位数据数组(按以下规范组装) + // 'jhlayers', // 当前添加的数据 唯一标识(删除该图层时也会用到)//./事件专题/交通事故.svg + // true // 当前新加图层是否启用聚合效果 + // ); + const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay)) + try{ + console.log('执行remove') + map2d.removeLayerByName('jhlayers') + await sleep(2000) + } catch(e){} + console.log('执行remove完毕') const aryPoints = []; - _data.forEach(e=>{ + this.data.forEach(e=>{ if(e.lnglat){ let _name = e.config.item.title; if(e.config.item.id.indexOf('./路测设备') !== -1){ @@ -114,35 +156,292 @@ export class MarkerCluster { }) } }) - this.dataInfo[_id] = _data; - this.data.push(..._data); - if(aryPoints.length > 0){ - Vue.prototype.mapIns.addPointByArr( - {pointList:aryPoints}, // 点位数据数组(按以下规范组装) - _id, // jhlayers 当前添加的数据 唯一标识(删除该图层时也会用到)//./事件专题/交通事故.svg + if(aryPoints.length > 0){ + + console.log('执行show') + map2d.addPointByArr( + {pointList:aryPoints}, // 点位数据数组(按以下规范组装) + 'jhlayers', // 当前添加的数据 唯一标识(删除该图层时也会用到)//./事件专题/交通事故.svg true // 当前新加图层是否启用聚合效果 - ); - console.log(aryPoints,_id,'点位数组') + ); + await sleep(2000) + console.log('执行show完毕',aryPoints,'点位数组') } if(Vue.prototype.isMapStatck){ - setTimeout(() => { - Vue.prototype.mapIns.pileIsShow(_id, true); - }, 500); + Vue.prototype.mapIns.pileIsShow("jhlayers", true); } } - removeData(_id, _data) { - if (!_data) return; - if (!Array.isArray(_data)) _data = [_data]; - const _vpmIndex = Vue.prototype.mapInsOpenLayers.findIndex(_id); - if(_vpmIndex !== -1){ - Vue.prototype.mapInsOpenLayers.splice(_vpmIndex) - } - - const _dataTemp = []; - if(this.dataInfo[_id]){ - _dataTemp = this.dataInfo[_id] + async showInfoWindow(data) { + const AMap = await loadAMap(); + + const map = this.getMap(); + + if (!this.infoWindow) + this.infoWindow = new AMap.InfoWindow({ + content: "", + isCustom: true, + anchor: "bottom-center", + offset: new AMap.Pixel(0, -60), + }); + + console.log( + "%c [ this.infoWindow ]-330-「map.js」", + "font-size:15px; background:#6f5757; color:#b39b9b;", + this.infoWindow + ); + //data.length 大于 5 取前5个数, 否则直接返回data + const pageSize = 6; + let page = 1; + const totalPages = Math.ceil(data.length / pageSize); + const currentPageData = + totalPages > 1 ? data.slice((page - 1) * pageSize, pageSize) : data; + window.currentPageData = currentPageData; + window.pageSize = pageSize; + window.page = page; + window.totalPages = totalPages; + let num = (page - 1) * pageSize; + function renderData(page) { + if (!data || page < 1 || page > totalPages) return; + window.page = page; + const pageSize = window.pageSize; + const dataContainer = document.getElementById("dataContainer"); + const dataPage = document.getElementById("dataPage"); + // 清空数据容器 + // dataContainer.innerHTML = ""; + // 计算当前页起始索引和结束索引 + const startIndex = (page - 1) * pageSize; + const endIndex = startIndex + pageSize; + let num = (page - 1) * pageSize; + if (data.length === 0 || data.length === 1) { + return this.infoWindow.close(); + } + const { latitude: lat, longitude: lng } = data[0].extData; + const lngLatStr = `${parseFloat(lng)}/${parseFloat(lat)}`; //更新清除节点后的数据 + data = lngLatMap[lngLatStr]; + // 截取当前页的数据 + const currentPageData = data.slice(startIndex, endIndex); + window.currentPageData = currentPageData; + const itemsTpl = currentPageData + .map((item) => { + return ` +
+ ${++num} + ${( + item.extData.deviceName || + item.extData.warningTitle || + item.config?.item.title + ).replace("G35 ", "")} +
+ `; + }) + .join(""); + // 渲染当前页数据 + dataContainer.innerHTML = itemsTpl; + dataPage && (dataPage.innerHTML = `第${page}页`); + bindItemClick(); + } + + window.renderData = renderData; + + // min-width: 240px; + // min-height: 90px; + // width: 90px; + this.infoWindow.setContent(`
+
+ 重叠 + +
+
+ ${currentPageData + .map( + (item) => ` +
+ ${++num} + ${( + item.extData.deviceName || + item.extData.warningTitle || + item.config?.item.title + ).replace("G35 ", "")} +
+ ` + ) + .join("")} +
+ ${ + totalPages > 1 + ? ` +
+ + 第${page} 页 + +
` + : "" + } +
`); + window.infoWindow = this.infoWindow; + this.infoWindow.open(map, currentPageData[0].lnglat); + window.openInfoWindow = true; + this.infoWindow.dom.querySelector(".info-close").onclick = () => + this.infoWindow.close(); + + this.infoWindow.dom.querySelector(".info-window-content").onmousewheel = ( + e + ) => e.stopPropagation(); + + this.infoWindow.dom.querySelector(".info-window-content").onwheel = (e) => + e.stopPropagation(); + + function bindItemClick() { + window.infoWindow.dom + .querySelectorAll(".info-window-item") + .forEach((item, index) => { + item.onclick = () => { + const currentPageData = window.currentPageData; + currentPageData[index].config.markerClick?.( + currentPageData[index].extData, + currentPageData[index].config?.item + ); + }; + }); } - _data.forEach((item, index) => { + bindItemClick(); + } + + async setMarkerCluster() { + const AMap = await loadAMap(); + + const map = this.getMap(); + + let hasClick = false; + + const reset = () => { + if (!window.openInfoWindow) { + // console.log("窗口movestart中", new Date()); + this.infoWindow?.close?.(); + } + }; + + map.on("zoomstart", reset); + map.on("zoomend", reset); + map.on("movestart", reset); + map.on("moveend", async () => { + if (window.openInfoWindow) { + // console.log("窗口位移结束", new Date()); + window.openInfoWindow = false; + // !window.infoWindow.getIsOpen() && window.infoWindow?.open?.(); + } + }); + + const markerCluster = new AMap.MarkerCluster(map, [], { + // gridSize: 15, + maxZoom: 15, + // 自定义聚合点样式 + renderClusterMarker(context) { + // 聚合中点个数 + const clusterCount = context.count; + const div = document.createElement("div"); + let bgColor = "204,235,197"; + + div.style.backgroundColor = `rgba(${bgColor}, .6)`; + + const size = Math.round(24 + `${clusterCount}`.length * 15); + + div.style.borderRadius = + div.style.lineHeight = + div.style.width = + div.style.height = + `${size}px`; + div.style.border = `solid 1px rgba(${bgColor}, 1)`; + div.innerHTML = context.count; + div.style.color = "#ffffff"; + div.style.fontSize = "24px"; + div.style.textAlign = "center"; + + context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2)); + context.marker.setContent(div); + }, + renderMarker: (context) => { + const markerData = context.data[0]; + const { + extData, + lnglat: { lat, lng }, + } = markerData; + const lngLatStr = `${lng}/${lat}`; + const data = lngLatMap[lngLatStr]; + if (data) { + const state = getState(data); + let nowTitleBg, nowTitleColor; + if (state) { + nowTitleBg = normalTitleBg; + nowTitleColor = "#FFDB82"; + } else { + nowTitleBg = faultTitleBg; + nowTitleColor = "#FF7575"; + } + const item = data[0]; + const { stakeMark } = item.extData; + const titleTemplate = window.showStakeText + ? `

${stakeMark}

` + : ""; + + context.marker.setAnchor("bottom-center"); + + context.marker.setLabel({ + direction: "bottom", + // offset: new AMap.Pixel(10, 0), //设置文本标注偏移量 + content: titleTemplate, //设置文本标注内容 + }); + + context.marker.setContent(getContent(data)); + // if (window.showStakeText) context.marker.setAnchor("center"); + // else context.marker.setAnchor("bottom-center"); + const offset = new AMap.Pixel(0, 0); + context.marker.setOffset(offset); + + context.marker.setExtData(extData); + + context.marker.on("click", (e) => { + hasClick = true; + + const data = lngLatMap[lngLatStr]; + if (data.length > 1) { + this.showInfoWindow(data); + return; + } + + console.log( + "%c [ 点击地图坐标 ]-302-「map.js」", + "font-size:15px; background:#8f8c0b; color:#d3d04f;", + data[0] + ); + + data[0].config.markerClick?.(data[0].extData, data[0].config?.item); + }); + } + }, + }); + + markerCluster.on("click", (e) => { + if (hasClick) return (hasClick = false); + + map.setCenter(e.lnglat); + map.setZoom(map.getZoom() + 3); + }); + + this.markerCluster = markerCluster; + } + + async removeData(data) { + data.forEach((item, index) => { const findIndex = this.data.findIndex( (removeData) => removeData === item ); @@ -168,30 +467,83 @@ export class MarkerCluster { } } if (findIndex > -1) this.data.splice(findIndex, 1); - - const _findIndex = _dataTemp.findIndex( - (removeData) => removeData === item - ); - if (_findIndex > -1) { - _dataTemp.splice(_findIndex, 1); - } }); - console.log('remove',_id,_data) - Vue.prototype.mapIns.removeLayerByName(_id); - if(_dataTemp.length > 0){ - const self = this; - setTimeout(() => { - self.refreshLayer(_id, _dataTemp); - }, 500); - } - + await this.setData() } + async setData() { + if(this.mapContainer === 'BMapContainer'){ + await this.refreshLayer(); + } else { + this.markerCluster.setData(this.data); //高德地图 + } + } clear() { this.data = []; } } +export function getContent(data) { + // const faultBg = require(`@screen/images/mapBg/fault.svg`); + // const normalBg = require(`@screen/images/mapBg/active.svg`); + const state = getState(data); + let nowBg, nowTitleBg, nowTitleColor; + if (state) { + nowBg = normalBg; + nowTitleBg = normalTitleBg; + nowTitleColor = "#FFDB82"; + } else { + nowBg = faultBg; + nowTitleBg = faultTitleBg; + nowTitleColor = "#FF7575"; + } + + const item = data[0]; + const { stakeMark } = item.extData; + if (data.length === 1) { + return ` +
+ +
+ `; + } else { + const width = `${36 + `${data.length}`.length * 15}px`; + + return ` +
+ ${data.length} +
+`; + } +} + function getIcon({ config, extData }, type = '') { const normal = require(`@screen/images/layer${type}${config.item.id.replace( /^\.|[^/]+(?=.svg$)/g, @@ -250,7 +602,6 @@ export function addInGraphHandle(data) { 54.394) * window.canvasRatio + window.canvasWidth * window.offsetRatio; //K54+394 开始到K208+979计算的比例尺 - const node = { shape: "custom-html", effect: ["data"] }; node.data = getDataConf(data, extData); const id = `${stakeMark}_${direction || ""}`; @@ -303,4 +654,4 @@ export function getLatAndLng(lnglat) { else return lnglat; } -export const markerClusterIns = new MarkerCluster(); +export const markerClusterIns = new MarkerCluster(); \ No newline at end of file diff --git a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/index.vue b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/index.vue index 9170efaf..e6dfc9f5 100644 --- a/ruoyi-ui/src/views/JiHeExpressway/pages/Home/index.vue +++ b/ruoyi-ui/src/views/JiHeExpressway/pages/Home/index.vue @@ -140,7 +140,6 @@ export default { // justify-content: center; - .card-menu { transition: all 0.24s linear; }