修改 地图

This commit is contained in:
GGJ
2024-01-02 16:34:56 +08:00
parent 0ed9c950ee
commit acac255e5e
10 changed files with 355 additions and 142 deletions

View File

@@ -15,6 +15,7 @@
"axios": "^1.6.2", "axios": "^1.6.2",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"echarts": "^5.4.3", "echarts": "^5.4.3",
"echarts4": "npm:echarts@^4.9.0",
"element-plus": "^2.4.4", "element-plus": "^2.4.4",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mitt": "^3.0.1", "mitt": "^3.0.1",

21
pnpm-lock.yaml generated
View File

@@ -1,5 +1,9 @@
lockfileVersion: '6.0' lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies: dependencies:
'@element-plus/icons-vue': '@element-plus/icons-vue':
specifier: ^2.3.1 specifier: ^2.3.1
@@ -19,6 +23,9 @@ dependencies:
echarts: echarts:
specifier: ^5.4.3 specifier: ^5.4.3
version: 5.4.3 version: 5.4.3
echarts4:
specifier: npm:echarts@^4.9.0
version: /echarts@4.9.0
element-plus: element-plus:
specifier: ^2.4.4 specifier: ^2.4.4
version: 2.4.4(vue@3.3.13) version: 2.4.4(vue@3.3.13)
@@ -1234,6 +1241,12 @@ packages:
resolution: {integrity: sha512-M/MERVDZ8hguvjl6MAlLWSLYLS7PzEyXaTb5gEeJ+SF+e9iUC0sdvlzqe91MMDHBoy+nqw7wKcUOrDSyvMCrRg==} resolution: {integrity: sha512-M/MERVDZ8hguvjl6MAlLWSLYLS7PzEyXaTb5gEeJ+SF+e9iUC0sdvlzqe91MMDHBoy+nqw7wKcUOrDSyvMCrRg==}
dev: false dev: false
/echarts@4.9.0:
resolution: {integrity: sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==}
dependencies:
zrender: 4.3.2
dev: false
/echarts@5.4.3: /echarts@5.4.3:
resolution: {integrity: sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==, tarball: https://registry.npmmirror.com/echarts/-/echarts-5.4.3.tgz} resolution: {integrity: sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==, tarball: https://registry.npmmirror.com/echarts/-/echarts-5.4.3.tgz}
dependencies: dependencies:
@@ -1956,12 +1969,12 @@ packages:
commander: 9.5.0 commander: 9.5.0
dev: false dev: false
/zrender@4.3.2:
resolution: {integrity: sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g==}
dev: false
/zrender@5.4.4: /zrender@5.4.4:
resolution: {integrity: sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==, tarball: https://registry.npmmirror.com/zrender/-/zrender-5.4.4.tgz} resolution: {integrity: sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==, tarball: https://registry.npmmirror.com/zrender/-/zrender-5.4.4.tgz}
dependencies: dependencies:
tslib: 2.3.0 tslib: 2.3.0
dev: false dev: false
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false

View File

@@ -63,7 +63,7 @@ const initChart = () => {
grid: { grid: {
top: '50px', top: '50px',
left: '10px', left: '10px',
right: '40px', right: '60px',
bottom: '40px', bottom: '40px',
containLabel: true containLabel: true
}, },

View File

@@ -8,8 +8,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, ref, watch, onMounted, defineEmits } from 'vue' import { onBeforeUnmount, ref, watch, onMounted, defineEmits } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts4'
import { useDictData } from '@/stores/dictData'
const dictData = useDictData()
const props = defineProps(['options']) const props = defineProps(['options'])
const myCharts = ref() const myCharts = ref()
const showCircle = ref(false) const showCircle = ref(false)
@@ -21,7 +22,7 @@ const fetchConfig = async (name: string) => {
} }
// fetchConfig() // fetchConfig()
const emit = defineEmits(['getRegionByRegionId']) const emit = defineEmits(['getRegionByRegion'])
onMounted(() => {}) onMounted(() => {})
const GetEchar = async (name: string) => { const GetEchar = async (name: string) => {
@@ -149,12 +150,28 @@ const GetEchar = async (name: string) => {
myCharts.value.on('click', (e: any) => { myCharts.value.on('click', (e: any) => {
if (name == '中国' && e.componentIndex == 0) { if (name == '中国' && e.componentIndex == 0) {
GetEchar(e.name) GetEchar(e.name)
MapReturn(e.name)
showCircle.value = true showCircle.value = true
// console.log('🚀 ~ file: MyEchartMap.vue:156 ~ myCharts.value.on ~ MapReturn(e.name):', MapReturn(e.name))
} }
emit('getRegionByRegionId', e)
}) })
} }
const MapReturn = (name: string) => {
let area = dictData.state.area[0].children
let list = {}
// break;
for (let i = 0; i < area.length; i++) {
if (area[i].name == name) {
list = area[i]
break
} else {
list = dictData.state.area[0]
}
}
emit('getRegionByRegion', list)
}
// 返回 // 返回
const circle = () => { const circle = () => {
GetEchar('中国') GetEchar('中国')
@@ -167,11 +184,11 @@ onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHandler) window.removeEventListener('resize', resizeHandler)
myCharts.value?.dispose() myCharts.value?.dispose()
}) })
defineExpose({ GetEchar })
watch( watch(
() => props.options, () => props.options,
(newVal, oldVal) => { (newVal, oldVal) => {
GetEchar('中国') // GetEchar('中国')
} }
) )
</script> </script>

