修改 地图

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",
"crypto-js": "^4.2.0",
"echarts": "^5.4.3",
"echarts4": "npm:echarts@^4.9.0",
"element-plus": "^2.4.4",
"lodash-es": "^4.17.21",
"mitt": "^3.0.1",

21
pnpm-lock.yaml generated
View File

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

View File

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

View File

@@ -8,8 +8,9 @@
<script setup lang="ts">
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 myCharts = ref()
const showCircle = ref(false)
@@ -21,7 +22,7 @@ const fetchConfig = async (name: string) => {
}
// fetchConfig()
const emit = defineEmits(['getRegionByRegionId'])
const emit = defineEmits(['getRegionByRegion'])
onMounted(() => {})
const GetEchar = async (name: string) => {
@@ -149,12 +150,28 @@ const GetEchar = async (name: string) => {
myCharts.value.on('click', (e: any) => {
if (name == '中国' && e.componentIndex == 0) {
GetEchar(e.name)
MapReturn(e.name)
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 = () => {
GetEchar('中国')
@@ -167,11 +184,11 @@ onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHandler)
myCharts.value?.dispose()
})
defineExpose({ GetEchar })
watch(
() => props.options,
(newVal, oldVal) => {
GetEchar('中国')
// GetEchar('中国')
}
)
</script>

View File

@@ -1,9 +1,9 @@
<template>
<el-cascader v-bind='$attrs' :options='options' :props='cascaderProps' />
<el-cascader ref="cascader" v-bind="$attrs" :options="options" :props="cascaderProps" @change="change" />
</template>
<script lang='ts' setup>
import { defineComponent } from 'vue'
<script lang="ts" setup>
import { defineComponent, ref } from 'vue'
defineOptions({
name: 'Area'
@@ -16,11 +16,19 @@ const cascaderProps = {
checkStrictly: true,
emitPath: false
}
const cascader = ref()
const dictData = useDictData()
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>
<style scoped>
</style>
<style scoped></style>

View File

@@ -1,8 +1,8 @@
<template>
<component :is='config.layout.layoutMode'></component>
<component :is="config.layout.layoutMode"></component>
</template>
<script setup lang='ts'>
<script setup lang="ts">
import { reactive } from 'vue'
import { useConfig } from '@/stores/config'
import { useNavTabs } from '@/stores/navTabs'
@@ -50,10 +50,7 @@ onBeforeMount(() => {
})
const init = async () => {
await Promise.all([
getAreaList(),
dictDataCache()
]).then(res => {
await Promise.all([getAreaList(), dictDataCache()]).then(res => {
dictData.state.area = res[0].data
dictData.state.basic = res[1].data
})
@@ -177,7 +174,38 @@ const init = async () => {
component: '/src/views/Event-boot/Region/distribution.vue',
keepalive: 'Event-boot/Region/distribution',
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

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

View File

@@ -2,7 +2,7 @@
<div class="default-main">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="区域">
<el-input v-model="deptIndex" placeholder="请选择区域" clearable />
<Area v-model="formInline.deptIndex" ref="area" />
</el-form-item>
<el-form-item label="统计类型:">
<el-select
@@ -23,142 +23,275 @@
<div>
<el-row :gutter="20">
<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 :span="12">1231</el-col>
</el-row>
</div>
</div>
</template>
<script setup lang="ts">
import Area from '@/components/form/area/index.vue'
import { getAreaLineDetail } from '@/api/Region'
import { useDictData } from '@/stores/dictData'
import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
import MyEchart from '@/components/echarts/MyEchart.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({
deptIndex: '5699e5916a18a6381e1ac92da5bd2628',
deptIndex: dictData.state.area[0].id,
monitorFlag: 2,
powerFlag: 2,
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 = () => {
titleA.value = formInline.statisticalType.name
getAreaLineDetail(formInline).then(res => {
echartList.value = {
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
// 处理地图数据
map(res)
tabulation(res)
histogram(res)
EchartMap.value.GetEchar(area.value.areaName)
console.log("🚀 ~ file: distribution.vue:98 ~ getAreaLineDetail ~ area.value.areaName:", area.value.areaName)
})
}
// 地图点击事件
const getRegionByRegion = (list: any) => {
formInline.deptIndex = list.id
onSubmit()
}
// 地图数处理
const map = (res: any) => {
echartMapList.value = {
name: '',
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/>'
}
},
color: ['green', 'red'],
legend: {
data: [
{
name: '正常'
},
{
name: '中断'
}
]
},
options: {
series: []
return tips
}
}
let mapList = [[], [], []]
if (res.data.substationDetailVOList != null) {
res.data.substationDetailVOList.forEach((item: any) => {
if (item.color == 'green') {
mapList[0].push(item)
} else if (item.color == 'red') {
mapList[1].push(item)
},
color: ['green', 'red'],
legend: {
data: [
{
name: '正常'
},
{
name: '中断'
}
})
]
},
options: {
series: []
}
mapList.forEach((item, ind) => {
echartList.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
}
let mapList = [[], [], []]
if (res.data.substationDetailVOList != null) {
res.data.substationDetailVOList.forEach((item: any) => {
if (item.color == 'green') {
mapList[0].push(item)
} else if (item.color == 'red') {
mapList[1].push(item)
}
})
}
mapList.forEach((item, ind) => {
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: {
normal: {
show: false
emphasis: {
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: {
show: false
}
},
data: item.map(function (itemOpt: any) {
// console.log(itemOpt);
return {
name: itemOpt.srbName,
value: [
parseFloat(itemOpt.coordY), //经度
parseFloat(itemOpt.coordX) //维度
],
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
itemStyle: {
//地图区域的多边形
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
}
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(() => {
info()
onSubmit()
})
</script>
@@ -166,4 +299,7 @@ onMounted(() => {
.map {
height: calc(100vh - 120px);
}
.tall {
height: calc((100vh - 120px) / 2);
}
</style>

View File

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

View File

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