From 94ae30d3d6a7ddf8a2b17635a849a1d446a6808a Mon Sep 17 00:00:00 2001 From: Xu Zhimeng Date: Fri, 16 Jun 2023 18:58:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=B9=E7=AA=97=E5=92=8C=E5=8A=A8?= =?UTF-8?q?=E6=95=88=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/map.js | 14 + .../components/DataListItem.vue | 4 +- .../stationOperation/components/MapMarker.vue | 282 +++++++++++++----- .../stationOperation/components/MapPane.vue | 81 ++++- .../stationOperation/components/markerEnum.js | 4 +- .../components/markerPopupColumns.js | 157 ++++++++++ src/views/stationOperation/index.vue | 16 +- 7 files changed, 459 insertions(+), 99 deletions(-) create mode 100644 src/utils/map.js create mode 100644 src/views/stationOperation/components/markerPopupColumns.js diff --git a/src/utils/map.js b/src/utils/map.js new file mode 100644 index 0000000..6c80e69 --- /dev/null +++ b/src/utils/map.js @@ -0,0 +1,14 @@ +/** + * 将十进制度格式的经度转换为度分秒 + * @param {*} decimal + * @param {*} isLongitude 是不是经度 + * @returns + */ +export function decimalToDms(decimal, isLongitude = true) { + const degrees = Math.floor(decimal); + const decimalMinutes = (decimal - degrees) * 60; + const minutes = Math.floor(decimalMinutes); + const seconds = parseInt((decimalMinutes - minutes) * 60); + const tail = isLongitude ? (decimal > 0 ? 'E' : decimal < 0 ? 'W' : '') : (decimal > 0 ? 'N' : decimal < 0 ? 'S' : '') + return `${Math.abs(degrees)}°${minutes}'${seconds}"${tail}`; +} \ No newline at end of file diff --git a/src/views/stationOperation/components/DataListItem.vue b/src/views/stationOperation/components/DataListItem.vue index 57ba3d9..44cc0fc 100644 --- a/src/views/stationOperation/components/DataListItem.vue +++ b/src/views/stationOperation/components/DataListItem.vue @@ -10,9 +10,11 @@ {{ item.stationType }} + +
- {{ item.altitude + 'm' }} + {{ item.altitude }}
diff --git a/src/views/stationOperation/components/MapMarker.vue b/src/views/stationOperation/components/MapMarker.vue index 1749b12..311a629 100644 --- a/src/views/stationOperation/components/MapMarker.vue +++ b/src/views/stationOperation/components/MapMarker.vue @@ -1,19 +1,27 @@ + diff --git a/src/views/stationOperation/components/MapPane.vue b/src/views/stationOperation/components/MapPane.vue index 408a30d..06b4513 100644 --- a/src/views/stationOperation/components/MapPane.vue +++ b/src/views/stationOperation/components/MapPane.vue @@ -224,6 +224,11 @@ import { postAction } from '../../../api/manage' import { MarkerType } from './markerEnum' import { Vector as VectorLayer } from 'ol/layer' +import VectorSource from 'ol/source/Vector' +import { Circle } from 'ol/geom' +import { fromLonLat } from 'ol/proj' +import Feature from 'ol/Feature' +import { Fill, Stroke, Style } from 'ol/style' // Filter中的筛选列表 const filterList = [ @@ -389,17 +394,26 @@ export default { created() { this.initParentMapProps() document.addEventListener('fullscreenchange', this.onFullScreenChange) + this.stationList = [] }, destroyed() { document.removeEventListener('fullscreenchange', this.onFullScreenChange) }, methods: { initParentMapProps() { - const { getZoom, setZoom, maxZoom, minZoom } = this.$parent + const { getZoom, setZoom, maxZoom, minZoom, map } = this.$parent this.getZoom = getZoom this.setZoom = setZoom this.maxZoom = maxZoom this.minZoom = minZoom + this.map = map + this.circleLayer = new VectorLayer({ + source: new VectorSource({ + features: [] + }), + properties: { name: 'eventCircle' } + }) + this.map.addLayer(this.circleLayer) }, handleFullScreen() { @@ -420,10 +434,13 @@ export default { this.active = active switch (active) { case 1: // 核设施查询面板 + this.drawCircle() this.emitStationChange() break case 2: // 筛选面板 this.emitTypeFilter() + const source = this.circleLayer.getSource() + source.clear() break } }, @@ -485,17 +502,19 @@ export default { }) this.dataSource = data // 设置Infomation表格内容 - const stationList = [] // 台站列表 - markerList.forEach(markerItem => { // 返回的数据类型不符合要求,根据stationId判断是否是台站,增加台站类型和转换字段,以便进行marker的绘制 + this.stationList = [] // 台站列表 + markerList.forEach(markerItem => { + // 返回的数据类型不符合要求,根据stationId判断是否是台站,增加台站类型和转换字段,以便进行marker的绘制 if (markerItem.stationId) { // 是台站 markerItem.stationType = MarkerType.ImsRnStationG - stationList.push(markerItem) + this.stationList.push(markerItem) } else { // 是核设施 markerItem.stationType = MarkerType.NuclearFacility markerItem.lon = markerItem.longitude markerItem.lat = markerItem.latitude + markerItem.stationId = markerItem.facilityId } }) @@ -508,7 +527,7 @@ export default { this.markerList = markerList this.emitStationChange() - this.drawCircle(stationList) + this.drawCircle() } else { this.$message.error(message) } @@ -520,13 +539,53 @@ export default { }, // 绘制圆圈 - drawCircle(stationList) { - this.circleLayer = new VectorLayer({ - source: new VectorSource({ - features: [] - }), - properties: { name: 'eventMarker' } + drawCircle() { + const source = this.circleLayer.getSource() + source.clear() + const circleFeatures = [] + this.stationList.forEach(stationItem => { + circleFeatures.push(this.getCircle(stationItem)) }) + source.addFeatures(circleFeatures) + }, + + getCircle(stationInfo) { + const { lon, lat } = stationInfo + + // 定义填充颜色 + const fill = new Fill({ + color: 'rgba(255, 0, 0, .4)' // 红色半透明填充 + }) + + // 定义边框样式 + const stroke = new Stroke({ + color: 'rgba(255, 0, 0, .4)', // 红色半透明边框 + width: 1 // 边框宽度 + }) + + // 创建样式 + const style = new Style({ + fill: fill, + stroke: stroke + }) + + const circle = new Circle(fromLonLat([lon, lat]), this.getRadius()) + const feature = new Feature({ + geometry: circle, + style: style + }) + feature.setStyle(style) + return feature + }, + + // 半径计算 + getRadius() { + const metersPerUnit = this.map + .getView() + .getProjection() + .getMetersPerUnit() + const circleRadius = (this.radius * 1000) / metersPerUnit + return circleRadius }, // 打开分析弹窗 diff --git a/src/views/stationOperation/components/markerEnum.js b/src/views/stationOperation/components/markerEnum.js index 3f375d9..e8731c6 100644 --- a/src/views/stationOperation/components/markerEnum.js +++ b/src/views/stationOperation/components/markerEnum.js @@ -7,8 +7,8 @@ import Ship from '@/assets/images/station-operation/ship.png' export const MarkerType = { Car: 'Car', GroudMonitoringStation: 'Groud monitoring station', - ImsRnStationP: 'IMS STATION', - ImsRnStationG: 'IMS STATION', + ImsRnStationP: 'IMS STATION(P)', + ImsRnStationG: 'IMS STATION(G)', NuclearFacility: 'Nuclear Facility', Ship: 'Ship' diff --git a/src/views/stationOperation/components/markerPopupColumns.js b/src/views/stationOperation/components/markerPopupColumns.js new file mode 100644 index 0000000..d136704 --- /dev/null +++ b/src/views/stationOperation/components/markerPopupColumns.js @@ -0,0 +1,157 @@ +import { MarkerType } from './markerEnum' + +// 核设施详情弹窗中的字段配置 +export default { + [MarkerType.NuclearFacility]: [ + { + label: 'ACTIVITY DAY', + key: 'activityDay' + }, + { + label: 'ACTIVITY_YEAR', + key: 'activityYear' + }, + { + label: 'BUILDDATE', + key: 'buildDate' + }, + { + label: 'CAPACITYGROSS', + key: 'capacitygross' + }, + { + label: 'CAPACITYNET', + key: 'capacitynet' + }, + { + label: 'CAPACITYTHERMAL', + key: 'capacitythermal' + }, + { + label: 'CRITICALITYDATE', + key: 'criticalityDate' + }, + { + label: 'FACILITY ID', + key: 'facilityId' + }, + { + label: 'FACILITY_NAME', + key: 'facilityName' + }, + { + label: 'GRIDCONEETIONDATE', + key: 'gridconeetionDate' + }, + { + label: 'LATITUDE', + key: 'lat' + }, + { + label: 'LOCATION', + key: 'location' + }, + { + label: 'LONGITUDE', + key: 'lon' + }, + { + label: 'OPERARTOR', + key: 'operartor' + }, + { + label: 'OWNER', + key: 'owner' + }, + { + label: 'RETIREDATE', + key: 'retireDate' + }, + { + label: 'STATUS', + key: 'status' + }, + { + label: 'TYPE', + key: 'type' + }, + { + label: 'VENDOR', + key: 'vendor' + }, + ], + [MarkerType.ImsRnStationP]: [{ + label: 'COUNTRYCODE', + key: 'countryCode' + }, { + label: 'DATEBEGIN', + key: 'dateBegin' + }, { + label: 'DATEEND', + key: 'dateEnd' + }, { + label: 'DESCRIPTION', + key: 'description' + }, { + label: 'ELEVATION', + key: 'elevation' + }, { + label: 'LATITUDE', + key: 'lat' + }, { + label: 'LONGITUDE', + key: 'lon' + }, { + label: 'MODDATE', + key: 'moddate' + }, { + label: 'STATIONCODE', + key: 'stationCode' + }, { + label: 'STATIONID', + key: 'stationId' + }, { + label: 'STATUS', + key: 'status' + }, { + label: 'TYPE', + key: 'type' + }], + [MarkerType.ImsRnStationG]: [{ + label: 'COUNTRYCODE', + key: 'countryCode' + }, { + label: 'DATEBEGIN', + key: 'dateBegin' + }, { + label: 'DATEEND', + key: 'dateEnd' + }, { + label: 'DESCRIPTION', + key: 'description' + }, { + label: 'ELEVATION', + key: 'elevation' + }, { + label: 'LATITUDE', + key: 'lat' + }, { + label: 'LONGITUDE', + key: 'lon' + }, { + label: 'MODDATE', + key: 'moddate' + }, { + label: 'STATIONCODE', + key: 'stationCode' + }, { + label: 'STATIONID', + key: 'stationId' + }, { + label: 'STATUS', + key: 'status' + }, { + label: 'TYPE', + key: 'type' + }] +} \ No newline at end of file diff --git a/src/views/stationOperation/index.vue b/src/views/stationOperation/index.vue index e814cee..79d7a8c 100644 --- a/src/views/stationOperation/index.vue +++ b/src/views/stationOperation/index.vue @@ -86,7 +86,7 @@ ref="customScrollContainerRef" class="scroller" :items="dataList" - :item-size="108" + :item-size="129" key-field="stationId" v-slot="{ item }" > @@ -139,8 +139,13 @@ ref="map" token="AAPK2b935e8bbf564ef581ca3c6fcaa5f2a71ZH84cPqqFvyz3KplFRHP8HyAwJJkh6cnpcQ-qkWh5aiyDQsGJbsXglGx0QM2cPm" > - - + +
@@ -332,6 +337,11 @@ export default { this.markerList = this.originalDataList.filter(item => typeList.includes(item.stationType)) }, + // 地图图标点击 + onMarkerClick() { + this.$refs.mapPane.handleOpenAnalyzeModal() + }, + getScrollContainer() { return this.$refs.customScrollContainerRef.$el },