Compare commits
5 Commits
621b368d38
...
efe6cd18a3
| Author | SHA1 | Date |
|---|---|---|
|
|
efe6cd18a3 | |
|
|
1dadfc0b6b | |
|
|
8ee0db5f3a | |
|
|
21949e6057 | |
|
|
9085ad60aa |
|
|
@ -3,9 +3,19 @@ import { regInfo } from '@/api/dataSearch'
|
||||||
|
|
||||||
let sourceLayer = undefined;
|
let sourceLayer = undefined;
|
||||||
let clickedLineIds = [];
|
let clickedLineIds = [];
|
||||||
// 单例 Popup,用于确保地图上只有一个弹框实例
|
// 存储可复用的每个地图对象的唯一 Popup 实例(key 为 mapId),以避免频繁创建/销毁 Popup 导致的性能问题和潜在内存泄漏
|
||||||
let sharedPopup = null;
|
let sharedPopup = {};
|
||||||
|
|
||||||
|
export function setMapLayoutProperty(mapId, visibility = "none") {
|
||||||
|
// 设置所有图层的显示/隐藏状态(根据图层类型或名称过滤底图图层,避免误操作)
|
||||||
|
const layers = Vue.config.maps[mapId].getStyle().layers;
|
||||||
|
layers.forEach(layer => {
|
||||||
|
// 跳过底图
|
||||||
|
if (layer.id !== '影像地图' && layer.type !== 'raster') {
|
||||||
|
Vue.config.maps[mapId].setLayoutProperty(layer.id, 'visibility', visibility);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
export function loadVectorLayer(layerId, features = ["line", "symbol"], colors = ["#FEFEFE", "#FF0000"], visibility = "visible", mapId = "homeMap", workspace = 'dsds', textField = "name") {
|
export function loadVectorLayer(layerId, features = ["line", "symbol"], colors = ["#FEFEFE", "#FF0000"], visibility = "visible", mapId = "homeMap", workspace = 'dsds', textField = "name") {
|
||||||
// 添加数据源
|
// 添加数据源
|
||||||
const sourceId = `vector-${layerId}`;
|
const sourceId = `vector-${layerId}`;
|
||||||
|
|
@ -127,6 +137,10 @@ export async function loadVectorFeature(layerId, feature, color, visibility, map
|
||||||
// 'slot': 'foreground'
|
// 'slot': 'foreground'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// 图层已存在则设置为可见
|
||||||
|
Vue.config.maps[mapId].setLayoutProperty(`${sourceId}-${feature}`, "visibility", "visible");
|
||||||
|
}
|
||||||
|
|
||||||
// 点击可交互的图层,显示相关信息
|
// 点击可交互的图层,显示相关信息
|
||||||
await setHighlight(`${sourceId}-${feature}`, sourceId, mapId);
|
await setHighlight(`${sourceId}-${feature}`, sourceId, mapId);
|
||||||
|
|
@ -136,6 +150,10 @@ export async function loadVectorFeature(layerId, feature, color, visibility, map
|
||||||
await showSampleLineInfo(`${sourceId}-${feature}`, mapId);
|
await showSampleLineInfo(`${sourceId}-${feature}`, mapId);
|
||||||
if (layerId.includes("sample_station"))
|
if (layerId.includes("sample_station"))
|
||||||
await showSampleStationInfo(`${sourceId}-${feature}`, mapId);
|
await showSampleStationInfo(`${sourceId}-${feature}`, mapId);
|
||||||
|
else if (sourceId.includes("-SY") || sourceId.includes("-FDZ")) {
|
||||||
|
await showDiveInfo(`${sourceId}-${feature}`, mapId);
|
||||||
|
console.log(mapId, `${sourceId}-${feature}`);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
await showTrackInfo(`${sourceId}-${feature}`, mapId);
|
await showTrackInfo(`${sourceId}-${feature}`, mapId);
|
||||||
|
|
||||||
|
|
@ -411,6 +429,36 @@ export function showTrackInfo(layerId, mapId = "homeMap") {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function showDiveInfo(layerId, mapId = "homeMap") {
|
||||||
|
Vue.config.maps[mapId].on("click", layerId, async (e) => {
|
||||||
|
// 禁止点击事件穿透 - 判断同一个 event 是否已经触发,用于避免图层内标记点注册的点击事件重复触发(点位分布密集时容易出现)
|
||||||
|
if (e.defaultPrevented)
|
||||||
|
return;
|
||||||
|
// 标记该 event 已触发,禁止点击事件穿透
|
||||||
|
if (typeof e.preventDefault === "function")
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const feature = e.features[0];
|
||||||
|
let coordinate = e.lngLat;
|
||||||
|
const description = `
|
||||||
|
<table class="popup-table" style="min-width:280px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">潜次信息</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">潜次编号: <b>${feature.properties.name}</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">created_at: <b>${feature.properties.created_at}</b></td>
|
||||||
|
</tr>
|
||||||
|
</table>`;
|
||||||
|
|
||||||
|
showPopupDetails({ mapId, coordinate, description, maxWidth: "300px" });
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function showPopupDetails({ mapId, coordinate, description, maxWidth = "300px", closeButton = true, closeOnClick = true, options = {}, callbackOnClose }) {
|
export function showPopupDetails({ mapId, coordinate, description, maxWidth = "300px", closeButton = true, closeOnClick = true, options = {}, callbackOnClose }) {
|
||||||
const map = Vue.config.maps[mapId];
|
const map = Vue.config.maps[mapId];
|
||||||
if (!map)
|
if (!map)
|
||||||
|
|
@ -419,28 +467,29 @@ export function showPopupDetails({ mapId, coordinate, description, maxWidth = "3
|
||||||
const popupOptions = Object.assign({ offset: {}, className: "my-class", closeButton: closeButton, closeOnClick: closeOnClick }, options);
|
const popupOptions = Object.assign({ offset: {}, className: "my-class", closeButton: closeButton, closeOnClick: closeOnClick }, options);
|
||||||
|
|
||||||
// 如果已有共享 popup,复用并更新位置/内容;否则创建新的并绑定 close 事件以便释放引用
|
// 如果已有共享 popup,复用并更新位置/内容;否则创建新的并绑定 close 事件以便释放引用
|
||||||
if (sharedPopup) {
|
if (sharedPopup[mapId]) {
|
||||||
try {
|
try {
|
||||||
sharedPopup.setLngLat(coordinate)
|
sharedPopup[mapId].setLngLat(coordinate)
|
||||||
.setHTML(description)
|
.setHTML(description)
|
||||||
.setOffset(10)
|
.setOffset(10)
|
||||||
.setMaxWidth(maxWidth);
|
.setMaxWidth(maxWidth)
|
||||||
|
.addTo(map);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.error("设置 popup 失败:", err);
|
||||||
try {
|
try {
|
||||||
// 万一现有 popup 状态异常,移除并重新创建
|
// 万一现有 popup 状态异常,移除并重新创建
|
||||||
sharedPopup.remove();
|
sharedPopup[mapId].remove();
|
||||||
sharedPopup = null;
|
sharedPopup[mapId] = null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("移除异常 popup 失败:", e);
|
console.error("移除异常 popup 失败:", e);
|
||||||
}
|
}
|
||||||
sharedPopup = new window.mapboxgl.Popup(popupOptions)
|
sharedPopup[mapId] = new window.mapboxgl.Popup(popupOptions)
|
||||||
.setLngLat(coordinate)
|
.setLngLat(coordinate)
|
||||||
.setHTML(description)
|
.setHTML(description)
|
||||||
.setOffset(10)
|
.setOffset(10)
|
||||||
.setMaxWidth(maxWidth)
|
.setMaxWidth(maxWidth)
|
||||||
.addTo(map);
|
.addTo(map);
|
||||||
sharedPopup.on('close', () => {
|
sharedPopup[mapId].on('close', () => {
|
||||||
sharedPopup = null;
|
|
||||||
// 关闭弹窗时执行回调(如有)
|
// 关闭弹窗时执行回调(如有)
|
||||||
if (callbackOnClose && typeof callbackOnClose === "function") {
|
if (callbackOnClose && typeof callbackOnClose === "function") {
|
||||||
callbackOnClose();
|
callbackOnClose();
|
||||||
|
|
@ -448,14 +497,13 @@ export function showPopupDetails({ mapId, coordinate, description, maxWidth = "3
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sharedPopup = new window.mapboxgl.Popup(popupOptions)
|
sharedPopup[mapId] = new window.mapboxgl.Popup(popupOptions)
|
||||||
.setLngLat(coordinate)
|
.setLngLat(coordinate)
|
||||||
.setHTML(description)
|
.setHTML(description)
|
||||||
.setOffset(10)
|
.setOffset(10)
|
||||||
.setMaxWidth(maxWidth)
|
.setMaxWidth(maxWidth)
|
||||||
.addTo(map);
|
.addTo(map);
|
||||||
sharedPopup.on('close', () => {
|
sharedPopup[mapId].on('close', () => {
|
||||||
sharedPopup = null;
|
|
||||||
// 关闭弹窗时执行回调(如有)
|
// 关闭弹窗时执行回调(如有)
|
||||||
if (callbackOnClose && typeof callbackOnClose === "function") {
|
if (callbackOnClose && typeof callbackOnClose === "function") {
|
||||||
callbackOnClose();
|
callbackOnClose();
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ import PieChart from './components/PieChart.vue'
|
||||||
import { reportList, platformHov, hovUnit, hovUnitYear, hovDiving } from '../../api/statistics'
|
import { reportList, platformHov, hovUnit, hovUnitYear, hovDiving } from '../../api/statistics'
|
||||||
import { filterDictItems } from '../../utils/index'
|
import { filterDictItems } from '../../utils/index'
|
||||||
import { initMapbox } from "@/utils/mapbox-utils";
|
import { initMapbox } from "@/utils/mapbox-utils";
|
||||||
import { loadVectorLayer, loadJsonPointFeature,showUnitReport } from '@/utils/vector-layer-utils'
|
import { setMapLayoutProperty, loadVectorLayer, loadJsonPointFeature, showUnitReport } from '@/utils/vector-layer-utils'
|
||||||
import { ColorGenerator } from '@/utils/color-generator';
|
import { ColorGenerator } from '@/utils/color-generator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -158,7 +158,6 @@ export default {
|
||||||
// 选择载人潜水器
|
// 选择载人潜水器
|
||||||
handleCommand(command) {
|
handleCommand(command) {
|
||||||
this.currentTitle = command
|
this.currentTitle = command
|
||||||
this.removeSingleLineImg()
|
|
||||||
if (command === '全部载人潜水器') {
|
if (command === '全部载人潜水器') {
|
||||||
this.getHovList()
|
this.getHovList()
|
||||||
this.gitHovDiving()
|
this.gitHovDiving()
|
||||||
|
|
@ -227,15 +226,17 @@ export default {
|
||||||
// 潜次统计
|
// 潜次统计
|
||||||
gitHovDiving(params = {}) {
|
gitHovDiving(params = {}) {
|
||||||
hovDiving(params).then(res => {
|
hovDiving(params).then(res => {
|
||||||
|
if (params.platform_name) {
|
||||||
|
// 按潜水器筛选数据,先隐藏所有图层,再根据筛选结果显示对应图层
|
||||||
|
setMapLayoutProperty('voyageMap_hov', 'none')
|
||||||
|
}
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const colors = ColorGenerator.generateDivergingColors(res.array.length);
|
const colors = ColorGenerator.generateDivergingColors(res.array.length);
|
||||||
// 添加轨迹图层
|
|
||||||
res.array.forEach(item => {
|
res.array.forEach(item => {
|
||||||
// 加载轨迹图层
|
// 加载下潜轨迹
|
||||||
loadVectorLayer(item.diving_sn, ["line", "symbol"], [colors[i], "#FFFFFF"], "visible", "voyageMap_hov", "dsds");
|
loadVectorLayer(item.diving_sn, ["line", "symbol"], [colors[i], "#FFFFFF"], "visible", "voyageMap_hov", "dsds");
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
// this.addSingleLineImg(item)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ import PieChart from './components/PieChart.vue'
|
||||||
import { reportList, shipTotal, shipUnit, shipUnitYear, shipVoyage } from '../../api/statistics'
|
import { reportList, shipTotal, shipUnit, shipUnitYear, shipVoyage } from '../../api/statistics'
|
||||||
import { getYearRange, filterDictItems } from '../../utils/index'
|
import { getYearRange, filterDictItems } from '../../utils/index'
|
||||||
import { initMapbox } from '@/utils/mapbox-utils'
|
import { initMapbox } from '@/utils/mapbox-utils'
|
||||||
import { loadVectorLayer, loadJsonPointFeature, showUnitReport } from '@/utils/vector-layer-utils'
|
import { setMapLayoutProperty, loadVectorLayer, loadJsonPointFeature, showUnitReport } from '@/utils/vector-layer-utils'
|
||||||
import { ColorGenerator } from '@/utils/color-generator'
|
import { ColorGenerator } from '@/utils/color-generator'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -171,7 +171,6 @@ export default {
|
||||||
// 选择科考船
|
// 选择科考船
|
||||||
handleCommand(command) {
|
handleCommand(command) {
|
||||||
this.currentTitle = command
|
this.currentTitle = command
|
||||||
// this.removeSingleLineImg()
|
|
||||||
if (command === '全部科考船') {
|
if (command === '全部科考船') {
|
||||||
this.getShipList()
|
this.getShipList()
|
||||||
this.gitShipVoyage()
|
this.gitShipVoyage()
|
||||||
|
|
@ -241,11 +240,16 @@ export default {
|
||||||
// 航次统计
|
// 航次统计
|
||||||
gitShipVoyage(params = {}) {
|
gitShipVoyage(params = {}) {
|
||||||
shipVoyage(params).then(res => {
|
shipVoyage(params).then(res => {
|
||||||
|
if (params.start || params.end) {
|
||||||
|
// 按年份筛选数据,先隐藏所有图层,再根据筛选结果显示对应图层
|
||||||
|
setMapLayoutProperty('voyageMap_ship', 'none')
|
||||||
|
}
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
const colors = ColorGenerator.generateDivergingColors(res.array.length)
|
const colors = ColorGenerator.generateDivergingColors(res.array.length)
|
||||||
// 添加轨迹图层
|
// 添加轨迹图层
|
||||||
res.array.forEach(item => {
|
res.array.forEach(item => {
|
||||||
// 加载轨迹图层
|
// 加载轨迹图层(已存在则设置为可见)
|
||||||
loadVectorLayer(item.voyage_name, ['line', 'symbol'], [colors[i], '#FFFFFF'], 'visible', 'voyageMap_ship', 'dsds')
|
loadVectorLayer(item.voyage_name, ['line', 'symbol'], [colors[i], '#FFFFFF'], 'visible', 'voyageMap_ship', 'dsds')
|
||||||
i++
|
i++
|
||||||
})
|
})
|
||||||
|
|
@ -256,7 +260,6 @@ export default {
|
||||||
selectVoyageYear(val) {
|
selectVoyageYear(val) {
|
||||||
const shipName = this.currentTitle === '全部科考船' ? '' : this.currentTitle
|
const shipName = this.currentTitle === '全部科考船' ? '' : this.currentTitle
|
||||||
if (val) {
|
if (val) {
|
||||||
// this.removeSingleLineImg()
|
|
||||||
const params = getYearRange(val)
|
const params = getYearRange(val)
|
||||||
this.gitShipVoyage({ ...params, ship_name: shipName })
|
this.gitShipVoyage({ ...params, ship_name: shipName })
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue