feat: 完成Filter和根据距离获取并绘制范围内核设施功能,增加点击左侧列表定位到台站功能
This commit is contained in:
parent
9c0195ed58
commit
dff9ee4442
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
@ -6,6 +6,7 @@
|
|||
checkable
|
||||
:selectedKeys="[]"
|
||||
:tree-data="treeData"
|
||||
:replace-fields="replaceFields"
|
||||
@select="onTreeSelect"
|
||||
>
|
||||
<a-icon slot="switcherIcon" type="down" />
|
||||
|
@ -21,6 +22,16 @@ export default {
|
|||
},
|
||||
value: {
|
||||
type: Array
|
||||
},
|
||||
replaceFields: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
children: 'children',
|
||||
title: 'title',
|
||||
key: 'key'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -41,8 +52,8 @@ export default {
|
|||
// 选中了
|
||||
this.checkedKeys.push(selectedKey)
|
||||
|
||||
const parentNode = this.treeData.find(tree => tree.key == parentKey) // 找到树列表中的父节点
|
||||
const childrenKeys = parentNode.children.map(child => child.key)
|
||||
const parentNode = this.treeData.find(tree => tree[this.replaceFields.key] == parentKey) // 找到树列表中的父节点
|
||||
const childrenKeys = parentNode.children.map(child => child[this.replaceFields.key])
|
||||
if (childrenKeys.every(key => this.checkedKeys.includes(key))) {
|
||||
// 如果子列表每一个都能在选中的列表中找到,则是全选
|
||||
this.checkedKeys.push(parentKey)
|
||||
|
@ -58,8 +69,8 @@ export default {
|
|||
}
|
||||
} else {
|
||||
//选中的是父级节点
|
||||
const parentNode = this.treeData.find(tree => tree.key == selectedKey)
|
||||
const childrenKeys = parentNode.children.map(child => child.key)
|
||||
const parentNode = this.treeData.find(tree => tree[this.replaceFields.key] == selectedKey)
|
||||
const childrenKeys = parentNode.children.map(child => child[this.replaceFields.key])
|
||||
|
||||
const findParent = this.checkedKeys.findIndex(key => key == selectedKey)
|
||||
if (-1 == findParent) {
|
||||
|
|
|
@ -363,20 +363,29 @@ body {
|
|||
border-left-width: 4px;
|
||||
border-right-width: 4px;
|
||||
border-bottom-color: #4b859e;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 50%;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
&-down {
|
||||
border-top: none;
|
||||
&::after {
|
||||
transform: rotate(180deg);
|
||||
top: 1px;
|
||||
transform: translateX(4px) rotate(180deg);
|
||||
top: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// 单选样式
|
||||
.ant-radio {
|
||||
&-wrapper {
|
||||
|
|
120
src/views/stationOperation/components/DataListItem.vue
Normal file
120
src/views/stationOperation/components/DataListItem.vue
Normal file
|
@ -0,0 +1,120 @@
|
|||
<template>
|
||||
<div class="data-list-item">
|
||||
<h4 class="data-list-item-title">
|
||||
{{ item.stationName }}
|
||||
</h4>
|
||||
<div class="data-list-item-container">
|
||||
<div class="data-list-item-content">
|
||||
<div class="data-list-item-children">
|
||||
<div class="data-list-item-child">
|
||||
<label>Station Type:</label>
|
||||
<span>{{ item.stationType }}</span>
|
||||
</div>
|
||||
<div class="data-list-item-child" style="word-break: break-all">
|
||||
<label>Altitude:</label>
|
||||
<span>{{ item.altitude + 'm' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-list-item-children">
|
||||
<div class="data-list-item-child">
|
||||
<label>Lon And Lat:</label>
|
||||
<span>{{ Number(item.lon).toFixed(6) }} {{ Number(item.lat).toFixed(6) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-list-item-children">
|
||||
<div class="data-list-item-child">
|
||||
<label>Status:</label>
|
||||
<span class="green">{{ item.status }}</span>
|
||||
</div>
|
||||
<div class="data-list-item-child">
|
||||
<label>Signal:</label>
|
||||
<span class="green">{{ item.signal }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
item: {
|
||||
type: Object
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.data-list-item {
|
||||
width: 322px;
|
||||
cursor: pointer;
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-title {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-family: Arial;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
padding: 10px 10px 10px 14px;
|
||||
flex: 1;
|
||||
color: #6ebad0;
|
||||
background: url(~@/assets/images/station-operation/data-item-bg.png) center no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.data-list-item-children {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.data-list-item-child {
|
||||
color: #fff;
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:nth-child(2n) {
|
||||
width: 110px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
label {
|
||||
color: #6ebad0;
|
||||
font-family: Arial;
|
||||
}
|
||||
|
||||
span {
|
||||
margin-left: 10px;
|
||||
&.green {
|
||||
color: #0cff00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -10,6 +10,7 @@ import TileLayer from 'ol/layer/Tile'
|
|||
import Map from 'ol/Map'
|
||||
import XYZ from 'ol/source/XYZ'
|
||||
import View from 'ol/View'
|
||||
import { fromLonLat } from 'ol/proj'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -19,7 +20,7 @@ export default {
|
|||
},
|
||||
zoom: {
|
||||
type: Number,
|
||||
default: 3
|
||||
default: 1
|
||||
},
|
||||
maxZoom: {
|
||||
type: Number,
|
||||
|
@ -27,7 +28,7 @@ export default {
|
|||
},
|
||||
minZoom: {
|
||||
type: Number,
|
||||
default: 3
|
||||
default: 1
|
||||
},
|
||||
center: {
|
||||
type: Object,
|
||||
|
@ -61,8 +62,8 @@ export default {
|
|||
]
|
||||
|
||||
const view = new View({
|
||||
projection: 'EPSG:900913', // 使用这个坐标系
|
||||
center: [longitude, latitude],
|
||||
projection: 'EPSG:3857', // 使用这个坐标系
|
||||
center: fromLonLat([longitude, latitude]),
|
||||
zoom: this.zoom,
|
||||
maxZoom: this.maxZoom,
|
||||
minZoom: this.minZoom
|
||||
|
@ -107,7 +108,7 @@ export default {
|
|||
// 平移到某个位置
|
||||
panTo(center, duration = 1000) {
|
||||
return this.map.getView().animate({
|
||||
center,
|
||||
center: fromLonLat(center),
|
||||
duration
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,8 +4,15 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { Vector as VectorLayer } from 'ol/layer'
|
||||
import VectorSource from 'ol/source/Vector'
|
||||
import Feature from 'ol/Feature'
|
||||
import { Fill, Icon, Stroke, Style } from 'ol/style'
|
||||
import { Point } from 'ol/geom'
|
||||
import Overlay from 'ol/Overlay'
|
||||
import MarkerImg from './markerImage'
|
||||
|
||||
import { MarkerIcon } from './markerEnum'
|
||||
import { fromLonLat } from 'ol/proj'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -21,22 +28,45 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.map = this.$parent.getMapInstance()
|
||||
this.initLayer()
|
||||
this.initMarkers()
|
||||
|
||||
this.initMapClick()
|
||||
this.initMapPopup()
|
||||
this.initMarkers()
|
||||
},
|
||||
methods: {
|
||||
initLayer() {
|
||||
this.markerLayer = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: []
|
||||
}),
|
||||
properties: { name: 'eventMarker' }
|
||||
})
|
||||
this.map.addLayer(this.markerLayer)
|
||||
console.log('%c [ ]-46', 'font-size:13px; background:pink; color:#bf2c9f;', this.markerLayer)
|
||||
},
|
||||
|
||||
// 初始化marker
|
||||
initMarkers() {
|
||||
const markerFeatures = []
|
||||
this.list.forEach(eventItem => {
|
||||
this.map.addOverlay(this.getMarker(eventItem))
|
||||
markerFeatures.push(this.getMarker(eventItem))
|
||||
})
|
||||
this.markerLayer.getSource().addFeatures(markerFeatures)
|
||||
},
|
||||
|
||||
// 初始化地图点击事件
|
||||
initMapClick() {
|
||||
this.map.on('click', () => {
|
||||
this.map.on('click', evt => {
|
||||
const feature = this.map.forEachFeatureAtPixel(evt.pixel, feature => {
|
||||
return feature
|
||||
})
|
||||
const stationInfo = feature && feature.values_ && feature.values_.stationInfo
|
||||
if (stationInfo) {
|
||||
this.showMapPopup(stationInfo)
|
||||
} else {
|
||||
this.closeMapPopup()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
|
@ -48,14 +78,14 @@ export default {
|
|||
autoPanAnimation: {
|
||||
duration: 250
|
||||
},
|
||||
positioning: 'bottom-center'
|
||||
positioning: 'top-center'
|
||||
})
|
||||
this.map.addOverlay(this.popupOverlay)
|
||||
},
|
||||
|
||||
// 显示地图弹窗
|
||||
showMapPopup(stationInfo) {
|
||||
this.popupOverlay.setPosition([stationInfo.lon, stationInfo.lat])
|
||||
this.popupOverlay.setPosition(fromLonLat([stationInfo.lon, stationInfo.lat]))
|
||||
this.currStationInfo = stationInfo // 填充基本信息
|
||||
},
|
||||
|
||||
|
@ -67,22 +97,23 @@ export default {
|
|||
// 获取marker图标
|
||||
getMarker(stationInfo) {
|
||||
const { lon, lat } = stationInfo
|
||||
const img = document.createElement('img')
|
||||
img.src =
|
||||
MarkerImg[
|
||||
['Car', 'GroudMonitoringStation', 'ImsRnStation', 'NuclearFacility', 'Ship'][parseInt(Math.random() * 5)]
|
||||
]
|
||||
img.style.width = '30px'
|
||||
img.style.height = '30px'
|
||||
img.style.cursor = 'pointer'
|
||||
img.addEventListener('click', () => {
|
||||
this.showMapPopup(stationInfo)
|
||||
const markerFeature = new Feature({
|
||||
geometry: new Point(fromLonLat([lon, lat])),
|
||||
stationInfo
|
||||
})
|
||||
|
||||
markerFeature.setStyle(this.getMarkerStyle(stationInfo.stationType))
|
||||
return markerFeature
|
||||
},
|
||||
|
||||
// 获取marker样式
|
||||
getMarkerStyle(type) {
|
||||
const src = MarkerIcon[type]
|
||||
return new Style({
|
||||
image: new Icon({
|
||||
src,
|
||||
scale: 0.8
|
||||
})
|
||||
return new Overlay({
|
||||
position: [lon, lat],
|
||||
element: img,
|
||||
id: stationInfo.stationId,
|
||||
positioning: 'top-center'
|
||||
})
|
||||
},
|
||||
|
||||
|
@ -91,6 +122,13 @@ export default {
|
|||
const overlay = this.map.getOverlayById(markerId)
|
||||
overlay.setPosition(position)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
list() {
|
||||
this.markerLayer.getSource().clear()
|
||||
console.log('%c [ ]-122', 'font-size:13px; background:pink; color:#bf2c9f;', this.map)
|
||||
this.initMarkers()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
</div>
|
||||
<div>
|
||||
<img v-if="active == 1" src="@/assets/images/station-operation/station-operate-active.png" />
|
||||
<img v-else src="@/assets/images/station-operation/station-operate.png" @click="active = 1" />
|
||||
<img v-else src="@/assets/images/station-operation/station-operate.png" @click="onPaneChange(1)" />
|
||||
</div>
|
||||
<div>
|
||||
<img v-if="active == 2" src="@/assets/images/station-operation/filter-station-active.png" />
|
||||
<img v-else src="@/assets/images/station-operation/filter-station.png" @click="active = 2" />
|
||||
<img v-else src="@/assets/images/station-operation/filter-station.png" @click="onPaneChange(2)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -71,7 +71,7 @@
|
|||
<div class="station-operation-infomation-content">
|
||||
<p class="radius-title">Radius</p>
|
||||
<div class="radius-search">
|
||||
<a-input suffix="KM" v-model="radius"></a-input>
|
||||
<a-input suffix="KM" v-model="radius" type="number"></a-input>
|
||||
<a-button type="primary" @click="handleSearchByRadius">
|
||||
Search
|
||||
</a-button>
|
||||
|
@ -81,7 +81,7 @@
|
|||
:scroll="{ y: 298 }"
|
||||
:columns="columns"
|
||||
:data-source="dataSource"
|
||||
rowKey="id"
|
||||
rowKey="index"
|
||||
:pagination="false"
|
||||
:loading="isGettingInfomationList"
|
||||
></a-table>
|
||||
|
@ -106,7 +106,7 @@
|
|||
</div>
|
||||
<span>{{ filterItem.title }}</span>
|
||||
</div>
|
||||
<a-checkbox v-model="filterItem.checked"></a-checkbox>
|
||||
<a-checkbox v-model="filterItem.checked" @change="emitTypeFilter"></a-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider style="background-color: #0a544e; margin: 10px 0 0;"></a-divider>
|
||||
|
@ -221,36 +221,45 @@ import FilterImage from './filterImage'
|
|||
import CustomTree from '@/components/CustomTree/index.vue'
|
||||
import RealTimeDataChart from './RealTimeDataChart.vue'
|
||||
import { postAction } from '../../../api/manage'
|
||||
import { MarkerType } from './markerEnum'
|
||||
|
||||
import { Vector as VectorLayer } from 'ol/layer'
|
||||
|
||||
// Filter中的筛选列表
|
||||
const filterList = [
|
||||
{
|
||||
title: 'IMS RN Station(P)',
|
||||
type: MarkerType.ImsRnStationP,
|
||||
icon: FilterImage.ImsRnStation,
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
title: 'IMS RN Station(G)',
|
||||
type: MarkerType.ImsRnStationG,
|
||||
icon: FilterImage.ImsRnStation,
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
title: 'Nuclear Facilities',
|
||||
type: MarkerType.NuclearFacility,
|
||||
icon: FilterImage.NuclearFacility,
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
title: 'Groud monitoring station',
|
||||
type: MarkerType.GroudMonitoringStation,
|
||||
icon: FilterImage.GroudMonitoringStation,
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
title: 'car',
|
||||
type: MarkerType.Car,
|
||||
icon: FilterImage.Car,
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
title: 'ship',
|
||||
type: MarkerType.Ship,
|
||||
icon: FilterImage.Ship,
|
||||
checked: true
|
||||
}
|
||||
|
@ -280,17 +289,21 @@ const dataQualityList = [
|
|||
const columns = [
|
||||
{
|
||||
title: 'nuclearfaclity',
|
||||
dataIndex: 'nuclearfaclity',
|
||||
dataIndex: 'nuclearFacilityName',
|
||||
width: 100,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: 'station',
|
||||
dataIndex: 'station'
|
||||
dataIndex: 'stationName',
|
||||
width: 70,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: 'distance',
|
||||
dataIndex: 'distance'
|
||||
dataIndex: 'radius',
|
||||
width: 80,
|
||||
ellipsis: true
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -349,7 +362,7 @@ export default {
|
|||
data() {
|
||||
this.columns = columns
|
||||
return {
|
||||
active: 1,
|
||||
active: 2,
|
||||
isFullScreen: false, // 是否处于全屏状态
|
||||
|
||||
checkedKeys: [], // 选中的树节点
|
||||
|
@ -357,7 +370,7 @@ export default {
|
|||
filterList, // 筛选类型列表
|
||||
dataQualityList, // 数据质量列表
|
||||
|
||||
radius: 0, // 距离
|
||||
radius: 5000, // 距离
|
||||
dataSource: [], // Infomation Radius 表格数据源
|
||||
isGettingInfomationList: false,
|
||||
|
||||
|
@ -368,7 +381,9 @@ export default {
|
|||
|
||||
legendList, // 图例列表
|
||||
statusList,
|
||||
showChart: true
|
||||
showChart: true,
|
||||
|
||||
markerList: [] // 要在地图上展示的marker列表
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -400,11 +415,37 @@ export default {
|
|||
this.isFullScreen = !!document.fullscreenElement
|
||||
},
|
||||
|
||||
// 面板改变
|
||||
onPaneChange(active) {
|
||||
this.active = active
|
||||
switch (active) {
|
||||
case 1: // 核设施查询面板
|
||||
this.emitStationChange()
|
||||
break
|
||||
case 2: // 筛选面板
|
||||
this.emitTypeFilter()
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
// 根据 Filter 筛选Marker
|
||||
emitTypeFilter() {
|
||||
this.$emit(
|
||||
'changeMarkerByType',
|
||||
this.filterList.filter(item => item.checked).map(item => item.type)
|
||||
)
|
||||
},
|
||||
|
||||
// 根据 Radius 筛选 Marker
|
||||
emitStationChange() {
|
||||
this.$emit('changeMarker', this.markerList)
|
||||
},
|
||||
|
||||
// 选中全部
|
||||
handleSelectAll() {
|
||||
this.checkedKeys = this.treeData.reduce((prev, curr) => {
|
||||
prev.push(curr.key)
|
||||
prev.push(...curr.children.map(child => child.key))
|
||||
prev.push(curr.stationId)
|
||||
prev.push(...curr.children.map(child => child.stationId))
|
||||
return prev
|
||||
}, [])
|
||||
},
|
||||
|
@ -416,17 +457,61 @@ export default {
|
|||
|
||||
// 根据半径查询台站列表
|
||||
async handleSearchByRadius() {
|
||||
if (this.radius == null || this.radius == undefined) {
|
||||
if (!this.radius) {
|
||||
this.$message.warn('Please Input Radius To Search')
|
||||
return
|
||||
}
|
||||
if (!this.checkedKeys.length) {
|
||||
this.$message.warn('Please Select Stations That Related To')
|
||||
return
|
||||
}
|
||||
|
||||
const stationIds = this.checkedKeys.filter(key => !this.treeData.find(leaf => leaf.stationId == key))
|
||||
try {
|
||||
this.isGettingInfomationList = true
|
||||
const res = await postAction('/jeecg-station-operation/stationOperation/getHitEquList', {
|
||||
const {
|
||||
success,
|
||||
result: { GIS: markerList, table },
|
||||
message
|
||||
} = await postAction('/jeecg-station-operation/stationOperation/getHitEquList', {
|
||||
radius: this.radius,
|
||||
stationIds: []
|
||||
stationIds
|
||||
})
|
||||
console.log('%c [ ]-486', 'font-size:13px; background:pink; color:#bf2c9f;', res)
|
||||
if (success) {
|
||||
const data = table.flat()
|
||||
data.forEach((item, index) => {
|
||||
item.radius = parseFloat(item.radius).toFixed(3)
|
||||
item.index = index
|
||||
})
|
||||
this.dataSource = data // 设置Infomation表格内容
|
||||
|
||||
const stationList = [] // 台站列表
|
||||
markerList.forEach(markerItem => { // 返回的数据类型不符合要求,根据stationId判断是否是台站,增加台站类型和转换字段,以便进行marker的绘制
|
||||
if (markerItem.stationId) {
|
||||
// 是台站
|
||||
markerItem.stationType = MarkerType.ImsRnStationG
|
||||
stationList.push(markerItem)
|
||||
} else {
|
||||
// 是核设施
|
||||
markerItem.stationType = MarkerType.NuclearFacility
|
||||
markerItem.lon = markerItem.longitude
|
||||
markerItem.lat = markerItem.latitude
|
||||
}
|
||||
})
|
||||
|
||||
if (markerList.length) {
|
||||
// 自动移动到搜出来的第一个台站那
|
||||
const firstMarker = markerList[0]
|
||||
this.$parent.panTo([firstMarker.lon, firstMarker.lat])
|
||||
}
|
||||
|
||||
this.markerList = markerList
|
||||
this.emitStationChange()
|
||||
|
||||
this.drawCircle(stationList)
|
||||
} else {
|
||||
this.$message.error(message)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
|
@ -434,6 +519,16 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// 绘制圆圈
|
||||
drawCircle(stationList) {
|
||||
this.circleLayer = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: []
|
||||
}),
|
||||
properties: { name: 'eventMarker' }
|
||||
})
|
||||
},
|
||||
|
||||
// 打开分析弹窗
|
||||
handleOpenAnalyzeModal() {
|
||||
this.dataStatusModalVisible = true
|
||||
|
|
24
src/views/stationOperation/components/markerEnum.js
Normal file
24
src/views/stationOperation/components/markerEnum.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import Car from '@/assets/images/station-operation/car.png'
|
||||
import GroudMonitoringStation from '@/assets/images/station-operation/groud-monitoring-station.png'
|
||||
import ImsRnStation from '@/assets/images/station-operation/ims-rn-station.png'
|
||||
import NuclearFacility from '@/assets/images/station-operation/nuclear-facility.png'
|
||||
import Ship from '@/assets/images/station-operation/ship.png'
|
||||
|
||||
export const MarkerType = {
|
||||
Car: 'Car',
|
||||
GroudMonitoringStation: 'Groud monitoring station',
|
||||
ImsRnStationP: 'IMS STATION',
|
||||
ImsRnStationG: 'IMS STATION',
|
||||
NuclearFacility: 'Nuclear Facility',
|
||||
Ship: 'Ship'
|
||||
|
||||
}
|
||||
|
||||
export const MarkerIcon = {
|
||||
[MarkerType.Car]: Car,
|
||||
[MarkerType.GroudMonitoringStation]: GroudMonitoringStation,
|
||||
[MarkerType.ImsRnStationP]: ImsRnStation,
|
||||
[MarkerType.ImsRnStationG]: ImsRnStation,
|
||||
[MarkerType.NuclearFacility]: NuclearFacility,
|
||||
[MarkerType.Ship]: Ship
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import Car from '@/assets/images/station-operation/car.png'
|
||||
import GroudMonitoringStation from '@/assets/images/station-operation/groud-monitoring-station.png'
|
||||
import ImsRnStation from '@/assets/images/station-operation/ims-rn-station.png'
|
||||
import NuclearFacility from '@/assets/images/station-operation/nuclear-facility.png'
|
||||
import Ship from '@/assets/images/station-operation/ship.png'
|
||||
|
||||
export default {
|
||||
Car,
|
||||
GroudMonitoringStation,
|
||||
ImsRnStation,
|
||||
NuclearFacility,
|
||||
Ship
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div class="station-operation">
|
||||
<!-- 左侧列表 -->
|
||||
<div class="date-container">
|
||||
<div class="data-container">
|
||||
<a-collapse v-model="activeKey" expandIconPosition="right" accordion>
|
||||
<template slot="expandIcon">
|
||||
<img src="@/assets/images/station-operation/toggle.png" alt="" />
|
||||
</template>
|
||||
<!-- All Date -->
|
||||
<!-- All Data -->
|
||||
<a-collapse-panel key="1">
|
||||
<template slot="header">
|
||||
<div class="title">
|
||||
<div class="title-text">All Date</div>
|
||||
<div class="title-text">All Data</div>
|
||||
<div class="title-rect">
|
||||
<span></span>
|
||||
<span></span>
|
||||
|
@ -36,7 +36,7 @@
|
|||
ref="scrollContainerRef"
|
||||
direction="verticle"
|
||||
:scrollContainer="getScrollContainer"
|
||||
class="date-list has-search"
|
||||
class="data-list has-search"
|
||||
:class="{
|
||||
'show-search': searchPlacementVisible
|
||||
}"
|
||||
|
@ -79,63 +79,31 @@
|
|||
</a-row>
|
||||
<!-- 筛选结束 -->
|
||||
</div>
|
||||
<div class="date-list-content">
|
||||
<a-spin v-if="isGettingDateList"></a-spin>
|
||||
<div class="data-list-content">
|
||||
<a-spin v-if="isGettingDataList"></a-spin>
|
||||
<template>
|
||||
<RecycleScroller
|
||||
ref="customScrollContainerRef"
|
||||
class="scroller"
|
||||
:items="dateList"
|
||||
:item-size="129"
|
||||
:items="dataList"
|
||||
:item-size="108"
|
||||
key-field="stationId"
|
||||
v-slot="{ item }"
|
||||
>
|
||||
<h4 class="date-list-item-title">
|
||||
{{ item.stationName }}
|
||||
</h4>
|
||||
<div class="date-list-item-container">
|
||||
<div class="date-list-item-content">
|
||||
<div class="date-list-item-children">
|
||||
<div class="date-list-item-child">
|
||||
<label>Station Type:</label>
|
||||
<span>{{ item.stationType }}</span>
|
||||
</div>
|
||||
<div class="date-list-item-child" style="word-break: break-all">
|
||||
<label>Altitude:</label>
|
||||
<span>{{ item.altitude }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="date-list-item-children">
|
||||
<div class="date-list-item-child">
|
||||
<label>Lon And Lat:</label>
|
||||
<span>{{ Number(item.lon).toFixed(6) }} {{ Number(item.lat).toFixed(6) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="date-list-item-children">
|
||||
<div class="date-list-item-child">
|
||||
<label>Status:</label>
|
||||
<span class="green">{{ item.status }}</span>
|
||||
</div>
|
||||
<div class="date-list-item-child">
|
||||
<label>Signal:</label>
|
||||
<span class="green">{{ item.signal }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DataListItem :item="item" @click.native="locateFacility(item)"></DataListItem>
|
||||
</RecycleScroller>
|
||||
<custom-empty v-if="!dateList.length" style="margin-top: 40px"></custom-empty>
|
||||
<custom-empty v-if="!dataList.length" style="margin-top: 40px"></custom-empty>
|
||||
</template>
|
||||
</div>
|
||||
<div class="shadow"></div>
|
||||
</ScrollContainer>
|
||||
</a-collapse-panel>
|
||||
<!-- All Date 结束 -->
|
||||
<!-- Focus Date -->
|
||||
<!-- All Data 结束 -->
|
||||
<!-- Focus Data -->
|
||||
<a-collapse-panel key="2">
|
||||
<template slot="header">
|
||||
<div class="title">
|
||||
<div class="title-text" style="width: 180px">Focus Date</div>
|
||||
<div class="title-text" style="width: 180px">Focus Data</div>
|
||||
<div class="title-rect">
|
||||
<span></span>
|
||||
<span></span>
|
||||
|
@ -146,59 +114,33 @@
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<ScrollContainer ref="scrollContainer2Ref" direction="verticle" class="date-list">
|
||||
<div class="date-list-content">
|
||||
<a-spin v-if="isGettingFollowedDateList"></a-spin>
|
||||
<ScrollContainer ref="scrollContainer2Ref" direction="verticle" class="data-list">
|
||||
<div class="data-list-content">
|
||||
<a-spin v-if="isGettingFollowedDataList"></a-spin>
|
||||
<template v-else>
|
||||
<div class="date-list-item" v-for="item of followedDateList" :key="item.id">
|
||||
<h4 class="date-list-item-title">
|
||||
{{ item.stationName }}
|
||||
</h4>
|
||||
<div class="date-list-item-container">
|
||||
<div class="date-list-item-content">
|
||||
<div class="date-list-item-children">
|
||||
<div class="date-list-item-child">
|
||||
<label>Station Type:</label>
|
||||
<span>{{ item.stationType }}</span>
|
||||
</div>
|
||||
<div class="date-list-item-child" style="word-break: break-all">
|
||||
<label>Altitude:</label>
|
||||
<span>{{ item.altitude }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="date-list-item-children">
|
||||
<div class="date-list-item-child">
|
||||
<label>Lon And Lat:</label>
|
||||
<span>{{ Number(item.lon).toFixed(6) }} {{ Number(item.lat).toFixed(6) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="date-list-item-children">
|
||||
<div class="date-list-item-child">
|
||||
<label>Status:</label>
|
||||
<span class="green">{{ item.status }}</span>
|
||||
</div>
|
||||
<div class="date-list-item-child">
|
||||
<label>Signal:</label>
|
||||
<span class="green">{{ item.signal }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<custom-empty v-if="!followedDateList.length" style="margin-top: 40px"></custom-empty>
|
||||
<DataListItem
|
||||
v-for="item of followedDataList"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
@click.native="locateFacility(item)"
|
||||
></DataListItem>
|
||||
<custom-empty v-if="!followedDataList.length" style="margin-top: 40px"></custom-empty>
|
||||
</template>
|
||||
</div>
|
||||
<div class="shadow"></div>
|
||||
</ScrollContainer>
|
||||
</a-collapse-panel>
|
||||
<!-- Focus Date 结束 -->
|
||||
<!-- Focus Data 结束 -->
|
||||
</a-collapse>
|
||||
</div>
|
||||
<!-- 右侧地图 -->
|
||||
<div class="station-operation-map">
|
||||
<Map token="AAPK2b935e8bbf564ef581ca3c6fcaa5f2a71ZH84cPqqFvyz3KplFRHP8HyAwJJkh6cnpcQ-qkWh5aiyDQsGJbsXglGx0QM2cPm">
|
||||
<MapMarker v-if="dateList.length" :list="dateList" />
|
||||
<MapPane :treeData="treeData" />
|
||||
<Map
|
||||
ref="map"
|
||||
token="AAPK2b935e8bbf564ef581ca3c6fcaa5f2a71ZH84cPqqFvyz3KplFRHP8HyAwJJkh6cnpcQ-qkWh5aiyDQsGJbsXglGx0QM2cPm"
|
||||
>
|
||||
<MapMarker :list="markerList" />
|
||||
<MapPane :treeData="treeData" @changeMarker="onChangeMarker" @changeMarkerByType="onChangeMarkerByType" />
|
||||
</Map>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -207,6 +149,7 @@
|
|||
import Map from './components/Map.vue'
|
||||
import MapMarker from './components/MapMarker.vue'
|
||||
import MapPane from './components/MapPane.vue'
|
||||
import DataListItem from './components/DataListItem.vue'
|
||||
import ScrollContainer from '@/components/ScrollContainer/index.vue'
|
||||
import { getAction } from '../../api/manage'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
@ -216,17 +159,19 @@ export default {
|
|||
Map,
|
||||
MapMarker,
|
||||
MapPane,
|
||||
ScrollContainer
|
||||
ScrollContainer,
|
||||
DataListItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeKey: '1',
|
||||
|
||||
isGettingDateList: false,
|
||||
isGettingFollowedDateList: false,
|
||||
isGettingDataList: false,
|
||||
isGettingFollowedDataList: false,
|
||||
|
||||
dateList: [],
|
||||
followedDateList: [], // 关注
|
||||
dataList: [], // 左侧All Data 列表
|
||||
followedDataList: [], // 关注
|
||||
markerList: [], // 地图上标记点列表
|
||||
|
||||
searchPlacementVisible: false, // 搜索栏占位是否显示
|
||||
|
||||
|
@ -255,10 +200,11 @@ export default {
|
|||
// 获取站点列表
|
||||
async getStationList() {
|
||||
try {
|
||||
this.isGettingDateList = true
|
||||
this.isGettingDataList = true
|
||||
const res = await getAction('/jeecg-station-operation/stationOperation/findList')
|
||||
this.dateList = res
|
||||
this.originalDateList = cloneDeep(res)
|
||||
this.originalDataList = res // 保留初始版本
|
||||
this.dataList = cloneDeep(res)
|
||||
this.markerList = cloneDeep(res)
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$refs.scrollContainerRef.checkScrollEnd()
|
||||
|
@ -266,16 +212,16 @@ export default {
|
|||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
this.isGettingDateList = false
|
||||
this.isGettingDataList = false
|
||||
}
|
||||
},
|
||||
|
||||
// 获取已关注站点列表
|
||||
async getFollowedStationList() {
|
||||
try {
|
||||
this.isGettingFollowedDateList = true
|
||||
this.isGettingFollowedDataList = true
|
||||
const res = await getAction('/jeecg-station-operation/sysUserFocusStation/findList')
|
||||
this.followedDateList = res
|
||||
this.followedDataList = res
|
||||
|
||||
const scrollContainer2Ref = this.$refs.scrollContainer2Ref
|
||||
if (scrollContainer2Ref) {
|
||||
|
@ -286,7 +232,7 @@ export default {
|
|||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
this.isGettingFollowedDateList = false
|
||||
this.isGettingFollowedDataList = false
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -304,18 +250,18 @@ export default {
|
|||
async getStationTree() {
|
||||
try {
|
||||
const { success, result, message } = await getAction('/stationOperation/findTree')
|
||||
if(success) {
|
||||
result.forEach(item => item.stationCode = item.code)
|
||||
if (success) {
|
||||
result.forEach(item => (item.stationCode = item.code))
|
||||
this.treeData = result
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.$message.error(message)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
},
|
||||
|
||||
// 显示搜索栏
|
||||
handleShowSearch() {
|
||||
if (this.filterVisible) {
|
||||
this.searchVisible = true
|
||||
|
@ -343,14 +289,14 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// 左侧 All Date 筛选
|
||||
// 左侧 All Data 筛选
|
||||
onFilterChange() {
|
||||
this.dateList = this.originalDateList.filter(dateItem => {
|
||||
this.dataList = this.originalDataList.filter(dataItem => {
|
||||
const filterSearchText =
|
||||
!this.filter.searchText ||
|
||||
-1 !== dateItem.stationName.toLowerCase().indexOf(this.filter.searchText.toLowerCase())
|
||||
const filterStatus = !this.filter.status || this.filter.status == dateItem.status
|
||||
const filterType = !this.filter.stationType || this.filter.type == dateItem.stationType
|
||||
-1 !== dataItem.stationName.toLowerCase().indexOf(this.filter.searchText.toLowerCase())
|
||||
const filterStatus = !this.filter.status || this.filter.status == dataItem.status
|
||||
const filterType = !this.filter.stationType || this.filter.type == dataItem.stationType
|
||||
|
||||
return filterSearchText && filterStatus && filterType
|
||||
})
|
||||
|
@ -360,6 +306,32 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
// 定位台站
|
||||
locateFacility(stationItem) {
|
||||
const find = this.markerList.find(
|
||||
markerItem => markerItem.stationId == stationItem.stationId && markerItem.stationType == stationItem.stationType
|
||||
)
|
||||
if (!find) {
|
||||
// 如果未显示,则不定位
|
||||
return
|
||||
}
|
||||
const { lon, lat } = stationItem
|
||||
this.$refs.map.panTo([lon, lat])
|
||||
},
|
||||
|
||||
// 修改地图上的marker列表
|
||||
onChangeMarker(markerList) {
|
||||
this.markerList = markerList
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据类型筛选地图上的marker列表
|
||||
* @param {Array<string>} typeList
|
||||
*/
|
||||
onChangeMarkerByType(typeList) {
|
||||
this.markerList = this.originalDataList.filter(item => typeList.includes(item.stationType))
|
||||
},
|
||||
|
||||
getScrollContainer() {
|
||||
return this.$refs.customScrollContainerRef.$el
|
||||
},
|
||||
|
@ -374,7 +346,7 @@ export default {
|
|||
.station-operation {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
.date-container {
|
||||
.data-container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
@ -419,7 +391,7 @@ export default {
|
|||
position: relative;
|
||||
}
|
||||
&.ant-motion-collapse-legacy {
|
||||
.date-list {
|
||||
.data-list {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +477,7 @@ export default {
|
|||
}
|
||||
|
||||
// 左侧列表内容
|
||||
.date-list {
|
||||
.data-list {
|
||||
width: 100%;
|
||||
margin-right: 2px;
|
||||
padding: 2px 0 10px 7px;
|
||||
|
@ -530,7 +502,7 @@ export default {
|
|||
}
|
||||
|
||||
&.has-search {
|
||||
.date-list-content {
|
||||
.data-list-content {
|
||||
transition: height 0.3s ease-in-out;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
@ -542,76 +514,11 @@ export default {
|
|||
height: @searchHeight;
|
||||
}
|
||||
|
||||
.date-list-content {
|
||||
.data-list-content {
|
||||
height: calc(100% - @searchHeight);
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
width: 322px;
|
||||
&-title {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-family: Arial;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
padding: 10px 10px 10px 14px;
|
||||
flex: 1;
|
||||
color: #6ebad0;
|
||||
background: url(~@/assets/images/station-operation/date-item-bg.png) center no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.date-list-item-children {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.date-list-item-child {
|
||||
color: #fff;
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:nth-child(2n) {
|
||||
width: 110px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
label {
|
||||
color: #6ebad0;
|
||||
font-family: Arial;
|
||||
}
|
||||
|
||||
span {
|
||||
margin-left: 10px;
|
||||
&.green {
|
||||
color: #0cff00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shadow {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user