View File

@@ -1,9 +1,9 @@
<template> <template>
<el-cascader v-bind='$attrs' :options='options' :props='cascaderProps' /> <el-cascader ref="cascader" v-bind="$attrs" :options="options" :props="cascaderProps" @change="change" />
</template> </template>
<script lang='ts' setup> <script lang="ts" setup>
import { defineComponent } from 'vue' import { defineComponent, ref } from 'vue'
defineOptions({ defineOptions({
name: 'Area' name: 'Area'
@@ -16,11 +16,19 @@ const cascaderProps = {
checkStrictly: true, checkStrictly: true,
emitPath: false emitPath: false
} }
const cascader = ref()
const dictData = useDictData() const dictData = useDictData()
const options = dictData.state.area const options = dictData.state.area
const areaName = ref(dictData.state.area[0].name)
const change = (e: any) => {
if (cascader.value.getCheckedNodes()[0].pathLabels.length == 1) {
areaName.value = cascader.value.getCheckedNodes()[0].pathLabels[0]
} else if (cascader.value.getCheckedNodes()[0].pathLabels.length >= 2) {
areaName.value = cascader.value.getCheckedNodes()[0].pathLabels[1]
}
}
defineExpose({ areaName })
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -1,8 +1,8 @@
<template> <template>
<component :is='config.layout.layoutMode'></component> <component :is="config.layout.layoutMode"></component>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { reactive } from 'vue' import { reactive } from 'vue'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'
import { useNavTabs } from '@/stores/navTabs' import { useNavTabs } from '@/stores/navTabs'
@@ -50,10 +50,7 @@ onBeforeMount(() => {
}) })
const init = async () => { const init = async () => {
await Promise.all([ await Promise.all([getAreaList(), dictDataCache()]).then(res => {
getAreaList(),
dictDataCache()
]).then(res => {
dictData.state.area = res[0].data dictData.state.area = res[0].data
dictData.state.basic = res[1].data dictData.state.basic = res[1].data
}) })
@@ -177,7 +174,38 @@ const init = async () => {
component: '/src/views/Event-boot/Region/distribution.vue', component: '/src/views/Event-boot/Region/distribution.vue',
keepalive: 'Event-boot/Region/distribution', keepalive: 'Event-boot/Region/distribution',
extend: 'none', extend: 'none',
children: [] children: [
{
id: 2,
pid: 3,
type: 'menu',
title: '区域概览',
name: 'Region/overview',
path: 'Region/overview',
icon: 'el-icon-Promotion',
menu_type: 'tab',
url: '',
component: '/src/views/dashboard/index.vue',
keepalive: 'Region/overview',
extend: 'none',
children: []
},
{
id: 1,
pid: 3,
type: 'menu',
title: '监测网分布',
name: 'Region/distribution',
path: 'Region/distribution',
icon: 'el-icon-Share',
menu_type: 'tab',
url: '',
component: '/src/views/Event-boot/Region/distribution.vue',
keepalive: 'Region/distribution',
extend: 'none',
children: []
}
]
} }
] ]
}, },

View File

