AnalysisSystemForRadionucli.../src/views/stationOperation/components/MapPane.vue

1238 lines
32 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div :class="'map-pane' + (active == 1 ? ' is-station' : '')">
<!-- 操作栏开始 -->
<div class="map-pane-operators">
<div>
<img
v-if="isFullScreen"
src="@/assets/images/station-operation/full-screen-active.png"
@click="handleExitFullScreen"
/>
<img v-else src="@/assets/images/station-operation/full-screen.png" @click="handleFullScreen" />
</div>
<div class="map-pane-operators-main-operator">
<div>
<img v-if="dataStatusModalVisible" src="@/assets/images/station-operation/analyze-active.png" />
<img v-else src="@/assets/images/station-operation/analyze.png" @click="handleOpenAnalyzeModal" />
</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="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="onPaneChange(2)" />
</div>
</div>
<div class="map-pane-operators-zoom">
<div class="map-pane-operators-zoom-map-plus" @click="handlePlus"></div>
<div class="map-pane-operators-zoom-map-minus" @click="handleMinus"></div>
</div>
</div>
<!-- 操作栏结束 -->
<!-- 主体部分开始 -->
<div class="map-pane-content">
<!-- 站点操作 -->
<div class="station-operation" v-show="active == 1">
<div class="station-operation-stations">
<div class="map-pane-content-header">
Stations
</div>
<div class="map-pane-content-main">
<div class="station-operation-stations-selection">
<a-space>
<a-button class="select-all" type="primary" @click="handleSelectAll">Select All</a-button>
<a-button class="clear-selection" type="primary" @click="handleClearSelection"
>Clear Selection</a-button
>
</a-space>
</div>
<a-divider style="background-color: #0a544e; margin: 10px 0 0;"></a-divider>
<!-- 站点选择树 -->
<div class="station-list-tree">
<custom-tree
v-model="checkedKeys"
:tree-data="treeData"
:replaceFields="{ children: 'children', title: 'stationCode', key: 'stationId' }"
></custom-tree>
</div>
<!-- 站点选择树 结束 -->
</div>
</div>
<div class="station-operation-infomation">
<div class="map-pane-content-header">
Infomation
</div>
<div class="map-pane-content-main">
<div class="station-operation-infomation-content">
<p class="radius-title">Radius</p>
<div class="radius-search">
<a-input suffix="KM" v-model="radius" type="number"></a-input>
<a-button type="primary" @click="handleSearchByRadius">
Search
</a-button>
</div>
<div class="radius-table">
<a-table
:scroll="{ y: 298 }"
:columns="columns"
:data-source="dataSource"
rowKey="index"
:pagination="false"
:loading="isGettingInfomationList"
></a-table>
</div>
</div>
</div>
</div>
</div>
<!-- 站点操作结束 -->
<!-- 站点筛选 -->
<div class="station-filter" v-show="active == 2">
<div class="map-pane-content-header">
Filter
</div>
<div class="map-pane-content-main">
<div class="station-filter-list">
<div
class="station-filter-item"
v-for="filterItem in filterList"
:key="filterItem.title"
@click="onStationTypeFilterChange(filterItem)"
>
<div class="station-filter-item-main">
<div>
<img :src="filterItem.icon" />
</div>
<span>{{ filterItem.title }}</span>
</div>
<a-checkbox v-model="filterItem.checked"></a-checkbox>
</div>
</div>
<a-divider style="background-color: #0a544e; margin: 10px 0 0;"></a-divider>
<!-- 数据质量类型 -->
<div class="station-data-quality-list">
<div
class="station-data-quality-list-item"
v-for="(stateItem, index) in dataQualityList"
:key="index"
@click="onDataQualityFilterChange(stateItem)"
>
<div>
<img :src="stateItem.icon" alt="" />
<span>{{ stateItem.title }}</span>
</div>
<a-checkbox v-model="stateItem.checked"></a-checkbox>
</div>
</div>
<!-- 数据质量结束 -->
</div>
</div>
<!-- 站点筛选结束 -->
</div>
<!-- 主体部分结束 -->
<!-- 数据监控状态弹窗开始 -->
<custom-modal
v-model="dataStatusModalVisible"
enableFullScreen
:bodyStyle="{ padding: '15px 0 10px' }"
title="Data Recevice status Monitoring"
:width="1230"
:showFooter="false"
@fullscreen="onModalFullScreen"
>
<div class="data-receive-status">
<!-- 左侧配置栏 -->
<div class="data-receive-status-list" :class="{ open: leftPaneShow }">
<div class="data-receive-status-list-container">
<div class="data-receive-status-list-item">
<div class="title">
<span>
Particulate Station
</span>
<img src="@/assets/images/station-operation/toggle.png" @click="leftPaneShow = !leftPaneShow" />
</div>
<div class="content">
<custom-tree
v-model="dataStatusCheckedKeys"
:tree-data="treeData"
:replaceFields="{ children: 'children', title: 'stationCode', key: 'stationId' }"
></custom-tree>
</div>
</div>
<div class="data-receive-status-list-item">
<div class="title">
<span>
Attribute Configuration
</span>
<img src="@/assets/images/station-operation/toggle.png" @click="leftPaneShow = !leftPaneShow" />
</div>
<div class="content">
<a-form-model class="attribute-form" layout="vertical">
<a-form-model-item label="Cache time">
<a-input-number type="number" v-model="dataRecieveStatusModel.cacheTime" :min="0"></a-input-number>
<span>day</span>
</a-form-model-item>
<a-form-model-item label="Scale interval">
<a-input-number
type="number"
v-model="dataRecieveStatusModel.scaleInterval"
:min="0"
></a-input-number>
<span>min</span>
</a-form-model-item>
<a-form-model-item label="Timeline length">
<a-input-number
type="number"
v-model="dataRecieveStatusModel.timelineLength"
:min="0"
></a-input-number>
<span>min</span>
</a-form-model-item>
<a-form-model-item label="Update interval time">
<a-input-number
type="number"
v-model="dataRecieveStatusModel.updateIntervalTime"
:min="0"
></a-input-number>
<span>min</span>
</a-form-model-item>
<div class="attribute-form-footer">
<a-button type="primary" @click="onSaveDataRecieveSettings" :loading="isSavingDataRecieveSettings">
SAVE
</a-button>
</div>
</a-form-model>
</div>
</div>
</div>
<!-- 展开左侧配置栏按钮开始 -->
<div class="data-receive-status-list-toggle-show-btn" v-if="!leftPaneShow">
<img src="@/assets/images/station-operation/toggle-2.png" @click="leftPaneShow = true" />
</div>
<!-- 展开左侧配置栏按钮结束 -->
</div>
<!-- 左侧配置栏结束 -->
<!-- 右侧图表展示栏 -->
<div class="data-receive-status-chart" :class="{ 'on-screen': !leftPaneShow }">
<!-- 图例 -->
<div class="legend">
<div class="legend-item" v-for="(legend, index) in legendList" :key="index">
<span class="legend-item-color" :style="{ backgroundColor: legend.color }"></span>
<span>{{ legend.title }}</span>
</div>
</div>
<!-- 图例结束 -->
<template v-if="showChart">
<template v-for="(item, index) in statusList">
<RealTimeDataChart :legendList="legendList" :title="item.title" :key="index" />
<a-divider :key="index + '_divider'" v-if="index !== statusList.length - 1"></a-divider>
</template>
</template>
</div>
<!-- 右侧图表展示栏结束 -->
</div>
</custom-modal>
<!-- 数据监控状态弹窗结束 -->
</div>
</template>
<script>
import CustomModal from '@/components/CustomModal/index.vue'
import CustomTree from '@/components/CustomTree/index.vue'
import RealTimeDataChart from './RealTimeDataChart.vue'
import { getAction, postAction } from '../../../api/manage'
import { MarkerType, FilterIcon } 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 = [
{
title: 'IMS RN Station(P)',
type: MarkerType.ImsRnStationP,
icon: FilterIcon[MarkerType.ImsRnStationP],
checked: true
},
{
title: 'IMS RN Station(G)',
type: MarkerType.ImsRnStationG,
icon: FilterIcon[MarkerType.ImsRnStationG],
checked: true
},
{
title: 'NRL',
type: MarkerType.NRL,
icon: FilterIcon[MarkerType.NRL],
checked: true
},
{
title: 'Nuclear Facilities',
type: MarkerType.NuclearFacility,
icon: FilterIcon[MarkerType.NuclearFacility],
checked: true
},
{
title: 'Groud monitoring station',
type: MarkerType.GroudMonitoringStation,
icon: FilterIcon[MarkerType.GroudMonitoringStation],
checked: true
},
{
title: 'car',
type: MarkerType.Car,
icon: FilterIcon[MarkerType.Car],
checked: true
},
{
title: 'ship',
type: MarkerType.Ship,
icon: FilterIcon[MarkerType.Ship],
checked: true
}
]
// Filter中的数据质量列表
const dataQualityList = [
{
title: 'Excellent data quality',
icon: FilterIcon.State1,
checked: true
},
{
title: 'Good data quality',
icon: FilterIcon.State2,
checked: true
},
{
title: 'Poor data quality',
icon: FilterIcon.State3,
checked: true
},
{
title: 'Signal interruption',
icon: FilterIcon.State4,
checked: true
}
]
// infomation-radius 表格列
const columns = [
{
title: 'nuclearfaclity',
dataIndex: 'nuclearFacilityName',
width: 100,
ellipsis: true
},
{
title: 'station',
dataIndex: 'stationName',
width: 70,
ellipsis: true
},
{
title: 'distance',
dataIndex: 'radius',
width: 80,
ellipsis: true
}
]
const legendList = [
{
title: 'SPHDPREL',
color: '#17a840'
},
{
title: 'SPHDF',
color: '#0cbfb0'
},
{
title: 'QC',
color: '#1c82eb'
},
{
title: 'GASBKPHDPREL',
color: '#d3ad16'
},
{
title: 'GASBKPHDF',
color: '#db6423'
},
{
title: 'SOH/MET',
color: '#8852da'
}
]
// Attribute Configuration 检验规则(自定义非a-form校验)
const rules = {
cacheTime: {
required: true,
message: 'Please Input Cache Time'
},
scaleInterval: {
required: true,
message: 'Please Input Scale Interval'
},
timelineLength: {
required: true,
message: 'Please Input Timeline Length'
},
updateIntervalTime: {
required: true,
message: 'Please Input Update Interval'
}
}
export default {
props: {
panMovePix: {
type: Number,
default: 500
},
treeData: {
type: Array
}
},
components: {
CustomModal,
CustomTree,
RealTimeDataChart
},
data() {
this.columns = columns
return {
active: 2,
isFullScreen: false, // 是否处于全屏状态
checkedKeys: [], // 选中的树节点
filterList, // 筛选类型列表
dataQualityList, // 数据质量列表
radius: 5000, // 距离
dataSource: [], // Infomation Radius 表格数据源
isGettingInfomationList: false,
dataStatusModalVisible: false, // 分析弹窗是否可见
initialDataRecieveSettings: {}, // 初始未改变的数据接收状态设置
dataStatusCheckedKeys: [], // 分析弹窗-左侧树选中的keys
dataRecieveStatusModel: {
cacheTime: 15,
scaleInterval: 120,
timelineLength: 1440,
updateIntervalTime: 5
}, // 数据接收状态配置
isSavingDataRecieveSettings: false,
leftPaneShow: true, // 左侧抽屉
legendList, // 图例列表
statusList: [], // 数据接收状态列表
isGettingStatusList: false,
showChart: true,
markerList: [] // 要在地图上展示的marker列表
}
},
created() {
this.initParentMapProps()
document.addEventListener('fullscreenchange', this.onFullScreenChange)
this.stationList = []
this.getDataRecieveSettings()
},
destroyed() {
document.removeEventListener('fullscreenchange', this.onFullScreenChange)
},
methods: {
initParentMapProps() {
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() {
const ele = document.querySelector('.station-operation')
ele.requestFullscreen()
},
handleExitFullScreen() {
document.exitFullscreen()
},
onFullScreenChange() {
this.isFullScreen = !!document.fullscreenElement
},
// 面板改变
onPaneChange(active) {
this.active = active
const source = this.circleLayer.getSource()
source.clear() // 清理图层
switch (active) {
case 1: // 核设施查询面板
this.drawCircle()
this.emitStationChange()
break
case 2: // 筛选面板
this.emitFilter()
break
}
},
// 根据 Filter 筛选Marker
emitFilter() {
const filterType = this.filterList.filter(item => item.checked).map(item => item.type)
const filterDataQuality = this.dataQualityList.filter(item => item.checked).map(item => item.title)
this.$emit('filterMarker', {
filterType,
filterDataQuality
})
},
// 根据 Radius 筛选 Marker
emitStationChange() {
this.$emit('changeMarker', this.markerList)
},
// 选中全部
handleSelectAll() {
this.checkedKeys = this.treeData.reduce((prev, curr) => {
prev.push(curr.stationId)
prev.push(...curr.children.map(child => child.stationId))
return prev
}, [])
},
// 反选全部
handleClearSelection() {
this.checkedKeys = []
},
// Filter 过滤单个类型
onStationTypeFilterChange(filterItem) {
filterItem.checked = !filterItem.checked
this.emitFilter()
},
// 数据质量过滤
onDataQualityFilterChange(stateItem) {
stateItem.checked = !stateItem.checked
this.emitFilter()
},
// 根据半径查询台站列表
async handleSearchByRadius() {
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 => -1 == key.toString().indexOf('root_'))
try {
this.isGettingInfomationList = true
const {
success,
result: { GIS: markerList, table },
message
} = await postAction('/jeecg-station-operation/stationOperation/getHitEquList', {
radius: this.radius,
stationIds
})
if (success) {
const source = this.circleLayer.getSource()
source.clear() // 清理图层
if (table) {
const data = table.flat()
data.forEach((item, index) => {
item.radius = parseFloat(item.radius).toFixed(3)
item.index = index
})
this.dataSource = data // 设置Infomation表格内容
this.stationList = [] // 台站列表
markerList.forEach(markerItem => {
// 返回的数据类型不符合要求根据stationId判断是否是台站增加台站类型和转换字段以便进行marker的绘制
if (markerItem.stationId) {
// 是台站
markerItem.stationType = MarkerType.ImsRnStationG
this.stationList.push(markerItem)
} else {
// 是核设施
markerItem.stationType = MarkerType.NuclearFacility
markerItem.lon = markerItem.longitude
markerItem.lat = markerItem.latitude
markerItem.stationId = markerItem.facilityId
}
})
if (markerList.length) {
// 自动移动到搜出来的第一个台站那
const firstMarker = markerList[0]
this.$parent.panTo([firstMarker.lon, firstMarker.lat])
}
this.markerList = markerList
this.emitStationChange()
this.drawCircle()
} else {
this.dataSource = []
this.markerList = []
this.emitStationChange()
}
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isGettingInfomationList = false
}
},
// 绘制圆圈
drawCircle() {
const source = this.circleLayer.getSource()
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
},
// 打开分析弹窗
handleOpenAnalyzeModal() {
this.dataStatusModalVisible = true
},
// 地图放大
handlePlus() {
const zoom = this.getZoom()
if (zoom < this.maxZoom) {
this.setZoom(zoom + 1)
}
},
// 地图缩小
handleMinus() {
const zoom = this.getZoom()
if (zoom > this.minZoom) {
this.setZoom(zoom - 1)
}
},
// 弹窗最大化
onModalFullScreen() {
this.showChart = false
this.$nextTick(() => {
this.showChart = true
})
},
// 保存数据接收状态的配置
async onSaveDataRecieveSettings() {
if (!this.dataStatusCheckedKeys.length) {
this.$message.warn('Please Select Particulate Station')
return
}
try {
await this.validateForm(this.dataRecieveStatusModel, rules)
try {
const stationIds = this.dataStatusCheckedKeys.filter(key => -1 == key.toString().indexOf('root_'))
this.isSavingDataRecieveSettings = true
const { success, message } = await postAction(
'/jeecg-station-operation/sysUserFocusStation/saveUserFocusByUserId',
{
stationIds,
...this.dataRecieveStatusModel
}
)
if (success) {
this.$message.success('Save Success')
await this.getDataRecieveSettings()
this.startGetDataReceiveStatusList()
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isSavingDataRecieveSettings = false
}
} catch (error) {
this.$message.warn(error)
}
},
// 验证表单
validateForm(model, rules) {
return new Promise((resolve, reject) => {
const rulesKey = Object.keys(rules)
for (const key of rulesKey) {
const rule = rules[key],
value = model[key]
if (rule.required && !value) {
reject(rule.message)
return
}
}
resolve()
})
},
// 获取数据接收状态配置
async getDataRecieveSettings() {
try {
const { success, result, message } = await getAction(
'/jeecg-station-operation/sysUserFocusStation/findUserFocusByUserId',
{
userId: this.$store.getters.userInfo.id
}
)
if (success) {
this.initialDataRecieveSettings = result
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
this.$message.error(error)
}
},
// 开始获取数据状态列表的定时器
startGetDataReceiveStatusList() {
if (this.timer) {
clearInterval(this.timer)
}
this.getDataRecieveStatusList()
this.timer = setInterval(() => {
this.getDataRecieveStatusList()
}, this.dataRecieveStatusModel.updateIntervalTime * 60 * 1000)
},
// 获取数据接收状态列表
async getDataRecieveStatusList() {
try {
console.log('%c [ ]-777', 'font-size:13px; background:pink; color:#bf2c9f;', this.initialDataRecieveSettings)
this.isGettingStatusList = true
const res = await getAction('/jeecg-station-operation/stationOperation/getDataReceivingStatus', {
userId: this.$store.getters.userInfo.id
})
console.log('%c [ res ]-640', 'font-size:13px; background:pink; color:#bf2c9f;', res)
} catch (error) {
console.error(error)
} finally {
this.isGettingStatusList = false
}
}
},
watch: {
dataStatusModalVisible(val) {
if (val) {
this.dataStatusCheckedKeys = this.initialDataRecieveSettings.sysUserFocusStations.map(item =>
parseInt(item.stationId)
)
this.dataRecieveStatusModel = {
cacheTime: this.initialDataRecieveSettings.cacheTime,
scaleInterval: this.initialDataRecieveSettings.scaleInterval,
timelineLength: this.initialDataRecieveSettings.timelineLength,
updateIntervalTime: this.initialDataRecieveSettings.updateIntervalTime
}
this.startGetDataReceiveStatusList()
} else {
clearInterval(this.timer)
}
}
}
}
</script>
<style lang="less" scoped>
// 地图右侧操作栏
.map-pane {
position: absolute;
right: 10px;
top: 10px;
max-height: calc(100% - 20px);
z-index: 1;
display: flex;
gap: 15px;
&.is-station {
height: calc(100% - 20px);
}
// 操作栏
&-operators {
user-select: none;
img {
cursor: pointer;
}
&-main-operator {
margin-top: 5px;
div {
width: 30px;
height: 30px;
&:not(:first-child) {
margin-top: -1px;
}
}
}
&-zoom {
margin-top: 10px;
div {
width: 30px;
height: 30px;
cursor: pointer;
}
&-map-plus {
background: url(~@/assets/images/station-operation/map-plus.png) center no-repeat;
background-size: 100% 100%;
&:active {
background-image: url(~@/assets/images/station-operation/map-plus-active.png);
}
}
&-map-minus {
margin-top: -1px;
background: url(~@/assets/images/station-operation/map-minus.png) center no-repeat;
background-size: 100% 100%;
&:active {
background-image: url(~@/assets/images/station-operation/map-minus-active.png);
}
}
}
}
// 主体部分
&-content {
width: 285px;
overflow: auto;
border: 1px solid #0a544e;
.map-pane-content-header {
padding-left: 20px;
height: 40px;
line-height: 40px;
background-color: #03353f;
letter-spacing: 2px;
font-size: 16px;
color: #0cebc9;
font-family: Arial;
}
.map-pane-content-main {
background-color: rgba(2, 26, 29, 0.9);
padding: 10px;
height: calc(100% - 40px);
overflow: auto;
}
// 站点操作面板
.station-operation {
height: 100%;
&-stations {
height: calc(100% - 443px);
overflow: hidden;
&-selection {
height: 24px;
margin-bottom: 10px;
.ant-space {
height: 100%;
.select-all,
.clear-selection {
height: 100%;
padding: 0 6px;
::v-deep {
span {
font-size: 14px;
}
}
}
}
}
.station-list-tree {
height: calc(100% - 35px);
overflow: auto;
}
}
&-infomation {
&-content {
height: 383px;
.radius {
&-title {
margin-bottom: 9px;
font-size: 14px;
line-height: 11px;
color: #5b9cba;
}
&-search {
display: flex;
height: 24px;
::v-deep {
.ant-input {
width: 183px;
height: 100%;
padding-left: 5px;
padding-right: 36px;
}
.ant-input-suffix {
color: #5b9cba;
}
}
.ant-btn {
width: 70px;
height: 100%;
margin-left: 10px;
padding: 0;
flex-shrink: 0;
::v-deep {
span {
font-size: 14px;
}
}
}
}
&-table {
margin-top: 10px;
width: 264px;
::v-deep {
.ant-table {
font-size: 14px;
}
.ant-table-thead > tr th {
padding-top: 2px !important;
padding-bottom: 2px !important;
}
.ant-table-tbody .ant-table-row td {
padding: 6px !important;
}
.ant-table-placeholder {
background-color: transparent;
}
}
}
}
}
}
}
// 站点筛选面板
.station-filter {
&-item {
width: 260px;
height: 32px;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
user-select: none;
&:nth-child(4) {
img {
margin-left: -10px;
}
}
&:nth-child(5) {
img {
margin-left: -12px;
}
}
&-main {
display: flex;
align-items: center;
> div {
width: 39px;
}
}
}
.station-data-quality-list {
&-item {
margin-left: 9px;
height: 32px;
display: flex;
align-items: center;
display: flex;
justify-content: space-between;
width: 251px;
cursor: pointer;
user-select: none;
align-items: center;
> div {
display: flex;
align-items: center;
}
span {
margin-left: 12px;
font-size: 16px;
}
}
}
}
}
}
// 地图右侧操作栏结束
// 弹窗
.data-receive-status {
height: 700px;
overflow: hidden;
position: relative;
@borderColor: rgba(65, 111, 127, 0.5);
&-list {
float: left;
width: 230px;
height: 100%;
margin-left: 15px;
transform: translateX(-245px);
transition: transform 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
&.open {
transform: translateX(0);
}
&-container {
height: 100%;
border: 1px solid @borderColor;
border-top: 0;
display: flex;
flex-direction: column;
}
&-item {
&:first-child {
height: calc(100% - 305px);
.content {
height: calc(100% - 50px);
overflow: auto;
margin: 7px;
margin-right: 0;
}
}
&:nth-child(2) {
.content {
padding-left: 16px;
}
}
.title {
height: 37px;
line-height: 37px;
padding-left: 18px;
background-color: #08363c;
border-top: 1px solid @borderColor;
border-bottom: 1px solid @borderColor;
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 10px;
user-select: none;
img {
cursor: pointer;
}
}
}
&-toggle-show-btn {
position: absolute;
right: -13px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
}
.attribute-form {
.ant-input-number {
width: 173px;
height: 24px;
::v-deep {
.ant-input-number-input {
height: 24px;
line-height: 24px;
font-size: 12px;
}
}
}
::v-deep {
.ant-form-item {
margin-bottom: 0;
padding-bottom: 0;
&-label {
padding-top: 7px;
padding-bottom: 2px;
}
&-children {
display: flex;
align-items: center;
> span {
margin-left: 7px;
color: #5b9cba;
}
}
}
}
&-footer {
margin-top: 9px;
text-align: center;
.ant-btn {
width: 120px;
background-color: #00bded;
}
}
}
}
&-chart {
position: absolute;
right: 15px;
width: calc(100% - 270px);
height: 100%;
overflow: auto;
padding: 0 15px 10px;
border: 1px solid @borderColor;
transition: width 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
&.on-screen {
width: calc(100% - 30px);
}
.ant-divider {
margin: 34px 0 40px;
background-color: rgba(65, 111, 127, 0.5);
}
}
.legend {
margin: 32px 0;
display: flex;
justify-content: center;
&-item {
color: #ade6ee;
line-height: 12px;
&:not(:last-child) {
margin-right: 30px;
}
&-color {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 4px;
margin-right: 6px;
}
}
}
}
.fullscreen {
.data-receive-status {
height: calc(100vh - 70px);
}
}
// 弹窗结束
</style>