@@ -11,8 +11,13 @@ export const useDictData = defineStore(
area: [] area: []
// 其他接口获取的字典,比如区域 // 其他接口获取的字典,比如区域
}) })
const getBasicData = (code: string) => { const getBasicData = (code: string, arr: string) => {
return state.basic.filter(item => item.code === code)[0]?.children || [] let list = []
list = state.basic.filter(item => item.code === code)[0]?.children || []
if (arr) {
list = list.filter(item => item.code !== arr)
}
return list
} }
return { return {
state, state,

View File

@@ -2,7 +2,7 @@
<div class="default-main"> <div class="default-main">
<el-form :inline="true" :model="formInline" class="demo-form-inline"> <el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="区域"> <el-form-item label="区域">
<el-input v-model="deptIndex" placeholder="请选择区域" clearable /> <Area v-model="formInline.deptIndex" ref="area" />
</el-form-item> </el-form-item>
<el-form-item label="统计类型:"> <el-form-item label="统计类型:">
<el-select <el-select
@@ -23,142 +23,275 @@
<div> <div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<MyEchartMap :options="echartList" class="map" /> <MyEchartMap
ref="EchartMap"
:options="echartMapList"
class="map"
@getRegionByRegion="getRegionByRegion"
/>
</el-col>
<el-col :span="12">
<my-echart class="tall" :options="echartList" />
<el-table class="tall" stripe :data="distributionData" border>
<el-table-column
prop="qy"
:label="
titleA == '电压等级'
? '电压等级'
: titleA == '终端厂家'
? '终端厂家'
: titleA == '干扰源类型'
? '干扰源类型'
: titleA == '电网拓扑'
? '区域'
: ''
"
align="center"
show-overflow-tooltip
></el-table-column>
<el-table-column prop="jcd" label="监测点数(个数)" align="center"></el-table-column>
<el-table-column prop="zc" label="通讯正常(个数)" sortable align="center"></el-table-column>
<el-table-column prop="zd" label="通讯中断(个数)" sortable align="center"></el-table-column>
</el-table>
</el-col> </el-col>
<el-col :span="12">1231</el-col>
</el-row> </el-row>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Area from '@/components/form/area/index.vue'
import { getAreaLineDetail } from '@/api/Region' import { getAreaLineDetail } from '@/api/Region'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import MyEchartMap from '@/components/echarts/MyEchartMap.vue' import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { ref, reactive, onMounted, provide } from 'vue' import { ref, reactive, onMounted, provide } from 'vue'
const options = ref<object[]>([])
const echartList = ref({})
const deptIndex = ref<string>('')
const DictData = useDictData() defineOptions({
name: 'Region/distribution'
})
const EchartMap = ref()
const dictData = useDictData()
const options = dictData.getBasicData('Statistical_Type', 'Report_Type')
const echartMapList = ref({})
const echartList = ref({})
const titleA = ref('')
const distributionData = ref([])
const area = ref()
const formInline = reactive({ const formInline = reactive({
deptIndex: '5699e5916a18a6381e1ac92da5bd2628', deptIndex: dictData.state.area[0].id,
monitorFlag: 2, monitorFlag: 2,
powerFlag: 2, powerFlag: 2,
serverName: 'event-boot', serverName: 'event-boot',
statisticalType: {} statisticalType: dictData.getBasicData('Statistical_Type', 'Report_Type')[0]
}) })
const info = () => {
options.value = DictData.getBasicData('Statistical_Type')
formInline.statisticalType = options.value[0]
}
const onSubmit = () => { const onSubmit = () => {
titleA.value = formInline.statisticalType.name
getAreaLineDetail(formInline).then(res => { getAreaLineDetail(formInline).then(res => {
echartList.value = { // 处理地图数据
title: { map(res)
text: '监测网分布' //+ "(" + _this.titles + ")", tabulation(res)
}, histogram(res)
tooltip: {
formatter: function (params: any) { EchartMap.value.GetEchar(area.value.areaName)
//console.log(params) console.log("🚀 ~ file: distribution.vue:98 ~ getAreaLineDetail ~ area.value.areaName:", area.value.areaName)
var tips = '' })
if (params.value == 0) { }
tips = "<font style='color: #000'>暂无数据</font><br/>"
} else { // 地图点击事件
tips += const getRegionByRegion = (list: any) => {
"<font style='color: #000'> " + formInline.deptIndex = list.id
params.name + onSubmit()
'</font><br/>区域暂降评估' + }
"<font style='color: #000'>:" + // 地图数处理
params.value + const map = (res: any) => {
'</font><br/>' echartMapList.value = {
} name: '',
return tips title: {
text: '监测网分布' //+ "(" + _this.titles + ")",
},
tooltip: {
formatter: function (params: any) {
//console.log(params)
var tips = ''
if (params.value == 0) {
tips = "<font style='color: #000'>暂无数据</font><br/>"
} else {
tips +=
"<font style='color: #000'> " +
params.name +
'</font><br/>区域暂降评估' +
"<font style='color: #000'>:" +
params.value +
'</font><br/>'
} }
}, return tips
color: ['green', 'red'],
legend: {
data: [
{
name: '正常'
},
{
name: '中断'
}
]
},
options: {
series: []
} }
} },
let mapList = [[], [], []] color: ['green', 'red'],
if (res.data.substationDetailVOList != null) { legend: {
res.data.substationDetailVOList.forEach((item: any) => { data: [
if (item.color == 'green') { {
mapList[0].push(item) name: '正常'
} else if (item.color == 'red') { },
mapList[1].push(item) {
name: '中断'
} }
}) ]
},
options: {
series: []
} }
mapList.forEach((item, ind) => { }
echartList.value.options.series.push({ let mapList = [[], [], []]
type: 'scatter', if (res.data.substationDetailVOList != null) {
mapName: 'china', res.data.substationDetailVOList.forEach((item: any) => {
name: ind == 0 ? '正常' : ind == 1 ? '中断' : '变电站', if (item.color == 'green') {
coordinateSystem: 'geo', mapList[0].push(item)
geoIndex: 0, } else if (item.color == 'red') {
animation: false, //坐标点是否显示动画 mapList[1].push(item)
roam: true, }
symbol: 'pin', })
symbolSize: function () { }
//坐标点大小 mapList.forEach((item, ind) => {
return 30 echartMapList.value.options.series.push({
type: 'scatter',
mapName: 'china',
name: ind == 0 ? '正常' : ind == 1 ? '中断' : '变电站',
coordinateSystem: 'geo',
geoIndex: 0,
animation: false, //坐标点是否显示动画
roam: true,
symbol: 'pin',
symbolSize: function () {
//坐标点大小
return 30
},
label: {
normal: {
show: false
}, },
label: { emphasis: {
normal: { show: false
show: false }
},
data: item.map(function (itemOpt: any) {
// console.log(itemOpt);
return {
name: itemOpt.srbName,
value: [
parseFloat(itemOpt.coordY), //经度
parseFloat(itemOpt.coordX) //维度
],
itemStyle: {
//地图区域的多边形
normal: {
color: itemOpt.color, //坐标点颜色
shadowBlur: 0, // 图形阴影的模糊大小
shadowOffsetX: 0 // 阴影水平方向上的偏移距离。
}
}, },
emphasis: { tooltip: {
show: false //仅在 options中最外层的 tooltip.trigger 为 'item'时有效
} position: 'bottom', //提示框位置,仅在 options中最外层的 tooltip.trigger 为 'item'时有效
}, formatter: function (params: any, ticket: any, callback: any) {
data: item.map(function (itemOpt: any) { var strHtml = '<div>变电站:' + itemOpt.subName + '<br/>' + '监测点:' + itemOpt.srbName
// console.log(itemOpt);
return {
name: itemOpt.srbName,
value: [
parseFloat(itemOpt.coordY), //经度
parseFloat(itemOpt.coordX) //维度
],
itemStyle: { strHtml += '</div>'
//地图区域的多边形 return strHtml
normal: {
color: itemOpt.color, //坐标点颜色
shadowBlur: 0, // 图形阴影的模糊大小
shadowOffsetX: 0 // 阴影水平方向上的偏移距离。
}
},
tooltip: {
//仅在 options中最外层的 tooltip.trigger 为 'item'时有效
position: 'bottom', //提示框位置,仅在 options中最外层的 tooltip.trigger 为 'item'时有效
formatter: function (params: any, ticket: any, callback: any) {
var strHtml = '<div>变电站:' + itemOpt.subName + '<br/>' + '监测点:' + itemOpt.srbName
strHtml += '</div>'
return strHtml
}
} }
} }
}) }
}) })
}) })
}) })
} }
// 表格数据处理
const tabulation = (res: any) => {
distributionData.value = []
for (var i = 0; i < res.data.areaValue.length; i++) {
distributionData.value.push({
qy: res.data.areaValue[i][0],
jcd: res.data.areaValue[i][1],
zc: res.data.areaValue[i][2],
zd: res.data.areaValue[i][3]
})
}
}
// 柱状图数据处理
const histogram = (res: any) => {
echartList.value = {
title: {
text:
titleA.value == '电压等级'
? '电压等级'
: titleA.value == '终端厂家'
? '终端厂家'
: titleA.value == '干扰源类型'
? '干扰源类型'
: titleA.value == '电网拓扑'
? '区域'
: '' // 给X轴加单位
},
tooltip: {
formatter: function (params) {
// console.log(params);
var tips = ''
for (var i = 0; i < params.length; i++) {
tips += params[i].name + '</br/>'
tips += '监测点数' + ':' + '&nbsp' + '&nbsp' + params[i].value + '</br/>'
}
return tips
}
},
xAxis: {
name:
titleA.value == '电压等级'
? '(电压\n等级)'
: titleA.value == '终端厂家'
? '(终端\n厂家)'
: titleA.value == '干扰源类型'
? '(干扰\n源类型)'
: titleA.value == '电网拓扑'
? '(区域)'
: '', // 给X轴加单位
data: distributionData.value.map(item => item.qy)
},
yAxis: {
name: '监测点数(个)' // 给X轴加单位
},
options: {
series: [
{
// name: '暂降次数',
type: 'bar',
data: distributionData.value.map(item => item.jcd),
barMaxWidth: 30,
itemStyle: {
normal: {
color: '#07CCCA'
}
},
label: {
show: true,
position: 'top',
textStyle: {
//数值样式
color: '#000'
},
fontSize: 12
}
}
]
}
}
}
onMounted(() => { onMounted(() => {
info()
onSubmit() onSubmit()
}) })
</script> </script>
@@ -166,4 +299,7 @@ onMounted(() => {
.map { .map {
height: calc(100vh - 120px); height: calc(100vh - 120px);
} }
.tall {
height: calc((100vh - 120px) / 2);
}
</style> </style>

View File

@@ -98,6 +98,7 @@ const Grade = (list: any) => {
} }
echartsArr.push(item.frequency) echartsArr.push(item.frequency)
}) })
voltageStatistics.value = { voltageStatistics.value = {
title: { title: {
text: '电压等级' text: '电压等级'
@@ -122,12 +123,10 @@ const Grade = (list: any) => {
legend: { legend: {
data: ['暂降次数'] data: ['暂降次数']
}, },
xAxis: [ xAxis: {
{ name: '电压等级',
name: '电压等级', // 给X轴加单位 data: echartsndArr
data: echartsndArr },
}
],
yAxis: [ yAxis: [
{ {
type: 'value' type: 'value'

View File

@@ -2,7 +2,7 @@
<div class="default-main"> <div class="default-main">
<el-form :inline="true" :model="formInline" class="demo-form-inline"> <el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="区域"> <el-form-item label="区域">
<el-input v-model="formInline.deptInd" placeholder="请选择区域" clearable /> <Area v-model="formInline.deptIndex" />
</el-form-item> </el-form-item>
<el-form-item label="时间"> <el-form-item label="时间">
<el-date-picker v-model="formInline.searchBeginTime" type="date" placeholder="请选择时间" /> <el-date-picker v-model="formInline.searchBeginTime" type="date" placeholder="请选择时间" />
@@ -15,24 +15,30 @@
<el-tab-pane label="图形" name="1"> <el-tab-pane label="图形" name="1">
<Echart :list="list" ref="echarts" /> <Echart :list="list" ref="echarts" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="表格" name="2"><Tableabove ref="table" /></el-tab-pane> <el-tab-pane label="表格" name="2"><Tableabove ref="table" /></el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, ref, onBeforeMount } from 'vue' import Area from '@/components/form/area/index.vue'
const activeName = ref('1') import { useDictData } from '@/stores/dictData'
import Echart from '@/views/dashboard/components/echart.vue' import Echart from '@/views/dashboard/components/echart.vue'
import Tableabove from '@/views/dashboard/components/Tableabove.vue' import Tableabove from '@/views/dashboard/components/Tableabove.vue'
import { onMounted, reactive, ref, onBeforeMount } from 'vue'
defineOptions({
name: 'Region/overview'
})
const activeName = ref('1')
import { getAreaCalculation } from '@/api/test' import { getAreaCalculation } from '@/api/test'
const list = ref([]) const list = ref([])
const echarts = ref() const echarts = ref()
const table = ref() const table = ref()
const dictData = useDictData()
const formInline = reactive({ const formInline = reactive({
deptInd: '', deptInd: '',
deptIndex: '5699e5916a18a6381e1ac92da5bd2628', deptIndex: dictData.state.area[0].id,
monitorFlag: 2, monitorFlag: 2,
powerFlag: 2, powerFlag: 2,
serverName: 'event-boot', serverName: 'event-boot',