同步现场代码

This commit is contained in:
GGJ
2024-05-09 18:00:04 +08:00
parent 06611f527a
commit 6d7f1bca56
46 changed files with 44063 additions and 1586 deletions

View File

@@ -1,3 +0,0 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View File

@@ -18,7 +18,8 @@
<!-- 冀北地图 --> <!-- 冀北地图 -->
<!--引入样式文件--> <!--引入样式文件-->
<!-- <link rel="stylesheet" href="http://24.43.102.201:30080/powermap.min.css"/> --> <!-- <link rel="stylesheet" href="http://24.43.102.201:30080/powermap.min.css"/> -->
<!-- <script src="http://24.43.102.201:30080/powermap.min.js"></script> --> <!-- <script src="http://25.42.182.218/narimap/libs/narimap.umd.min.js"></script>
<script src="http://25.42.182.218/narimap/libs/nrgis-common/libs/index.min.js"></script> -->
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -28,6 +28,10 @@ export function getGridDiagramLineData(data: any) {
export function getGridDiagramDev(data: any) { export function getGridDiagramDev(data: any) {
return request({ url: '/device-boot/gridDiagram/getGridDiagramDev', method: 'post', data }) return request({ url: '/device-boot/gridDiagram/getGridDiagramDev', method: 'post', data })
} }
// 区域终端统计
export function getGridDiagramDevDataList(data: any) {
return request({ url: '/device-boot/gridDiagram/getGridDiagramDevDataList', method: 'post', data })
}
// 终端趋势分析 // 终端趋势分析
export function getGridDiagramDevTendency(data: any) { export function getGridDiagramDevTendency(data: any) {
return request({ url: '/device-boot/gridDiagram/getGridDiagramDevTendency', method: 'post', data }) return request({ url: '/device-boot/gridDiagram/getGridDiagramDevTendency', method: 'post', data })
@@ -113,4 +117,34 @@ export function getAssessTrend(data: any) {
export function getEventDetailByList(data: any) { export function getEventDetailByList(data: any) {
return request({ url: '/event-boot/gridDiagram/getEventDetailByList', method: 'post', data }) return request({ url: '/event-boot/gridDiagram/getEventDetailByList', method: 'post', data })
} }
//通过监测点集合查询总监测点数据完整性
export function getTotalIntegrityByLineIds(data: any) {
return request({ url: '/device-boot/LineIntegrityData/getTotalIntegrityByLineIds', method: 'post', data })
}
//根据终端id集合获取总终端在线率
export function getTotalOnlineRates(data: any) {
return request({ url: '/device-boot/deviceInfo/getTotalOnlineRates', method: 'post', data })
}
//监测点稳态指标合格率详情
export function lineQualifiedDetail(data: any) {
return request({ url: '/harmonic-boot/grid/lineQualifiedDetail', method: 'post', params:data })
}
//监测点评估
export function getLineAssess(data: any) {
return request({ url: '/harmonic-boot/grid/getLineAssess', method: 'post', params:data })
}
//根据监测点获取暂态短时中断和暂态赞升暂降
export function getEventDetailByLineId(data: any) {
return request({ url: '/event-boot/gridDiagram/getEventDetailByLineId', method: 'post', data })
}

BIN
src/assets/img/BDZ-GJ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

BIN
src/assets/img/BDZ-ZS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

BIN
src/assets/img/FGX-L.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

BIN
src/assets/img/FGX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

BIN
src/assets/img/JCD-ZS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
src/assets/img/JCD-ZX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
src/assets/img/TJ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

BIN
src/assets/img/ZD-ZS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

BIN
src/assets/img/ZD-ZX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

View File

@@ -0,0 +1,160 @@
/*
* @Author: your name
* @Date: 2021-10-27 15:42:24
* @LastEditTime: 2021-10-30 23:09:59
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \webgis-sdk\html\examples_PMS\configs\devicesDemo.js
*/
export const devicesDemo = {
// 地图中心点
center: [116.478935, 39.997761],
// 机构层级
ids: {
orgId: 'ff80808149f52e24014a039871840007',
provinceId: 'ff80808149f52e24014a039871840007',
},
// 设备查询过滤
device: {
// 电网资源查询
ids: [
{ devId: '10197', classId: 110, distribution: 1, provinceId: 'ff80808149f52e24014a039871840007' },
{ devId: '133403886', classId: 200, distribution: 1, provinceId: 'ff80808149f52e24014a039871840007' }
],
locateId:
'{"devId":"da00e9d6-5bde-4a4e-8975-eff2d00e3d3e","devType":"0200000","distribution":1,"provinceId":"ff80808149f52e24014a039871840007"}',
dynamicRender: '{"110":["10230","10234"],"200":["100255259"]}',
renderBounds: [
[120.1619289646693, 31.613147889448626],
[120.26799346408444, 31.655677320017233]
],
feeder: { devId: '10DKX-341329', classId: 300, provinceId: 'ff80808149f52e24014a039871840007', distribution: 0 },
transId: '650008239558001',
outLineIds: '357000356901101',
orgId: '700000',
devCardId: '652323175448100',
stationId: '650011510096501',
relateSwitchs: '652221579508700',
simulateSwitches: '650003389835901',
feederForTower: '650003387691401',
zones: ['62632a29-e2de-17bc-e053-0a8657155d6e2tm3nf'], // 低压台区ID
feederIds: ['SBID0000001B9E4A1418D94489948781CD5407FF4D', 'SBID000000DB42085DCB3E4D90AF4AEA09435FD801'], // 输电线路ID
provinces: ['ff80808149f52e24014a039871840007'], // 省级ID
cities: ['ff8080814a616f0f014b38b062e0050e'], // 地市ID
countries: ['ff808081542d934101542e24b2c30001'], // 区县ID
maintCrews: ['ff8080814db36458014db89148050006'], // 维护班组ID,
lineIds: ['10DKX-395601'], // 配电线路ID
hideYPDevices: true, // 是否隐藏营销设备
// 设备显示过滤表单默认值
devIdFilter: '10230,10234',
voltageLevel: '500000,220000',
runStatus: 1, //运行状态
chargedState: 0, //带电状态
mannerDefault: 'type',
levelDefault: [],
propertyDefault: 'vlevel_code',
ownershipCode: 1, //电网资产
// 设备属性高亮表单默认值
highlightManner: 'id',
propertyRender: '10230,10234,100255259',
highlightColor: '#0060ff',
otherColor: '#999999',
hasflash: 1,
feederId: '90150224',
// 服务端过滤
serviceManner: 'filter',
serviceLevel: '4',
serviceDomain: '1',
serviceFilterName: 'cities',
lnglat: '119.04805,32.03709', // 经纬度
// 设备名称查询
keyword: '220',
NameQueryOrgId: '',
distribution: 1,
// 设备 ID 查询
idQueryManner: 'bothends',
// 线路和运行杆塔查询
lineId: '80116367',
poles: '80158265,80158271,80158277'
},
space: {
// 空间分析 - 空间查询
rectangle: '[[119.5259089995932, 32.93433342834534],[119.41603, 32.74]]', // 矩形坐标
polygon: '[[119.26388, 32.12946],[119.15631, 32.52946],[119.18388, 32.85984],[119.34397, 32.85857]]', // 多边形坐标
// 空间分析 - 缓冲区查询
polyline: '[[119.34397,32.85857],[119.34709,32.86392], [119.36636,32.86221]]', // 线坐标
// 查询
radius: '10000',
distribution: 1
},
topology: {
// 拓扑分析
supplyRadiusDevice: '650008239306401', // 供电范围
supplyRadiusFeederId: '652221827488500', // 供电半径 - 馈线
supplyRadiusTransId: '650008239306401', // 供电半径 - 台区
powerSource: '650008239306401', // 电源
electricStatus: '650008239306401', // 带电状态
shortPathStart: '651220001069800', // 最短路径 - 起始设备ID
shortPathEnd: '651220001337700', // 最短路径 - 终止设备ID
devId: '14000124192657',
devType: '0111',
classIdsForShowResultPanel: [136, 137, 335, 431],
classIdsForDefineAffectPSRType: [
338, 436, 490, 306, 310, 311, 312, 321, 335, 339, 342, 343, 344, 349, 410, 411, 412, 421, 430, 431, 433, 434, 435, 437, 439,
441, 442, 443, 444, 505, 506, 510, 511, 512, 521, 546, 556, 558, 567, 569, 571
]
},
// 查询面板的设备类型选项
devicesTypeDemo: [
{ code: '296', name: '发电厂' },
{ code: '110', name: '变电站' },
{ code: '200', name: '输电线路' },
// { code: '300', name: '配电线路分支' },
{ code: '300', name: '馈线' },
{ code: '335', name: '配电台变' },
{ code: '342', name: '柱上开关' },
{ code: '521', name: '低压落火点' }
],
topologyDevicesTypeDemo: [
{ code: '335', name: '配电台变' },
{ code: '211', name: '配电电缆段' },
{ code: '310', name: '配电架空段' },
{ code: '511', name: '低压电缆段' },
{ code: '510', name: '低压架空段' },
{ code: '342', name: '柱上开关' },
{ code: '521', name: '低压落火点' }
],
//环境气象
environment: {
typhoonid: '202114',
},
// 聚类图层
layer: {
center: [118.2, 24.5]
},
//管理网格
grid: {
center: [105.90544679658711, 39.1171887995564],
initOrgIds: ['8a812897493378a0014956770fd56660'],
},
//动画
visualization: {
// 动画
speed: 5,
color: '2',
backgroundWidth: 1,
backgroundColor: '#ffffff',
lineLength: 40,
lineWidth: 5,
},
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@ import { onBeforeUnmount, onMounted, ref, defineExpose, watch } from 'vue'
// import echarts from './echarts' // import echarts from './echarts'
import * as echarts from 'echarts' // 全引入 import * as echarts from 'echarts' // 全引入
import 'echarts-gl' import 'echarts-gl'
import 'echarts-liquidfill'
import 'echarts/lib/component/dataZoom' import 'echarts/lib/component/dataZoom'
import { color, gradeColor3 } from './color' import { color, gradeColor3 } from './color'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'

View File

@@ -149,8 +149,8 @@
.el-button--primary:focus { .el-button--primary:focus {
color: var(--el-color-white); color: var(--el-color-white);
border-color: var(--el-color-primary); // border-color: var(--el-color-primary);
background-color: var(--el-color-primary); // background-color: var(--el-color-primary);
outline: 0; outline: 0;
} }
.el-button--primary:hover { .el-button--primary:hover {

View File

@@ -31,6 +31,9 @@
// mt0,mr0,mb0,ml0 --> mt100,mr100,mb100,ml100 // mt0,mr0,mb0,ml0 --> mt100,mr100,mb100,ml100
@for $i from 0 through 100 { @for $i from 0 through 100 {
.md#{$i} {
margin: #{$i}px !important;
}
.mt#{$i} { .mt#{$i} {
margin-top: #{$i}px !important; margin-top: #{$i}px !important;
} }
@@ -47,6 +50,9 @@
margin-left: #{$i}px !important; margin-left: #{$i}px !important;
} }
.pd#{$i} {
padding: #{$i}px !important;
}
.pt#{$i} { .pt#{$i} {
padding-top: #{$i}px !important; padding-top: #{$i}px !important;
} }

View File

@@ -1209,7 +1209,7 @@ const rendering = () => {
let data = { let data = {
name: item2, name: item2,
type: 'scatter', type: 'scatter',
symbol: new URL('@/assets/point.png', import.meta.url).href, symbol:`image://`+ new URL('@/assets/point.png', import.meta.url).href,
symbolSize: 16, symbolSize: 16,
itemStyle: { itemStyle: {
width: '22px', width: '22px',
@@ -1302,9 +1302,10 @@ const rendering = () => {
data: item.gvalue data: item.gvalue
} }
opitonserise.push(data) opitonserise.push(data)
} else {
opitonserise.push([])
} }
// else {
// opitonserise.push([])
// }
}) })
if (item.valueName == undefined) { if (item.valueName == undefined) {
item.valueName = '无' item.valueName = '无'

View File

@@ -0,0 +1,277 @@
<!-- 稳态 -->
<template>
<!-- 终端 -->
<el-dialog draggable title="稳态指标超标占比统计" v-model="dialogVisible" width="1400px">
<el-row style="height: 330px" :gutter="20">
<el-col :span="12">
<div class="title">
<span>稳态指标超标占比</span>
</div>
<div class="boxSteps">
<el-steps>
<template v-for="(item, i) in Voltage">
<el-step
:class="active == i ? 'highlight' : ''"
:title="item.name"
@click="handleClick(i)"
></el-step>
</template>
</el-steps>
</div>
<div v-for="(item, i) in evaluationData" class="evaluationData">
<el-row style="width: 100%">
<el-col :span="12" style="display: flex">
<img :src="url[i]" />
<span>{{ item.targetName }}</span>
</el-col>
<el-col :span="12" style="display: flex">
<div style="width: 150px">
均值
<span style="color: #339966">{{ item.avg == 3.14159 ? '--' : item.avg }}</span>
</div>
<div>
标准差
<span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.sd }}</span>
</div>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="12">
<!-- <div class="title">
<span>稳态电能质量水平评估环比变化</span>
</div>
<div class="pie">
<div style="height: 260px; width: 100%" ref="chartRef"></div>
</div> -->
</el-col>
</el-row>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue'
import echarts from '@/components/echarts/echarts'
import { useDictData } from '@/stores/dictData'
import { color } from '@/components/echarts/color'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getEvaluationData, evaluationDetail, evaluationRatio } from '@/api/device-boot/panorama'
const dialogVisible: any = ref(false)
const rowList = ref({})
const active: any = ref(1)
const evaluationData: any = ref([])
const dictData = useDictData()
const Voltage: any = dictData.getBasicData('Dev_Voltage_Stand').filter(item => {
if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') {
return item
}
})
const chartRef = ref<HTMLDivElement>()
const url: any = [
new URL(`@/assets/img/PLPC.png`, import.meta.url),
new URL(`@/assets/img/DYPC.png`, import.meta.url),
new URL(`@/assets/img/JBL.png`, import.meta.url),
new URL(`@/assets/img/SXDY.png`, import.meta.url),
new URL(`@/assets/img/SB.png`, import.meta.url)
]
const tableData: any = ref([])
const echart = (row: any) => {
let chart = echarts.init(chartRef.value as HTMLDivElement)
let dataname = ['频率偏差', '电压偏差', '电压总谐波畸变率', '三相电压不平衡度', '闪变']
let datamax = [100, 100, 100, 100, 100, 100]
let indicator = []
for (let i = 0; i < dataname.length; i++) {
indicator.push({
name: dataname[i],
max: datamax[i]
})
}
let option: any = {
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.35)',
borderWidth: 0
},
legend: {
data: row.map((item: any) => item.time),
type: 'scroll',
orient: 'vertical',
icon: 'roundRect',
right: '20',
itemGap: 10,
itemWidth: 16,
itemHeight: 16,
textStyle: {
fontSize: '15',
color: '#656565'
}
},
radar: {
center: ['50%', '50%'],
radius: '65%',
startAngle: 90,
splitNumber: 5,
splitArea: {
areaStyle: {
color: ['#FFFFFF', '#F5F9FF'].reverse()
}
},
axisLabel: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: '#D2E4F8'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#D2E4F8'
}
},
name: {
formatter: '{value}',
textStyle: {
color: '#656565',
fontSize: 15
}
},
indicator: indicator
},
series: []
}
row.forEach((item: any, i: any) => {
option.series.push({
name: item.time,
type: 'radar',
symbol: 'none',
areaStyle: {
normal: {
color: color[i + 1]
}
},
itemStyle: {
color: color[i + 1]
},
data: [item.ratioList]
})
})
chart.setOption(option)
}
const open = async (row: any) => {
rowList.value = row
dialogVisible.value = true
// 稳态电能质量水平评估
handleClick(0)
}
// 点击电压等级
const handleClick = (i: any) => {
active.value = i
getEvaluationData({
...rowList.value,
voltageLevel: Voltage[i].id
}).then(res => {
evaluationData.value = res.data
})
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-select) {
min-width: 80px;
}
.title {
display: flex;
justify-content: space-between;
margin: 10px;
span {
font-weight: 550;
font-size: 18px;
}
}
.pie {
display: flex;
justify-content: space-around;
}
.evaluationData {
height: 40px;
margin: 8px 30px;
width: 100%;
box-shadow: 1px 1px 1px 1px #e8e3e3;
display: flex;
font-size: 18px;
line-height: 40px;
img {
height: 30px;
width: 30px;
margin: 5px 30px;
}
}
.el-steps {
margin-top: 5px;
}
:deep(.el-step__icon) {
border: none;
background: #ccc;
margin-top: 5px;
width: 15px;
height: 15px;
}
:deep(.el-step__icon-inner) {
display: none;
}
:deep(.boxSteps) {
border-radius: 50px;
width: 60%;
height: 25px;
margin: auto;
margin-top: 30px;
.el-step__title {
line-height: 18px;
font-size: 16px;
margin-left: -10px;
font-weight: 500;
color: #000 !important;
position: relative;
top: -50px;
}
}
:deep(.highlight) {
.el-step__icon {
background: var(--el-color-primary);
}
.el-step__title {
font-weight: 700 !important;
color: var(--el-color-primary) !important;
}
// .is-wait {
// color: var(--el-color-primary) !important;
// }
}
</style>

View File

@@ -1,6 +1,6 @@
<template> <template>
<!-- 综合评估详情 --> <!-- 综合评估详情 -->
<el-dialog draggable title="指标合格率统计详情" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="指标合格率统计统计" v-model="dialogVisible" width="1400px">
<div> <div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="600px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="600px" :data="tableData">
<vxe-column field="substationName" title="变电站名称" /> <vxe-column field="substationName" title="变电站名称" />

View File

@@ -1,201 +0,0 @@
<template>
<div class="boxLeft">
<!-- 监测点 -->
<el-card>
<template #header>
<div class="card-header">
<span>技术监督</span>
</div>
</template>
<div :style="boxHeight">
<el-segmented v-model="segmentedValue" :options="segmentedList" block />
<el-row style="height: calc(100% - 62px); margin-top: 20px">
<el-col :span="12" class="col" style="border-right: 1px solid #ccc">
<div>
<span>异常问题总数</span>
<span style="color: #2dcd28">60</span>
</div>
<div>
<span style="width: 120px">已关联工单数</span>
<span style="color: #81b337">60</span>
</div>
<div>
<span style="width: 120px"> 工单转换率</span>
<span style="color: #338dff">60%</span>
</div>
</el-col>
<el-col :span="12" class="col">
<div>
<span>异常问题总数</span>
<span style="color: #2dcd28">60</span>
</div>
<div>
<span style="width: 120px">已关联工单数</span>
<span style="color: #81b337">60</span>
</div>
<div>
<span style="width: 120px"> 工单转换率</span>
<span style="color: #338dff">60%</span>
</div>
</el-col>
</el-row>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, provide } from 'vue'
import MyEChart from '@/components/echarts/MyEchart.vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import {} from '@/api/device-boot/panorama'
const dictData = useDictData()
const boxHeight: any = mainHeight(220, 3)
const formRow: any = ref({})
const segmentedValue = ref('0')
const segmentedList = [
{
label: '监督计划',
value: '0'
},
{
label: '系统监测',
value: '1'
},
{
label: '现场测试',
value: '2'
},
{
label: '用户投诉',
value: '3'
}
]
const info = (row: any) => {
let form = {
...row,
id: row.orgNo,
deptIndex: row.orgNo,
orgId: row.orgNo,
ids: [],
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0],
isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid
}
let loadType = dictData.getBasicData('Statistical_Type').find(item => item.code == 'Load_Type')
formRow.value = form
}
defineExpose({ info })
</script>
<style lang="scss" scoped>
.boxLeft {
// width: calc(50% - 10px);
width: 50%;
padding: 10px 10px 10px 10px;
font-size: 13px;
overflow: hidden;
}
.title {
// height: ;
display: flex;
justify-content: space-between;
font-size: 16px;
height: 22px;
line-height: 23px;
padding-left: 5px;
width: 100%;
background-image: linear-gradient(to right, #a4e5da, #fff);
.info {
font-weight: normal;
display: flex;
font-size: 12px;
cursor: pointer;
}
}
.evaluate {
height: 60px;
border: 1px solid #ccc;
margin: 10px 0;
padding: 10px 0;
display: flex;
justify-content: space-around;
text-align: center;
overflow-x: auto;
overflow-y: hidden;
}
.boxR {
border: 1px solid #ccc;
margin: 10px 0;
padding: 5px;
.num {
color: #2478f2;
}
.top {
display: flex;
justify-content: space-between;
}
.bottom {
margin: 0;
border: 0px;
}
}
:deep(.el-select) {
min-width: 120px;
}
.col {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.imgR {
position: absolute;
padding: 10px;
top: calc(50% - 80px);
left: -23px;
z-index: 1;
height: 200px;
cursor: pointer;
}
:deep(.el-card) {
.el-card__header {
padding: 5px 20px;
font-size: 1.2rem;
&::before {
width: 0.3rem;
height: 1.2rem;
margin-top: 0.3rem;
position: absolute;
content: '';
background: var(--el-color-primary);
border-radius: 0.02rem;
left: 1.2rem;
}
}
.el-card__body {
padding: 10px;
}
}
.col {
display: grid;
grid-template-columns: 1fr;
grid-template-rows:repeat(3,auto);
text-align: center;
// flex-wrap: wrap;
// justify-content: space-around;
// align-items: center;
}
:deep(.el-segmented) {
--el-border-radius-base: 16px;
}
</style>

View File

@@ -1,40 +1,46 @@
<template> <template>
<div :class="show ? 'show' : 'noshow'">
<div class="boxLeft" :style="height"> <div class="boxLeft" :style="height">
<!-- 在线监测规模 --> <!-- 在线监测规模 -->
<div :style="boxHeight">
<el-card> <div class="title">
<template #header>
<div class="card-header">
<span>在线监测规模</span> <span>在线监测规模</span>
</div> </div>
</template>
<MyEChart :style="boxHeight" :options="onlineCharts" />
</el-card>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<MyEChart :style="tabHeight" :options="onlineCharts" />
</div>
<!-- 监测终端状态 --> <!-- 监测终端状态 -->
<div :style="boxHeight">
<el-card> <div class="title">
<template #header>
<div class="card-header">
<span>监测终端状态</span> <span>监测终端状态</span>
</div> </div>
</template>
<div> <div style="display: flex" class="mt2">
<MyEChart :style="boxHeight" :options="terminalCharts" /> <img src="@/assets/img/FGX.png" />
</div>
<MyEChart :style="tabHeight" :options="terminalCharts" />
</div> </div>
</el-card>
<!-- 监测点 --> <!-- 监测点 -->
<el-card> <div :style="boxHeight">
<template #header> <div class="title">
<div class="card-header"> <span>监测点数据完整率</span>
<span>监测点</span>
</div> </div>
</template>
<MyEChart :style="boxHeight" :options="dotCharts" />
</el-card>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<MyEChart :style="tabHeight" :options="dotCharts" />
</div>
</div>
<img
class="imgL"
:style="show ? 'transform: rotate(0deg);' : 'transform: rotate(180deg);'"
@click="show = !show"
src="@/assets/img/QH.png"
/>
</div> </div>
</template> </template>
@@ -47,9 +53,10 @@ import { mainHeight } from '@/utils/layout'
import { getPracticalRunDeviceInfo, getGridDiagramCityDev, getGridDiagramLineData } from '@/api/device-boot/panorama' import { getPracticalRunDeviceInfo, getGridDiagramCityDev, getGridDiagramLineData } from '@/api/device-boot/panorama'
const dictData = useDictData() const dictData = useDictData()
const height = mainHeight(20) const height = mainHeight(30)
const boxHeight: any = mainHeight(220, 3) const boxHeight = mainHeight(40, 3)
const tabHeight: any = mainHeight(150, 3)
const show = ref(false)
const formRow: any = ref({}) const formRow: any = ref({})
const terminalCharts: any = ref({}) const terminalCharts: any = ref({})
@@ -57,7 +64,6 @@ const dotCharts = ref()
const onlineCharts = ref() const onlineCharts = ref()
const info = (row: any) => { const info = (row: any) => {
let form = { let form = {
...row, ...row,
@@ -67,7 +73,7 @@ const info = (row: any) => {
ids: [], ids: [],
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0], statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0],
isUpToGrid: row.isUpToGrid, isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid monitorFlag: row.isUpToGrid == 0 ? null : row.isUpToGrid
} }
let loadType = dictData.getBasicData('Statistical_Type').find(item => item.code == 'Load_Type') let loadType = dictData.getBasicData('Statistical_Type').find(item => item.code == 'Load_Type')
@@ -77,12 +83,13 @@ const info = (row: any) => {
onlineCharts.value = { onlineCharts.value = {
tooltip: {}, tooltip: {},
yAxis: { yAxis: {
type: 'value' type: 'value',
name:'个'
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: ['变电站', '监测装置', '监测点'], data: ['变电站', '监测终端', '监测点'],
axisLabel: { axisLabel: {
color: '#000', color: '#000',
fontSize: 12 fontSize: 12
@@ -98,7 +105,7 @@ const info = (row: any) => {
dataZoom: null, dataZoom: null,
series: [ series: [
{ {
name: '', name: '个数',
type: 'bar', type: 'bar',
data: [ data: [
res.data[0].subIndexes.length, res.data[0].subIndexes.length,
@@ -130,7 +137,7 @@ const info = (row: any) => {
}, },
yAxis: [ yAxis: [
{ {
name: '个', name: '个',
type: 'value' type: 'value'
}, },
{ {
@@ -196,7 +203,7 @@ const info = (row: any) => {
} }
}, },
yAxis: { yAxis: {
name: '', name: '%',
min: 0, min: 0,
max: 100 max: 100
}, },
@@ -209,7 +216,7 @@ const info = (row: any) => {
dataZoom: null, dataZoom: null,
series: [ series: [
{ {
name: '数据完整', name: '数据完整',
type: 'bar', type: 'bar',
data: res.data.map((item: any) => item.integrityRate), data: res.data.map((item: any) => item.integrityRate),
@@ -225,14 +232,15 @@ const info = (row: any) => {
}) })
} }
defineExpose({ info }) defineExpose({ info, show })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.boxLeft { .boxLeft {
// background-color: #fff; background-color: #fff;
width: 25%; width: 100%;
padding: 10px 0px 10px 10px; padding: 10px 10px 10px 10px;
border-radius: 5px;
font-size: 13px; font-size: 13px;
overflow: hidden; overflow: hidden;
} }
@@ -241,84 +249,50 @@ defineExpose({ info })
// height: ; // height: ;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: 16px; font-size: 15px;
height: 22px;
line-height: 23px; line-height: 23px;
padding-left: 5px; padding-left: 5px;
width: 100%; width: 100%;
background-image: linear-gradient(to right, #a4e5da, #fff); font-weight: 550;
.info { .info {
font-weight: normal; font-weight: normal;
display: flex; display: flex;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
color: #757575;
} }
} }
.evaluate {
height: 60px; .imgL {
border: 1px solid #ccc;
margin: 10px 0;
padding: 10px 0;
display: flex;
justify-content: space-around;
text-align: center;
overflow-x: auto;
overflow-y: hidden;
}
.boxR {
border: 1px solid #ccc;
margin: 10px 0;
padding: 5px;
.num {
color: #2478f2;
}
.top {
display: flex;
justify-content: space-between;
}
.bottom {
margin: 0;
border: 0px;
}
}
:deep(.el-select) {
min-width: 120px;
}
.col {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.imgR {
position: absolute; position: absolute;
padding: 10px; padding: 10px;
top: calc(50% - 80px); top: calc(50% - 80px);
left: -23px; right: -23px;
z-index: 1;
transform: rotate(180deg);
height: 200px; height: 200px;
cursor: pointer; cursor: pointer;
} }
.show {
width: 0px;
transition: all 0.3s ease;
.boxLeft {
padding: 0;
}
}
.noshow {
width: 25%;
transition: all 0.3s ease;
.boxLeft {
padding: 10px 10px 10px 10px;
}
}
:deep(.el-card) { :deep(.el-card) {
.el-card__header { --el-card-padding: 10px !important;
padding: 5px 20px;
font-size: 1.2rem;
&::before {
width: 0.3rem;
height: 1.2rem;
margin-top: 0.3rem;
position: absolute;
content: '';
background: var(--el-color-primary);
border-radius: 0.02rem;
left: 1.2rem;
} }
} :deep(.el-table thead) {
.el-card__body { color: #000;
padding: 10px;
}
margin-bottom: 10px;
margin-right: 10px;
} }
</style> </style>

View File

@@ -1,26 +1,35 @@
<template> <template>
<div :class="show ? 'show' : 'noshow'">
<div class="boxLeft" :style="height"> <div class="boxLeft" :style="height">
<!-- 指标合格率统计 --> <!-- 指标合格率统计 -->
<div :style="`height:calc(${boxHeight.height} - 40px)`">
<el-card> <div class="title">
<template #header>
<div class="card-header" style="display: flex; justify-content: space-between">
<span>指标合格率统计</span> <span>指标合格率统计</span>
<span class="info" @click="open(0)"> <span class="info" @click="open(0)">
详情 详情
<ArrowRight style="width: 12px" /> <ArrowRight style="width: 12px" />
</span> </span>
</div> </div>
</template>
<MyEChart :style="`height:calc(${boxHeight.height} - 40px)`" :options="passingCharts" />
</el-card>
<el-card> <div style="display: flex" class="mt2">
<template #header> <img src="@/assets/img/FGX.png" />
<div class="card-header"> </div>
<span>稳态指标超标占比</span> <MyEChart :style="`height:calc(${EchHeight.height} - 40px)`" :options="passingCharts" />
</div>
<!-- 稳态指标超标占比 -->
<div :style="`height:calc(${boxHeight.height} + 40px)`">
<div class="title">
<span>稳态指标超标占比</span>
<span class="info" @click="open(1)">
详情
<ArrowRight style="width: 12px" />
</span>
</div>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div> </div>
</template>
<div> <div>
<div class="monitoringPoints"> <div class="monitoringPoints">
<div>在线监测点数{{ monitorList.onlineNum }}</div> <div>在线监测点数{{ monitorList.onlineNum }}</div>
@@ -28,104 +37,136 @@
<div>超标监测点占比{{ monitorList.overRatio }}</div> <div>超标监测点占比{{ monitorList.overRatio }}</div>
</div> </div>
<MyEChart :style="boxHeight" :options="exceededCharts" /> <MyEChart :style="`height:calc(${EchHeight.height} + 10px)`" :options="exceededCharts" />
</div> </div>
</el-card>
<!-- 稳态电能质量指标水平评估 -->
<el-card>
<template #header>
<div class="card-header">
<span>稳态电能质量指标水平评估</span>
</div> </div>
</template>
<div :style="`height:calc(${boxHeight.height} + 20px)`" class="boxSteps"> <!-- 暂态事件统计 -->
<el-segmented v-model="active" :options="Voltage" block @change="handleClick" /> <div :style="`height:calc(${boxHeight.height} - 10px)`">
<div class="evaluationData mt10"> <div class="title">
<div v-for="(item, i) in evaluationData"> <span>暂态事件统计</span>
<el-row style="width: 100%"> </div>
<el-col :span="12" style="display: flex">
<img :src="url[i]" /> <div style="display: flex" class="mt2">
<span>{{ item.targetName }}</span> <img src="@/assets/img/FGX.png" />
</el-col> </div>
<el-col :span="12" style="display: flex"> <MyEChart :style="`height:calc(${EchHeight.height} - 10px)`" :options="statisticsCharts" />
<div style="width: 50%"> </div>
均值
<span style="color: #339966">{{ item.avg == 3.14159 ? '--' : item.avg }}</span> <!-- 稳态电能质量指标水平评估 -->
<div>
<div class="title">
<span>技术监督管理</span>
<!-- <span class="info" @click="open(3)">
详情
<ArrowRight style="width: 12px" />
</span> -->
</div>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<div style="height: 150px" class="boxR">
<el-segmented v-model="active" :options="Voltage" block />
<el-row
style="height: calc(100% - 45px); display: flex; justify-content: space-around"
class="ml10 mr10 mt5"
>
<el-col :span="11" class="col pt10">
<div>
<span>异常问题总数</span>
<span style="color: #2dcd28">60</span>
</div> </div>
<div> <div>
标准差 <span style="width: 120px">已关联工单数</span>
<span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.avg }}</span> <span style="color: #81b337">60</span>
</div>
<div>
<span style="width: 120px"> 工单转换率</span>
<span style="color: #338dff">60%</span>
</div>
</el-col>
<el-col :span="11" class="col pt10" :offset="0.5">
<div>
<span>异常问题总数</span>
<span style="color: #2dcd28">60</span>
</div>
<div>
<span style="width: 120px">已关联工单数</span>
<span style="color: #81b337">60</span>
</div>
<div>
<span style="width: 120px"> 工单转换率</span>
<span style="color: #338dff">60%</span>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</div> </div>
</div>
</el-card>
<!-- 暂态事件统计 -->
<el-card>
<template #header>
<div class="card-header">
<span>暂态事件统计</span>
</div>
</template>
<MyEChart :style="boxHeight" :options="statisticsCharts" />
</el-card>
<!-- 指标合格率统计 --> <!-- 指标合格率统计 -->
<statistics ref="statisticsRef" /> <statistics ref="statisticsRef" />
<!-- 稳态指标超标占比 -->
<exceeded ref="exceededRef" />
</div>
<img
class="imgR"
:style="show ? 'transform: rotate(180deg);' : 'transform: rotate(0deg);'"
@click="show = !show"
src="@/assets/img/QH.png"
/>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, ref, provide } from 'vue' import { onMounted, reactive, ref, provide } from 'vue'
import statistics from '../components/city/statistics.vue' import statistics from '../components/city/statistics.vue'
import exceeded from '../components/city/exceeded.vue'
import MyEChart from '@/components/echarts/MyEchart.vue' import MyEChart from '@/components/echarts/MyEchart.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { color } from '@/components/echarts/color'
import { ArrowRight } from '@element-plus/icons-vue' import { ArrowRight } from '@element-plus/icons-vue'
import { getAssessDetail, evaluationDetail, getGeneralSituation, getEvaluationData } from '@/api/device-boot/panorama' import { getAssessDetail, evaluationDetail, getGeneralSituation } from '@/api/device-boot/panorama'
const dictData = useDictData() const dictData = useDictData()
const height = mainHeight(20) const height = mainHeight(30)
const boxHeight: any = mainHeight(280, 4) const show = ref(false)
const boxHeight: any = mainHeight(220, 3)
const EchHeight: any = mainHeight(320, 3)
const statisticsRef = ref() const statisticsRef = ref()
const exceededRef = ref()
const formRow: any = ref({}) const formRow: any = ref({})
const monitorList: any = ref({}) const monitorList: any = ref({})
const statisticsCharts: any = ref({}) const statisticsCharts: any = ref({})
const rowList: any = ref({})
const chartRef = ref()
const evaluationData: any = ref([])
const passingCharts = ref() const passingCharts = ref()
const exceededCharts = ref() const exceededCharts = ref()
const Voltage: any = dictData const Voltage: any = [
.getBasicData('Dev_Voltage_Stand') {
.filter(item => { label: '技术监督计划',
if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') { value: '0'
return item },
{
label: '在线监测',
value: '1'
},
{
label: '用户投诉',
value: '2'
},
{
label: '谐波普测',
value: '3'
} }
})
.map(item => {
return {
label: item.name,
value: item.id
}
})
const active: any = ref(Voltage[0].value)
const url: any = [
new URL(`@/assets/img/PLPC.png`, import.meta.url),
new URL(`@/assets/img/DYPC.png`, import.meta.url),
new URL(`@/assets/img/JBL.png`, import.meta.url),
new URL(`@/assets/img/SXDY.png`, import.meta.url),
new URL(`@/assets/img/SB.png`, import.meta.url)
] ]
const active: any = ref(Voltage[0].value)
const open = (e: number) => { const open = (e: number) => {
if (e == 0) { if (e == 0) {
statisticsRef.value.open(formRow.value) statisticsRef.value.open(formRow.value)
} else if (e == 1) {
exceededRef.value.open(formRow.value)
} }
} }
const info = (row: any) => { const info = (row: any) => {
@@ -137,7 +178,7 @@ const info = (row: any) => {
ids: [], ids: [],
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0], statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0],
isUpToGrid: row.isUpToGrid, isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid monitorFlag: row.isUpToGrid == 0 ? null : row.isUpToGrid
} }
formRow.value = form formRow.value = form
// 指标合格率统计 // 指标合格率统计
@@ -300,7 +341,8 @@ const info = (row: any) => {
}), }),
axisLabel: { axisLabel: {
color: '#000', color: '#000',
fontSize: 12 fontSize: 12,
interval:0
} }
}, },
grid: { grid: {
@@ -344,8 +386,6 @@ const info = (row: any) => {
}) })
// 稳态电能质量指标水平评估 // 稳态电能质量指标水平评估
handleClick(active.value)
// 暂态电能质量水平评估
getGeneralSituation({ ...form, monitorFlag: form.isUpToGrid == 0 ? 2 : 1 }).then(res => { getGeneralSituation({ ...form, monitorFlag: form.isUpToGrid == 0 ? 2 : 1 }).then(res => {
statisticsCharts.value = { statisticsCharts.value = {
tooltip: {}, tooltip: {},
@@ -384,51 +424,65 @@ const info = (row: any) => {
}) })
} }
// 点击电压等级 defineExpose({ info, show })
const handleClick = (i: any) => {
active.value = i
getEvaluationData({
...formRow.value,
voltageLevel: i
}).then(res => {
evaluationData.value = res.data
})
}
defineExpose({ info })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.boxLeft { .boxLeft {
// background-color: #fff; background-color: #fff;
width: 25%; width: 100%;
padding: 10px 0px 10px 10px; padding: 10px 10px 10px 10px;
font-size: 13px; font-size: 13px;
overflow: hidden; overflow: hidden;
border-radius: 5px;
} }
.title {
// height: ;
display: flex;
justify-content: space-between;
font-size: 15px;
line-height: 23px;
padding-left: 5px;
width: 100%;
font-weight: 550;
.info { .info {
font-weight: normal; font-weight: normal;
display: flex; display: flex;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
align-items: center; color: #757575;
}
}
.TJTop {
display: flex;
img {
height: 1.2rem;
width: 1.2rem;
margin-right: 5px;
}
} }
.evaluate { .evaluate {
height: 60px;
border: 1px solid #ccc;
margin: 10px 0; margin: 10px 0;
padding: 10px 0;
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
text-align: center; text-align: center;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
.line {
display: inline-block;
width: 0.5rem;
height: 0.5rem;
border-radius: 0.25rem;
background: var(--el-color-primary);
margin-right: 2px;
margin-bottom: 1px;
}
} }
.boxR { .boxR {
border: 1px solid #ccc; margin: 10px 0 0 0;
margin: 10px 0;
padding: 5px;
.num { .num {
color: #2478f2; color: #2478f2;
} }
@@ -440,48 +494,62 @@ defineExpose({ info })
margin: 0; margin: 0;
border: 0px; border: 0px;
} }
}
:deep(.el-card) { .harmonic {
.el-card__header { display: grid;
padding: 5px 20px; .progress {
font-size: 1.2rem; display: flex;
&::before { align-items: center;
width: 0.3rem; .text {
height: 1.2rem; width: 50px;
margin-top: 0.3rem; font-size: 12px;
}
.el-progress {
flex: 1;
}
}
}
}
:deep(.el-select) {
min-width: 120px;
}
.col {
display: grid;
grid-template-columns: 1fr;
border-radius: 10px;
text-align: center;
background-color: #edededc0;
}
.imgR {
position: absolute; position: absolute;
content: '';
background: var(--el-color-primary);
border-radius: 0.02rem;
left: 1.2rem;
}
}
.el-card__body {
padding: 10px; padding: 10px;
top: calc(50% - 80px);
left: -23px;
height: 200px;
cursor: pointer;
} }
margin-bottom: 10px; .show {
margin-right: 10px; width: 0px;
transition: all 0.3s ease;
.boxLeft {
padding: 0;
}
}
.noshow {
width: 25%;
transition: all 0.3s ease;
.boxLeft {
padding: 10px 10px 10px 10px;
}
}
:deep(.el-progress__text) {
font-size: 0.8rem !important ;
} }
.monitoringPoints { .monitoringPoints {
display: grid; display: grid;
grid-template-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
text-align: center; margin-top: 10px;
} margin-bottom: 10px;
:deep(.boxSteps) {
font-size: 1rem;
.evaluationData {
display: grid;
height: calc(100% - 30px);
grid-template-rows: repeat(5, auto);
}
img {
width: 1.3rem;
height: 1.3rem;
margin-right: 10px;
}
}
:deep(.el-segmented) {
--el-border-radius-base: 16px;
} }
</style> </style>

View File

@@ -1,9 +1,9 @@
<template> <template>
<!-- 综合评估详情 --> <!-- 综合评估详情 -->
<el-dialog draggable title="综合评估详情" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="综合评估统计" v-model="dialogVisible" width="1400px">
<div> <div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="deptName" title="所属区域" /> <vxe-column field="deptName" title="地市" />
<vxe-column field="assessData" title="综合评估得分" :formatter="formatter" /> <vxe-column field="assessData" title="综合评估得分" :formatter="formatter" />
<vxe-column field="qualifyData" title="指标合格率" :formatter="formatter" /> <vxe-column field="qualifyData" title="指标合格率" :formatter="formatter" />
<vxe-colgroup title="各项指标得分"> <vxe-colgroup title="各项指标得分">
@@ -55,8 +55,8 @@ const open = async (row: any) => {
text: '各地市综合评估趋势对比' text: '各地市综合评估趋势对比'
}, },
xAxis: { xAxis: {
name: '(区域)', name: '时间',
data: res.data.map((item: any) => item.deptName) data: res.data[0].children.map((item: any) => item.dataTime)
}, },
grid: { grid: {
bottom: '10px' bottom: '10px'
@@ -73,13 +73,10 @@ const open = async (row: any) => {
let list: any = [] let list: any = []
let time: any = [] let time: any = []
res.data.forEach((item: any, num: any) => { res.data.forEach((item: any, num: any) => {
time = [] time.push(item.deptName)
item.children.forEach((val: any, i: any) => {
if (num == 0) {
list.push([]) list.push([])
} item.children.forEach((val: any, i: any) => {
time.push(val.dataTime) list[num].push(val.score == 3.14159 ? null : val.score)
list[i].push(val.score == 3.14159 ? null : val.score)
}) })
}) })
list.forEach((item: any, i: any) => { list.forEach((item: any, i: any) => {

View File

@@ -1,6 +1,6 @@
<template> <template>
<!-- 监测点详情 --> <!-- 监测点详情 -->
<el-dialog draggable title="监测点详情" v-model="dialogVisible" width="1400px" :before-close="handleClose"> <el-dialog draggable title="监测点统计" v-model="dialogVisible" width="1400px" :before-close="handleClose">
<el-row style="height: 300px" :gutter="20"> <el-row style="height: 300px" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
@@ -31,22 +31,14 @@
</el-row> </el-row>
<div> <div>
<div class="title"> <div class="title">
<span>监测点详细列表</span> <span>区域监测点统计</span>
</div> </div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="lineName" title="监测点名称" /> <vxe-column field="orgName" title="区域" :formatter="formatter" />
<vxe-column field="areaName" title="所属区域" /> <vxe-column field="num" title="监测点个数" :formatter="formatter" />
<vxe-column field="subName" title="所属变电站" /> <vxe-column field="integrityRate" title="数据完整率(%)" />
<vxe-column field="voltageScale" title="电压等级" :formatter="formatter" /> <vxe-column field="onLineRate" title="数据在线率(%)" />
<vxe-column field="loadType" title="负荷类型" :formatter="formatter" /> <vxe-column field="outOfStandardRate" title="超标监测点占比(%)" />
<vxe-column field="comFlag" title="通讯状态">
<template #default="scope">
<el-tag type="success" v-if="scope.row.comFlag == 1">正常</el-tag>
<el-tag type="danger" v-else>中断</el-tag>
</template>
</vxe-column>
<vxe-column field="onlineRate" title="在线率(%)" />
<vxe-column field="integrityData" title="数据完整性(%)" />
</vxe-table> </vxe-table>
</div> </div>
</el-dialog> </el-dialog>
@@ -62,7 +54,7 @@ const dialogVisible: any = ref(false)
const Voltage = dictData.getBasicData('Dev_Voltage_Stand') const Voltage = dictData.getBasicData('Dev_Voltage_Stand')
const tableData: any = ref([]) const tableData: any = ref([])
const options = dictData.getBasicData('Statistical_Type', ['Report_Type']) const options = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Power_Network'])
const time = ref('1') const time = ref('1')
const statisticalType = ref(options[0]) const statisticalType = ref(options[0])
const loadTypeArr = dictData.getBasicData('Interference_Source') const loadTypeArr = dictData.getBasicData('Interference_Source')
@@ -84,8 +76,11 @@ const open = async (row: any) => {
// 统计 // 统计
statiStics() statiStics()
// 监测点列表 // 监测点列表
getHalfReport(rowList.value).then((res: any) => { getGridDiagramLineData({
tableData.value = res.data.records ...rowList.value,
statisticalType: rowList.value.deviceInfoParam.statisticalType
}).then((res: any) => {
tableData.value = res.data
}) })
dialogVisible.value = true dialogVisible.value = true
@@ -145,15 +140,15 @@ const statiStics = () => {
text: '' text: ''
}, },
xAxis: { xAxis: {
data: res.data.map((item: any) => item.orgName) data: res.data.map((item: any) => item.orgName)
}, },
yAxis: { yAxis: {
name: '', name: '%',
min: 0, min: 0,
max: 100 max: 100
}, },
options: { options: {
dataZoom: null,
series: [ series: [
{ {
name: '数据完整性', name: '数据完整性',
@@ -192,10 +187,10 @@ const statiStics = () => {
}) })
} }
const formatter = (row: any) => { const formatter = (row: any) => {
if (row.column.field == 'loadType') { if (row.column.field == 'orgName') {
return loadTypeArr.filter((item: any) => item.id == row.cellValue)[0]?.name return row.cellValue.match(/[\u4e00-\u9fa5]+/g).join('')
} else if (row.column.field == 'voltageScale') { } else if (row.column.field == 'num') {
return Voltage.filter((item: any) => item.id == row.cellValue)[0]?.name return row.row.orgName.match(/\(([^]+)\)/)[1]
} else { } else {
return row.cellValue return row.cellValue
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<!-- 变电站 --> <!-- 变电站 -->
<el-dialog draggable title="变电站详情" v-model="dialogVisible" width="1400px" :before-close="handleClose"> <el-dialog draggable title="变电站统计" v-model="dialogVisible" width="1400px" :before-close="handleClose">
<el-row style="height: 300px" :gutter="20"> <el-row style="height: 300px" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
@@ -39,16 +39,21 @@
</div> </div>
<div class="pie"> <div class="pie">
<MyEChart v-for="item in picEChart" class="MyEChart" :options="item" /> <MyEChart
v-for="(item, i) in picEChart"
:style="i == 3 ? `margin-left: 20%;` : ``"
class="MyEChart"
:options="item"
/>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div> <div>
<div class="title mb10"> <div class="title mb10">
<span>变电站详细列表</span> <span>区域变电站统计</span>
</div> </div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="name" title="所属区域" /> <vxe-column field="name" title="区域" />
<vxe-column field="num" title="变电站总数" /> <vxe-column field="num" title="变电站总数" />
<vxe-column field="num1" title="无污染数量" :formatter="formatter" /> <vxe-column field="num1" title="无污染数量" :formatter="formatter" />
<vxe-column field="num2" title="轻微污染数量" :formatter="formatter" /> <vxe-column field="num2" title="轻微污染数量" :formatter="formatter" />
@@ -96,23 +101,11 @@ const open = async (row: any) => {
// 污染 // 污染
contaminateC() contaminateC()
// 列表 // 列表
getPollutionAlarmList(rowList.value).then(res => {
tableData.value = res.data.map((item: any) => {
return {
name: item[0],
num: item[1],
num1: item[2],
num2: item[3],
num3: item[4],
num4: item[5],
num5: item[5]
}
})
})
dialogVisible.value = true dialogVisible.value = true
} }
const contaminateC = () => { const contaminateC = () => {
// rowList.value.deviceInfoParam.ids=[contaminate.value]
getPollutionAlarmData({ ...rowList.value, ids: [contaminate.value] }).then(res => { getPollutionAlarmData({ ...rowList.value, ids: [contaminate.value] }).then(res => {
let data = [] let data = []
@@ -213,14 +206,15 @@ const contaminateC = () => {
show: false show: false
}, },
axisLabel: { axisLabel: {
distance: 5, show: false
color: '#666', // distance: 5,
fontSize: 12, // color: '#666',
formatter: function (value: any) { // fontSize: 12,
if (value === 0 || value === 100) { // formatter: function (value: any) {
return value + '%' // if (value === 0 || value === 100) {
} // return value + '%'
} // }
// }
}, },
anchor: { anchor: {
show: false, show: false,
@@ -260,6 +254,19 @@ const contaminateC = () => {
} }
}) })
}) })
getPollutionAlarmList({ ...rowList.value, ids: [contaminate.value] }).then(res => {
tableData.value = res.data.map((item: any) => {
return {
name: item[0],
num: item[1],
num1: item[2],
num2: item[3],
num3: item[4],
num4: item[5],
num5: item[5]
}
})
})
} }
const analysis = (e: any) => { const analysis = (e: any) => {
let time = rowList.value.searchBeginTime?.slice(0, 4) + `-01-01` let time = rowList.value.searchBeginTime?.slice(0, 4) + `-01-01`

View File

@@ -1,7 +1,7 @@
<!-- 稳态 --> <!-- 稳态 -->
<template> <template>
<!-- 终端 --> <!-- 终端 -->
<el-dialog draggable title="稳态电能质量水平评估详情" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="稳态电能质量水平评估统计" v-model="dialogVisible" width="1400px">
<el-row style="height: 330px" :gutter="20"> <el-row style="height: 330px" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
@@ -31,7 +31,7 @@
</div> </div>
<div> <div>
标准差 标准差
<span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.avg }}</span> <span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.sd }}</span>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
@@ -48,10 +48,10 @@
</el-row> </el-row>
<div> <div>
<div class="title"> <div class="title">
<span>稳态电能质量水平评估详细列表</span> <span>区域稳态电能质量水平评估</span>
</div> </div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="deptName" title="区域名称" /> <vxe-column field="deptName" title="区域" />
<vxe-column field="onlineNum" title="在线监测点数量(个)" /> <vxe-column field="onlineNum" title="在线监测点数量(个)" />
<vxe-column field="overNum" title="超标监测点数量(个)" /> <vxe-column field="overNum" title="超标监测点数量(个)" />
<vxe-column field="overRatio" title="超标监测点占比(%)" /> <vxe-column field="overRatio" title="超标监测点占比(%)" />

View File

@@ -1,6 +1,6 @@
<!-- 技术 --> <!-- 技术 -->
<template> <template>
<el-dialog draggable title="技术监督管理详情" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="技术监督管理统计" v-model="dialogVisible" width="1400px">
<div> <div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="devName" /> <vxe-column field="devName" />
@@ -24,11 +24,7 @@ import { defaultAttribute } from '@/components/table/defaultAttribute'
const dialogVisible: any = ref(false) const dialogVisible: any = ref(false)
const tableData: any = ref([ const tableData: any = ref([])
{
devName: 123
}
])
const picEChart = ref({ const picEChart = ref({
title: { title: {

View File

@@ -1,9 +1,9 @@
<!-- 暂态 --> <!-- 暂态 -->
<template> <template>
<el-dialog draggable title="暂态电能质量水平评估详情" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="暂态电能质量水平评估统计" v-model="dialogVisible" width="1400px">
<div> <div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="name" title="所属区域" /> <vxe-column field="name" title="区域" />
<vxe-column field="sagTimes" title="暂降次数" /> <vxe-column field="sagTimes" title="暂降次数" />
<vxe-column field="swellTimes" title="暂升次数" /> <vxe-column field="swellTimes" title="暂升次数" />
@@ -32,7 +32,7 @@
<div class="statistics-box"> <div class="statistics-box">
<MyEChart style="height: 300px" :options="picEChart1" /> <MyEChart style="height: 300px" :options="picEChart1" />
<el-table size="small" height="300px" :data="resembleData"> <el-table size="small" height="300px" :data="resembleData">
<el-table-column prop="name" label="暂降原因" width="80px" align="center" /> <el-table-column prop="name" label="暂降类型" width="80px" align="center" />
<el-table-column prop="value" label="暂降次数" width="80px" align="center" /> <el-table-column prop="value" label="暂降次数" width="80px" align="center" />
</el-table> </el-table>
</div> </div>
@@ -66,7 +66,8 @@ const open = async (row: any) => {
trigger: 'item' trigger: 'item'
}, },
legend: { legend: {
orient: 'vertical' orient: 'vertical',
left: '10px'
}, },
xAxis: { xAxis: {
show: false show: false
@@ -79,7 +80,7 @@ const open = async (row: any) => {
series: [ series: [
{ {
type: 'pie', type: 'pie',
center: ['40%', '50%'], center: ['60%', '50%'],
radius: '50%', radius: '50%',
label: { label: {
show: false, show: false,
@@ -98,7 +99,8 @@ const open = async (row: any) => {
trigger: 'item' trigger: 'item'
}, },
legend: { legend: {
orient: 'vertical' orient: 'vertical',
left: '10px'
}, },
xAxis: { xAxis: {
show: false show: false
@@ -111,7 +113,7 @@ const open = async (row: any) => {
series: [ series: [
{ {
type: 'pie', type: 'pie',
center: ['40%', '50%'], center: ['60%', '50%'],
radius: '50%', radius: '50%',
label: { label: {
show: false, show: false,

View File

@@ -1,6 +1,6 @@
<template> <template>
<!-- 终端 --> <!-- 终端 -->
<el-dialog draggable title="终端统计详情" v-model="dialogVisible" width="1400px" :before-close="handleClose"> <el-dialog draggable title="终端统计" v-model="dialogVisible" width="1400px" :before-close="handleClose">
<el-row style="height: 300px" :gutter="20"> <el-row style="height: 300px" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
@@ -50,30 +50,14 @@
</el-row> </el-row>
<div> <div>
<div class="title"> <div class="title">
<span>终端统计细列表</span> <span>区域终端统计</span>
</div> </div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="300px" :data="tableData">
<vxe-column field="devName" title="终端名称" /> <vxe-column field="orgName" title="区域" />
<vxe-column field="areaName" title="所属区域" /> <vxe-column field="runNum" title="运行个数 " />
<vxe-column field="bdName" title="所属变电站" /> <vxe-column field="overhaulNum" title="检修个数 " />
<vxe-column field="devType" title="终端型号" /> <vxe-column field="refundNum" title="退役个数" />
<vxe-column field="loginTime" title="投运时间" /> <vxe-column field="onLineRate" title="数据在线率(%)" />
<vxe-column field="runFlag" title="终端状态">
<template #default="scope">
<el-tag :type="scope.row.runFlag == '投运' ? 'success' : 'danger'">
{{ scope.row.runFlag }}
</el-tag>
</template>
</vxe-column>
<vxe-column field="comFlag" title="通讯状态">
<template #default="scope">
<el-tag :type="scope.row.comFlag == '正常' ? 'success' : 'danger'">
{{ scope.row.comFlag }}
</el-tag>
</template>
</vxe-column>
<vxe-column field="updateTime" title="最新数据时间" />
<vxe-column field="onlineEvaluate" title="终端在线率(%)" :formatter="formatter" />
</vxe-table> </vxe-table>
</div> </div>
</el-dialog> </el-dialog>
@@ -83,7 +67,7 @@ import { ref } from 'vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import MyEChart from '@/components/echarts/MyEchart.vue' import MyEChart from '@/components/echarts/MyEchart.vue'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getGridDiagramDevTendency, getGridDiagramDevData, getRuntimeData } from '@/api/device-boot/panorama' import { getGridDiagramDevTendency, getGridDiagramDevData, getGridDiagramDevDataList } from '@/api/device-boot/panorama'
const dictData = useDictData() const dictData = useDictData()
const dialogVisible: any = ref(false) const dialogVisible: any = ref(false)
const time = ref('1') const time = ref('1')
@@ -122,6 +106,10 @@ const open = async (row: any) => {
}) })
picEChart.value = { picEChart.value = {
tooltip: {
trigger: 'item',
formatter: '{b} :在运终端数 {c} 台'
},
legend: { legend: {
show: false show: false
}, },
@@ -161,13 +149,23 @@ const open = async (row: any) => {
} }
}) })
// 列表 // 列表
getRuntimeData({ getGridDiagramDevDataList({
deviceInfoParam: {
...row, ...row,
serverName: 'pqs-common', serverName: 'pqs-common',
ids: [row.id],
runFlag: [], runFlag: [],
comFlag: [], comFlag: [],
manufacturer: dictData.getBasicData('Dev_Manufacturers'), manufacturer: dictData.getBasicData('Dev_Manufacturers'),
statisticalType: {} statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0]
},
...row,
serverName: 'pqs-common',
ids: [row.id],
runFlag: [],
comFlag: [],
manufacturer: dictData.getBasicData('Dev_Manufacturers'),
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0]
}).then((res: any) => { }).then((res: any) => {
tableData.value = res.data tableData.value = res.data
}) })

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,613 @@
<template>
<div class="default-main lineInfo" :style="height">
<DatePicker ref="datePickerRef" style="display: none" />
<el-page-header :icon="ArrowLeft" @back="emit('back')">
<template #content>
<span class="text-large font-600 mr-3">{{ dropList.lineName }}详情</span>
</template>
</el-page-header>
<el-row :gutter="20" class="mt10" :style="`height:${rowHeight}`">
<el-col :span="8">
<h3 class="mb10 iconBox">
<span></span>
台账信息
</h3>
<el-descriptions title="" border :column="2">
<el-descriptions-item label="监测点名称">{{ dropList.lineName }}</el-descriptions-item>
<el-descriptions-item label="所属厂家">{{ dropList.manufacturer }}</el-descriptions-item>
<el-descriptions-item label="电压等级">{{ dropList.scale }}</el-descriptions-item>
<el-descriptions-item label="投运日期">{{ dropList.loginTime }}</el-descriptions-item>
<el-descriptions-item label="PT">{{ dropList.pt }}</el-descriptions-item>
<el-descriptions-item label="CT">{{ dropList.ct }}</el-descriptions-item>
<el-descriptions-item label="干扰源类型">{{ dropList.loadType }}</el-descriptions-item>
<el-descriptions-item label="通讯状态">
<el-tag size="small" :type="dropList.comFlag == '正常' ? 'success' : 'danger'" effect="dark">
{{ dropList.comFlag }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-col>
<el-col :span="8">
<h3 class="mb10 iconBox">
<span></span>
数据质量
</h3>
<div style="display: flex">
<MyEChart :style="`height: calc(${rowHeight} - 31px)`" :options="ComCharts" />
<MyEChart :style="`height: calc(${rowHeight} - 31px)`" :options="onLineCharts" />
</div>
</el-col>
<el-col :span="8">
<h3 class="mb10 iconBox">
<span></span>
监测点总体评价结论
</h3>
<div class="evaluationData">
<el-row style="width: 96%" class="row pb5">
<el-col :span="12" style="display: flex">
<span>{{ dropList.lineName }}</span>
</el-col>
<el-col :span="12" style="display: flex">
<div>
综合评估得分:
<span style="color: #299edf">
{{ dropList.assessData == 3.14159 ? '--' : dropList.assessData }}
</span>
</div>
</el-col>
</el-row>
<el-row style="width: 96%" v-for="(item, i) in evaluationData" class="row pb5">
<el-col :span="14" style="display: flex">
<img :src="url[i]" />
<span>{{ item.targetName }}</span>
</el-col>
<el-col :span="10" style="display: flex">
<div style="width: 100%">
评估得分
<span style="color: #299edf">{{ item.avg == 3.14159 ? '--' : item.avg }}</span>
</div>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<el-row :gutter="20" class="mt10" :style="`height:${rowHeight}`">
<el-col :span="8">
<h3 class="mb10 iconBox">
<span></span>
稳态指标合格率
</h3>
<div :style="`height: calc(${rowHeight} - 31px)`" ref="chartRef"></div>
</el-col>
<el-col :span="8">
<h3 class="mb10 iconBox">
<span></span>
暂态事件统计
</h3>
<MyEChart :style="`height: calc(${rowHeight} - 31px)`" :options="incidentCharts" />
</el-col>
</el-row>
<el-row :gutter="20" class="mt10" :style="`height:${rowHeight}`">
<el-col :span="24">
<h3 class="mb10 iconBox">
<span></span>
历史趋势图
</h3>
<history :lineId="lineId" ref="historyRef" />
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, provide } from 'vue'
import { ArrowLeft } from '@element-plus/icons-vue'
import { mainHeight } from '@/utils/layout'
import history from './history.vue'
import { color } from '@/components/echarts/color'
import DatePicker from '@/components/form/datePicker/index.vue'
import MyEChart from '@/components/echarts/MyEchart.vue'
import echarts from '@/components/echarts/echarts'
import { getLineDetailData } from '@/api/advance-boot/bearingCapacity'
import {
getTotalIntegrityByLineIds,
getTotalOnlineRates,
lineQualifiedDetail,
getLineAssess,
getEventDetailByLineId
} from '@/api/device-boot/panorama'
import { title } from 'process'
import { fontWeight } from 'html2canvas/dist/types/css/property-descriptors/font-weight'
const emit = defineEmits(['back'])
const dropList: any = ref({})
const evaluationData: any = ref([])
const incidentCharts: any = ref({})
const ComCharts: any = ref({})
const onLineCharts: any = ref({})
const datePickerRef = ref()
const chartRef = ref<HTMLDivElement>()
const historyRef = ref()
const url: any = [
new URL(`@/assets/img/PLPC.png`, import.meta.url),
new URL(`@/assets/img/DYPC.png`, import.meta.url),
new URL(`@/assets/img/JBL.png`, import.meta.url),
new URL(`@/assets/img/SXDY.png`, import.meta.url),
new URL(`@/assets/img/SB.png`, import.meta.url)
]
const lineId: any = ref('')
const height = mainHeight(20)
const rowHeight = mainHeight(190, 3).height
// 查询
const open = async (id: string) => {
let form = {
comFlag: 1,
endTime: datePickerRef.value.timeValue[1],
lineIds: [id],
ids: [id],
searchValue: '',
startTime: datePickerRef.value.timeValue[0]
}
lineId.value = id
const { data } = await getLineDetailData({ id: id })
dropList.value = data
// 运行状态
// 完整性
getTotalIntegrityByLineIds(form).then((res: any) => {
let num = (res.data || 0) / 100
ComCharts.value = {
title: {
text: '完整性',
bottom: '10%',
left: 'center',
textStyle: {
fontSize: 16
}
},
xAxis: {
show: false
},
yAxis: {
show: false
},
options: {
dataZoom: null,
series: [
{
//第二个球的填充
type: 'liquidFill',
radius: '65%',
center: ['50%', '40%'], //中心点
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 1,
color: '#2aa1e3'
}
],
globalCoord: false
}
],
data: [num, num], // data个数代表波浪数
backgroundStyle: {
borderWidth: 1,
color: '#f7f8fc'
},
label: {
normal: {
textStyle: {
fontSize: 20,
color: '#000'
}
}
},
outline: {
// show: false
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
}
}
}
]
}
}
// 稳态指标合格率
})
// 在线率
getTotalOnlineRates(form).then((res: any) => {
let num = (res.data || 0) / 100
onLineCharts.value = {
title: {
text: '在线率',
bottom: '10%',
left: 'center',
textStyle: {
fontSize: 16
}
},
xAxis: {
show: false
},
yAxis: {
show: false
},
options: {
dataZoom: null,
series: [
{
//第二个球的填充
type: 'liquidFill',
radius: '65%',
center: ['50%', '40%'], //中心点
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 1,
color: '#67c23a'
}
],
globalCoord: false
}
],
data: [num, num], // data个数代表波浪数
backgroundStyle: {
color: '#f7f8fc'
},
label: {
normal: {
textStyle: {
fontSize: 20,
color: '#000'
}
}
},
outline: {
// show: false
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
}
}
}
]
}
}
})
// 监测点总体评价结论
getLineAssess({
lineId: id,
startTime: datePickerRef.value.timeValue[0],
endTime: datePickerRef.value.timeValue[1]
}).then((res: any) => {
dropList.value.assessData = res.data.assessData
evaluationData.value = [
{
targetName: '频率偏差',
avg: res.data.freqAssessData,
sd: res.data.freqQualifyData
},
{
targetName: '电压偏差',
avg: res.data.vdevAssessData,
sd: res.data.vdevQualifyData
},
{
targetName: '电压总谐波畸变率',
avg: res.data.harmAssessData,
sd: res.data.harmQualifyData
},
{
targetName: '三相电压不平衡度',
avg: res.data.unbalanceAssessData,
sd: res.data.unbalanceQualifyData
},
{
targetName: '闪变',
avg: res.data.flickerAssessData,
sd: res.data.flickerQualifyData
}
]
})
// 稳态指标合格率
lineQualifiedDetail({
lineId: id,
startTime: datePickerRef.value.timeValue[0],
endTime: datePickerRef.value.timeValue[1]
}).then(res => {
echart([
{
time: datePickerRef.value.timeValue[0].substring(0, 7),
targetList: ['频率偏差', '电压偏差', '电压总谐波畸变率', '三相电压不平衡度', '闪变'],
ratioList: [
res.data.freqDev == 3.14159 ? null : res.data.freqDev,
res.data.vdev == 3.14159 ? null : res.data.vdev,
res.data.vthd == 3.14159 ? null : res.data.vthd,
res.data.ubalance == 3.14159 ? null : res.data.ubalance,
res.data.plt == 3.14159 ? null : res.data.plt
]
}
])
})
// 暂态事件统计
getEventDetailByLineId({
id: id,
startTime: datePickerRef.value.timeValue[0],
endTime: datePickerRef.value.timeValue[1],
type: datePickerRef.value.interval
}).then((res: any) => {
let data = [
{
name: '电压暂升',
value: res.data?.swellTimes || 0
},
{
name: '电压暂降',
value: res.data?.sagTimes || 0
},
{
name: '电压中断',
value: res.data?.interruptTimes || 0
}
]
incidentCharts.value = {
title: {
text: `${res.data?.swellTimes + res.data?.sagTimes + res.data?.interruptTimes}`,
left: '37%',
top: '40%',
textStyle: {
fontWeight: 600,
fontSize: 16
},
subtext: '总数',
subtextStyle: {
fontWeight: 550,
fontSize: 14
}
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
top: 'center',
right: '10%',
formatter: function (e: any) {
console.log('🚀 ~ open ~ e:', e)
return e + ' ' + data.filter(item => item.name == e)[0].value + '条'
}
},
xAxis: {
show: false
},
yAxis: {
show: false
},
options: {
dataZoom: null,
series: [
{
type: 'pie',
center: ['40%', '50%'],
radius: ['50%', '70%'],
label: {
show: false,
position: 'outside',
textStyle: {
//数值样式
}
},
data: data
}
]
}
}
// incidentCharts.value = {
// title: {
// text: ''
// },
// legend: {
// show: true,
// right: 90
// },
// xAxis: {
// data: ['电压暂升', '电压暂降', '电压中断']
// },
// yAxis: {
// name: '条'
// },
// grid: {
// top: '35px',
// left: '20px',
// right: '20px'
// },
// options: {
// dataZoom: null,
// series: [
// {
// type: 'bar',
// data: [res.data?.swellTimes, res.data?.sagTimes, res.data?.interruptTimes],
// label: {
// show: true,
// position: 'top',
// fontSize: 12
// }
// }
// ]
// }
// }
})
}
const echart = (row: any) => {
let chart = echarts.init(chartRef.value as HTMLDivElement)
let dataname = ['频率偏差', '电压偏差', '电压总谐波畸变率', '三相电压不平衡度', '闪变']
let datamax = [100, 100, 100, 100, 100, 100]
let indicator = []
for (let i = 0; i < dataname.length; i++) {
indicator.push({
name: dataname[i],
max: datamax[i]
})
}
let option: any = {
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.35)',
borderWidth: 0
},
legend: {
data: row.map((item: any) => item.time),
type: 'scroll',
orient: 'vertical',
icon: 'roundRect',
right: '20',
itemGap: 10,
itemWidth: 16,
itemHeight: 16,
textStyle: {
fontSize: '15',
color: '#656565'
}
},
radar: {
center: ['50%', '50%'],
radius: '65%',
startAngle: 90,
splitNumber: 5,
splitArea: {
areaStyle: {
color: ['#FFFFFF', '#F5F9FF'].reverse()
}
},
axisLabel: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: '#D2E4F8'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#D2E4F8'
}
},
name: {
formatter: '{value}',
textStyle: {
color: '#656565',
fontSize: 15
}
},
indicator: indicator
},
series: []
}
row.forEach((item: any, i: any) => {
option.series.push({
name: item.time,
type: 'radar',
symbol: 'none',
areaStyle: {
normal: {
color: '#2a9fe069'
}
},
itemStyle: {
color: '#2a9fe0'
},
data: [item.ratioList]
})
})
chart.setOption(option)
}
onMounted(() => {
// open('4c87b7dff2281254fc55c25a4da31506')
})
defineExpose({ open })
</script>
<style lang="scss" scoped>
.lineInfo {
padding: 0 10px 10px 10px;
}
:deep(.el-page-header__header) {
height: 45px;
border-bottom: 1px solid #f1eded;
}
:deep(.el-descriptions__header) {
margin-bottom: 10px;
}
.evaluationData {
display: grid;
grid-template-rows: repeat(5, auto);
.row {
margin: 5px 2%;
width: 100%;
box-shadow: 1px 1px 1px 1px #e8e3e3;
}
img {
width: 7%;
margin: 0px 15px;
}
}
.iconBox {
display: flex;
span {
display: inline-block;
width: 3px;
height: 18px;
background: var(--el-color-primary);
margin-right: 5px;
margin-left: 3px;
}
}
</style>

View File

@@ -0,0 +1,717 @@
<template>
<DatePicker ref="datePickerRef" style="display: none" />
<div id="map" style="width: 100%; height: 100%" v-show="prop.lineInfo"></div>
<div id="nrDeviceCard"></div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, nextTick } from 'vue'
import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
// import { devicesDemo } from '@/assets/panorama/devicesDemo.js'
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
import DatePicker from '@/components/form/datePicker/index.vue'
import '@/assets/panorama/narimap.css'
import '@/assets/panorama/nrgisCommon.css'
const emit = defineEmits(['changeValue', 'drop', 'show'])
const prop = defineProps({
lineInfo: {
type: Boolean
}
})
const narimap = window?.narimap
const dictData = useDictData()
const datePickerRef = ref()
const map: any = ref(null)
const deviceCard: any = ref(null)
const popup: any = ref(null)
const markerGroup: any = ref(null)
const orgId = ref(dictData.state.area[0].code)
narimap.Require(
['PSRMap', 'Thematic', 'Components.Query', 'Components.RegionSelector', 'Components.DeviceTreeGW'],
() => {
if (narimap.Config.examples.notlogin) {
initMap(narimap.Config.styles.sjDark)
} else {
//电网GIS地图服务登录
narimap.SGAuth.login()
.then((result: any) => {
if (result.success) {
console.log('登录成功')
} else {
console.log('登录失败', result)
}
//默认打开电网GIS影像图
initMap(narimap.Config.styles.sjDark)
})
.catch((err: any) => {
console.log('错误', err)
})
}
}
)
function initMap(styleurl: any) {
map.value = new narimap.Map({
container: 'map',
style: styleurl,
zoom: 6,
center: [116.478935, 39.997761],
controls: false,
country: true,
// 地图默认字体
localIdeographFontFamily: 'Microsoft YoHei'
})
map.value.on('load', () => {
nextTick(() => {
// 加载点
addMarkers()
// 查询组件
Query()
})
})
}
const Query = () => {
// 添加行政区划
let powerManageGridMap = new narimap.ManageGrid.PowerManageGridMap(map.value)
powerManageGridMap.init(
{
base: {
outline: {
paint: {
'line-color': '#0D867F',
'line-width': 1,
'line-opacity': 1
}
},
fill: {
paint: {
'fill-color': '#0D867F',
'fill-opacity': 0
}
},
label: {
paint: {
'text-color': '#063094',
'text-halo-color': '#ffffff',
'text-halo-width': 1
}
},
hover: {
enable: !0,
type: 'all',
fill: {
enable: !0,
paint: {
'fill-color': 'rgba(1,1,1,0)',
'fill-opacity': 0
}
},
outline: {
enable: !0,
paint: {
'line-color': '#0D867F',
'line-width': 4,
'line-opacity': 1
}
}
}
}
},
{
initOrgIds: [orgId.value],
//是否联级,包含下属全部子部门,即同样显示编码对应的所属下级
cascade: true
}
)
// 添加区域选择
let component = new narimap.Components.RegionSelector(map.value, {
isIntegratedGridmap: true,
//是否联级,包含下属全部子部门,即同样显示编码对应的所属下级
cascade: true,
orgId: orgId.value
})
component.on('regionSelect', (e: any) => {
emit('changeValue', e)
})
setTimeout(() => {
addLine()
const query = new narimap.Components.Query(map.value)
query.init(map.value.getContainer())
query.setQueryOrgId(orgId.value)
}, 500)
}
// 添加变电站线路
const addLine = () => {
//添加电网图层
let psrmap = new narimap.PSRMap(map.value, {
orgId: orgId.value == '1100F3DE20806FADE050007F01006CBE' ? '' : orgId.value
})
psrmap.addPSR()
initDeviceCard()
const devTree = new narimap.Components.DeviceTreeGW(map.value)
devTree.init({ orgId: orgId.value })
//添加电网要素点击事件
// device-tree-gw__button
document.querySelectorAll('.device-tree-gw__button')[0].onclick = function (v: any) {
emit('show', true)
}
//添加电网要素点击事件
psrmap.on('click', (features: any) => {
console.log(features)
})
}
// 添加变电站弹框
const initDeviceCard = () => {
deviceCard.value && deviceCard.value.close()
let options = {
map: map.value, // map实例
container: 'nrDeviceCard', // details容器id为用户自定义的容器名
narimap: narimap, //nariMap实例
//用户自定义功能
customButtons: {
popupButtons: {
buttons: []
},
detailsButtons: {
buttons: []
}
}
}
deviceCard.value = new nrgisCommon.EquipmentAccount.DeviceCard(options)
deviceCard.value.on('click', (res: any) => {
if (res.button.id == 'nariPopupViewDetail') {
emit('show', true)
}
setTimeout(() => {
document.querySelectorAll('.nari-tabs__close')[0].onclick = function (v: any) {
emit('show', false)
}
}, 10)
})
//
}
//添加多个监测点
const addMarkers = async () => {
let params = {
deptIndex: dictData.state.area[0].id,
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: datePickerRef.value.timeValue[0],
searchEndTime: datePickerRef.value.timeValue[1],
serverName: 'event-boot',
statisticalType: {}
}
let { data } = await getAreaLineInfo(params)
let r = 0.0035
let tempFeatureZ: any = []
let tempFeatureT: any = []
data.forEach((item: any) => {
if (item.children.length > 10 && item.children.length < 100) {
r = 0.0055
} else if (item.children.length >= 100) {
r = 0.01055
}
item.children.forEach((val: any, i: number) => {
val.lng = item.lng + r * Math.cos((2 * Math.PI * i) / item.children.length)
val.lat = item.lat + r * Math.sin((2 * Math.PI * i) / item.children.length)
val.imageUrl =
val.comFlag == 0
? new URL('@/assets/txzdwzj.png', import.meta.url).href
: new URL('@/assets/txzcwzj.png', import.meta.url).href
// // 监测点图标
let tempFeature = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [val.lng, val.lat]
},
properties: {
name: val.lineName,
list: val
}
}
switch (val.comFlag) {
case 0:
tempFeatureT.push(tempFeature)
break
case 1:
tempFeatureZ.push(tempFeature)
break
}
})
})
map.value.loadImage(
new URL('@/assets/txzcwzj.png', import.meta.url).href, // 图片地址
(error: any, image: any) => {
if (error) throw error
//添加图片到map第一个参数为图片设置id
map.value.addImage('poi1', image)
map.value.addLayer({
id: 'spotImg-ZY',
type: 'symbol',
minzoom: 8,
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: tempFeatureZ
}
},
layout: {
// 为图层设置引用的图片ID
'icon-image': 'poi1',
'icon-size': 0.7,
'icon-ignore-placement': true,
'icon-allow-overlap': true
}
})
map.value.addLayer({
id: 'spotName-ZY',
type: 'symbol',
minzoom: 10,
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: tempFeatureZ
}
},
layout: {
// 为图层设置引用的图片ID
'text-field': '{name}',
'icon-ignore-placement': true,
'text-ignore-placement': false,
'text-size': 12,
'text-max-width': 8,
'text-offset': [0, 2],
'text-font': ['Microsoft YaHei Regular']
},
paint: {
'text-color': '#ccc',
'text-halo-width': 1.33333
}
})
}
)
map.value.loadImage(
new URL('@/assets/txzdwzj.png', import.meta.url).href, // 图片地址
(error: any, image: any) => {
if (error) throw error
//添加图片到map第一个参数为图片设置id
map.value.addImage('poi2', image)
map.value.addLayer({
id: 'spotImg-TY',
type: 'symbol',
minzoom: 8,
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: tempFeatureT
}
},
layout: {
// 为图层设置引用的图片ID
'icon-image': 'poi2',
'icon-size': 0.7,
// 'text-field': '{name}',
'icon-ignore-placement': true,
'icon-allow-overlap': true
// 'text-ignore-placement': false,
// 'text-size': 12,
// 'text-max-width': 8,
// 'text-offset': [0, 2],
// 'text-font': ['Microsoft YaHei Regular']
}
// paint: {
// 'text-color': '#ccc',
// // 'text-halo-color': '#FFFFFF',
// 'text-halo-width': 1.33333
// }
})
map.value.addLayer({
id: 'spotName-TyY',
type: 'symbol',
minzoom: 8,
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: tempFeatureT
}
},
layout: {
// 为图层设置引用的图片ID
// 'icon-image': 'poi2',
// 'icon-size': 0.7,
'text-field': '{name}',
'icon-ignore-placement': true,
'text-ignore-placement': false,
'text-size': 12,
'text-max-width': 8,
'text-offset': [0, 2],
'text-font': ['Microsoft YaHei Regular']
},
paint: {
'text-color': '#ccc',
// 'text-halo-color': '#FFFFFF',
'text-halo-width': 1.33333
}
})
}
)
map.value.on('click', (e: any) => {
const features = map.value.queryRenderedFeatures(e.point, {
layers: ['spotImg-ZY', 'spotImg-TY']
})
if (features.length > 0) {
popup.value && popup.value.remove()
setTimeout(() => {
deviceCard.value.popup && deviceCard.value.popup.remove()
}, 10)
let data = JSON.parse(features[0].properties.list)
let markerHeight = 20
let markerRadius = 10
let linearOffset = 25
let popupOffsets = {
top: [0, 0],
'top-left': [0, 0],
'top-right': [0, 0],
bottom: [0, -markerHeight + 10],
'bottom-left': [linearOffset, (markerHeight - markerRadius + linearOffset) * -1],
'bottom-right': [-linearOffset, (markerHeight - markerRadius + linearOffset) * -1],
left: [markerRadius, (markerHeight - markerRadius) * -1],
right: [-markerRadius, (markerHeight - markerRadius) * -1]
}
popup.value = new narimap.Popup({ offset: popupOffsets, className: 'my-popup' })
.setLngLat([data.lng, data.lat])
.setHTML(
`<div class="popup-box"><div class="popup_content">
<img src="${data.imageUrl}"/>
<div>
<div style="display: flex">
<span class="title">${data.lineName}</span>
<span class="state" style="background-color: ${data.comFlag == 0 ? '#ff0000' : '#3ab34a'};">${
data.comFlag == 0 ? '停运' : '在运'
}</span>
</div>
<div class="info">
<span>监测点</span>
<span>${data.voltageScale}</span>
<span>${data.gdName} </span>
</div>
</div>
</div>
<div class="popup_footer">
<span id="ids" data-sid="${data.lineId}">查看详情</span>
</div>
</div>
`
)
.addTo(map.value)
document.getElementById('ids').onclick = function (v: any) {
// console.log(e.target.dataset.sid)
emit('drop', v.target.dataset.sid)
}
}
})
}
//添加多个监测点
// const addMarkers = async () => {
// let params = {
// deptIndex: dictData.state.area[0].id,
// monitorFlag: 2,
// powerFlag: 2,
// searchBeginTime: datePickerRef.value.timeValue[0],
// searchEndTime: datePickerRef.value.timeValue[1],
// serverName: 'event-boot',
// statisticalType: {}
// }
// let markerGroup = new narimap.MarkerGroup(map.value)
// let { data } = await getAreaLineInfo(params)
// let r = 0.0035
// data.forEach((item: any) => {
// if (item.children.length > 10 && item.children.length < 100) {
// r = 0.0055
// } else if (item.children.length >= 100) {
// r = 0.01055
// }
// item.children.forEach((val: any, i: number) => {
// val.lng = item.lng + r * Math.cos((2 * Math.PI * i) / item.children.length)
// val.lat = item.lat + r * Math.sin((2 * Math.PI * i) / item.children.length)
// // // 监测点图标
// val.icon = {
// imageUrl: '',
// iconSize: [24, 24] // 设置图标大小
// }
// switch (val.comFlag) {
// case 0:
// val.icon.imageUrl = new URL('@/assets/txzdwzj.png', import.meta.url).href
// break
// case 1:
// val.icon.imageUrl = new URL('@/assets/txzcwzj.png', import.meta.url).href
// break
// }
// let marker = new narimap.Marker().setLngLat([val.lng, val.lat]).setImage(val.icon)
// marker.data = val
// markerGroup.addMarker(val.lineId, marker)
// markerGroup.hide()
// })
// })
// setTimeout(() => {
// markerGroup.on('click', (e: any) => {
// popup.value && popup.value.close()
// deviceCard.value.popup && deviceCard.value.popup.remove()
// let data = e.marker.data
// let markerHeight = 20
// let markerRadius = 10
// let linearOffset = 25
// let popupOffsets = {
// top: [0, 0],
// 'top-left': [0, 0],
// 'top-right': [0, 0],
// bottom: [0, -markerHeight],
// 'bottom-left': [linearOffset, (markerHeight - markerRadius + linearOffset) * -1],
// 'bottom-right': [-linearOffset, (markerHeight - markerRadius + linearOffset) * -1],
// left: [markerRadius, (markerHeight - markerRadius) * -1],
// right: [-markerRadius, (markerHeight - markerRadius) * -1]
// }
// popup.value = new narimap.Popup({ offset: popupOffsets, className: 'my-popup' })
// .setLngLat([data.lng, data.lat])
// .setHTML(
// `<div class="popup-box"><div class="popup_content">
// <img src="${data.icon.imageUrl}"/>
// <div>
// <div style="display: flex">
// <span class="title">${data.lineName}</span>
// <span class="state" style="background-color: ${data.comFlag == 0 ? '#ff0000' : '#3ab34a'};">${
// data.comFlag == 0 ? '停运' : '在运'
// }</span>
// </div>
// <div class="info">
// <span>监测点</span>
// <span>${data.voltageScale}</span>
// <span>${data.gdName} </span>
// </div>
// </div>
// </div>
// <div class="popup_footer">
// <span id="ids" data-sid="${data.lineId}">查看详情</span>
// </div>
// </div>
// `
// )
// .addTo(map.value)
// document.getElementById('ids').onclick = function (v: any) {
// // console.log(e.target.dataset.sid)
// emit('drop', v.target.dataset.sid)
// }
// })
// }, 0)
// map.value.on('zoom', (e: any) => {
// // map.value.getZoom()
// if (map.value.getZoom() > 7) {
// markerGroup.show()
// } else {
// markerGroup.hide()
// }
// })
// }
onMounted(() => {
// 监听地图初始化完成事件
})
// const locatePositions = (e: any) => {
// let mapList = [
// {
// code: '1100F3DE20806FADE050007F01006CBE', //冀北
// centralCoordinate: [116.13740482, 39.5478448705],
// zoom: 6
// },
// {
// code: '1100F3DE22316FADE050007F01006CBE', //"唐山"
// centralCoordinate: [118.335849137, 39.7213593355],
// zoom: 7
// },
// {
// code: '1100F3DE20816FADE050007F01006CBE', //张家口
// centralCoordinate: [115.032504679, 40.8651549951],
// zoom: 7
// },
// {
// code: '1100F3DE23F96FADE050007F01006CBE', //秦皇岛
// centralCoordinate: [119.185113833, 40.0879119754],
// zoom: 7
// },
// {
// code: '1100F3DE23466FADE050007F01006CBE', //承德
// centralCoordinate: [117.548498365, 41.3475890632],
// zoom: 7
// },
// {
// code: '1100F3DE218D6FADE050007F01006CBE', //廊坊
// centralCoordinate: [116.628004129, 39.2589378611],
// zoom: 7
// }
// ]
// let data: any = []
// data = mapList.filter(item => item.code == e.data.code) || []
// if (data.length > 0) {
// // orgId.value = e.data.code
// // addCity()
// console.log('🚀 ~ locatePositions ~ data[0].zoom:', data[0].zoom)
// map.value.locatePositions(data[0].centralCoordinate, {
// zoom: data[0].zoom
// })
// }
// }
// defineExpose({ locatePositions })
const height = mainHeight(20)
</script>
<style lang="scss" scoped>
:deep(.query-box-wrap) {
position: absolute;
top: 10px;
left: calc(50% - 385px);
.query-box {
border-radius: 8px 0 0 8px;
}
}
:deep(.device-tree-gw__button) {
position: absolute;
top: 10px;
border-radius: 0 8px 8px 0;
left: calc(50% - 55px);
z-index: 0 !important;
}
:deep(.province-selector) {
position: absolute;
top: 10px;
left: 50%;
.distribution__body {
height: auto;
}
.province-selector__options {
height: auto;
}
.province-op {
width: 48%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.province-selector__button {
width: 100px;
padding: 4px 12px;
span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.province-selector__options {
z-index: 1;
}
}
:deep(.sgmap-canvas) {
width: 100% !important;
}
:deep(.my-popup) {
max-width: 400px !important;
.popup-box {
width: 260px;
height: 70px;
.popup_content {
display: grid;
grid-template-columns: 50px 1fr;
img {
width: 42px;
height: 42px;
}
.title {
font-weight: 550;
}
.state {
width: 45px;
margin-left: 5px;
text-align: center;
border-radius: 3px;
color: #fff;
}
.info {
color: #18181b99;
margin: 5px 0;
span {
&::after {
display: inline-block;
margin: 0 5px;
content: ' ';
width: 2px;
height: 11px;
background: #e5e6eb73;
vertical-align: middle;
}
}
}
}
.popup_footer {
padding: 5px 5px;
border-top: 1px solid #e5e6eb;
color: var(--el-color-primary);
span {
margin-right: 8px;
cursor: pointer;
}
}
}
.sgmap-popup-content {
padding: 15px 10px 10px !important;
}
.sgmap-popup-close-button {
position: absolute;
right: 5px;
top: 5px;
font-size: 16px;
}
}
#nrDeviceCard {
position: absolute;
top: 11px;
right: 70px;
width: 450px;
z-index: 0;
}
</style>

View File

@@ -9,235 +9,94 @@
<ArrowRight style="width: 12px" /> <ArrowRight style="width: 12px" />
</span> </span>
</div> </div>
<!-- <div style="border: 1px solid #ccc; margin-top: 10px">
<div class="infoTop"> <div style="display: flex" class="mt2">
<div class="infoL"> <img src="@/assets/img/FGX.png" />
<img :src="item.img" />
</div>
<div class="infoR">
<div class="top">{{ item.infoT }}</div>
<div class="bottom">
<div v-for="(num, k) in item.num">
<span :style="{ color: item.color[k] }">{{ num.a }}</span>
/
<span :style="{ color: item.color[4] }">{{ num.b }}</span>
</div>
</div>
</div>
</div>
<el-table size="small" :height="tabHeight" :data="item.list">
<el-table-column prop="name" width="60px" label=""></el-table-column>
<el-table-column prop="a" label="500kV" width="63px" align="center"></el-table-column>
<el-table-column prop="b" label="220kV" width="63px" align="center"></el-table-column>
<el-table-column prop="d" label="110KV" width="63px" align="center"></el-table-column>
<el-table-column prop="d" label="35KV" width="63px" align="center"></el-table-column>
<el-table-column prop="d" label="总数" width="63px" align="center"></el-table-column>
</el-table>
</div> -->
<div class="cardBox">
<el-card class="card" style="width: 98%">
<div style="display: flex">
<img :src="item.img" />
<div class="row">
<el-row :gutter="20">
<el-col :span="12">{{ item.titleT[0] }}</el-col>
<el-col :span="12">{{ item.titleT[1] }}</el-col>
</el-row>
<el-row :gutter="20" class="mt4">
<el-col :span="12" style="color: #2dcd28">{{ item.list[4].numOne }}</el-col>
<el-col :span="12" style="color: #bd3124">{{ item.list[4].numTwo }}</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/500kv.png" alt="" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">{{ item.list[0].numOne }}</el-col>
<el-col :span="12" style="color: #bd3124">{{ item.list[0].numTwo }}</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/220kv.png" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">{{ item.list[1].numOne }}</el-col>
<el-col :span="12" style="color: #bd3124">{{ item.list[1].numTwo }}</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/110kv.png" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">{{ item.list[2].numOne }}</el-col>
<el-col :span="12" style="color: #bd3124">{{ item.list[2].numTwo }}</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/35kv.png" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">{{ item.list[3].numOne }}</el-col>
<el-col :span="12" style="color: #bd3124">{{ item.list[3].numTwo }}</el-col>
</el-row>
</div>
</div>
</el-card>
</div>
</div>
<!-- <div :style="boxHeight">
<div class="title">
<span>终端统计</span>
<span class="info" @click="open(1)">
详情
<ArrowRight style="width: 12px" />
</span>
</div> </div>
<div class="cardBox"> <div class="cardBox">
<el-card class="card" style="width: 98%"> <div class="card" style="width: 98%">
<div style="display: flex">
<img src="@/assets/img/ZD.png" />
<div class="row">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12">终端个数</el-col> <el-col :span="12" class="cor">
<el-col :span="12">终端在线率</el-col> <img :src="item.img[0]" />
</el-row> {{ item.titleT[0] }}
<el-row :gutter="20" class="mt4"> <span :style="`color: ${item.color[0]}`">{{ item.list[4].numOne }}</span>
<el-col :span="12" style="color: #2dcd28">480</el-col> </el-col>
<el-col :span="12" style="color: #bd3124">120</el-col> <el-col :span="12" class="cor">
<img :src="item.img[1]" />
{{ item.titleT[1] }}
<span :style="`color: ${item.color[1]}`">{{ item.list[4].numTwo }}</span>
</el-col>
</el-row> </el-row>
</div> </div>
<div :style="`height:calc(${boxHeight.height} - 90px);width: 100%;overflow-y: auto;`" class="BoxA">
<div class="card-Box">
<div>
<span class="line"></span>
<span class="vol">500kV</span>
</div> </div>
</el-card> <div class="num">
<el-card class="card"> <div>
<div style="display: flex; align-items: center"> {{ item.titleT[0] }}:
<img src="@/assets/img/500kv.png" alt="" /> <span :style="`color: ${item.color[0]}`">{{ item.list[0].numOne }}</span>
<div class="row"> </div>
<el-row> <div>
<el-col :span="12" style="color: #2dcd28">120</el-col> {{ item.titleT[1] }}:
<el-col :span="12" style="color: #bd3124">30</el-col> <span :style="`color: ${item.color[1]}`">{{ item.list[0].numTwo }}</span>
</el-row>
</div> </div>
</div> </div>
</el-card> </div>
<el-card class="card"> <div class="card-Box">
<div style="display: flex; align-items: center"> <div>
<img src="@/assets/img/220kv.png" /> <span class="line"></span>
<div class="row"> <span class="vol">220kV</span>
<el-row> </div>
<el-col :span="12" style="color: #2dcd28">120</el-col> <div class="num">
<el-col :span="12" style="color: #bd3124">30</el-col> <div>
</el-row> {{ item.titleT[0] }}:
<span :style="`color: ${item.color[0]}`">{{ item.list[1].numOne }}</span>
</div>
<div>
{{ item.titleT[1] }}:
<span :style="`color: ${item.color[1]}`">{{ item.list[1].numTwo }}</span>
</div> </div>
</div> </div>
</el-card> </div>
<el-card class="card"> <div class="card-Box">
<div style="display: flex; align-items: center"> <div>
<img src="@/assets/img/110kv.png" /> <span class="line"></span>
<div class="row"> <span class="vol">110kV</span>
<el-row> </div>
<el-col :span="12" style="color: #2dcd28">120</el-col> <div class="num">
<el-col :span="12" style="color: #bd3124">30</el-col> <div>
</el-row> {{ item.titleT[0] }}:
<span :style="`color: ${item.color[0]}`">{{ item.list[2].numOne }}</span>
</div>
<div>
{{ item.titleT[1] }}:
<span :style="`color: ${item.color[1]}`">{{ item.list[2].numTwo }}</span>
</div> </div>
</div> </div>
</el-card> </div>
<el-card class="card"> <div class="card-Box">
<div style="display: flex; align-items: center"> <div>
<img src="@/assets/img/35kv.png" /> <span class="line"></span>
<div class="row"> <span class="vol">350kV</span>
<el-row> </div>
<el-col :span="12" style="color: #2dcd28">120</el-col> <div class="num">
<el-col :span="12" style="color: #bd3124">30</el-col> <div>
</el-row> {{ item.titleT[0] }}:
<span :style="`color: ${item.color[0]}`">{{ item.list[3].numOne }}</span>
</div>
<div>
{{ item.titleT[1] }}:
<span :style="`color: ${item.color[1]}`">{{ item.list[3].numTwo }}</span>
</div> </div>
</div> </div>
</el-card>
</div> </div>
</div> </div>
<div :style="boxHeight">
<div class="title">
<span>监测点统计</span>
<span class="info" @click="open(2)">
详情
<ArrowRight style="width: 12px" />
</span>
</div>
<div class="cardBox">
<el-card class="card" style="width: 98%">
<div style="display: flex">
<img src="@/assets/img/JCD.png" />
<div class="row">
<el-row :gutter="20">
<el-col :span="12">总数</el-col>
<el-col :span="12">在线</el-col>
</el-row>
<el-row :gutter="20" class="mt4">
<el-col :span="12" style="color: #2dcd28">480</el-col>
<el-col :span="12" style="color: #bd3124">120</el-col>
</el-row>
</div> </div>
</div> </div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/500kv.png" alt="" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">120</el-col>
<el-col :span="12" style="color: #bd3124">30</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/220kv.png" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">120</el-col>
<el-col :span="12" style="color: #bd3124">30</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/110kv.png" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">120</el-col>
<el-col :span="12" style="color: #bd3124">30</el-col>
</el-row>
</div>
</div>
</el-card>
<el-card class="card">
<div style="display: flex; align-items: center">
<img src="@/assets/img/35kv.png" />
<div class="row">
<el-row>
<el-col :span="12" style="color: #2dcd28">120</el-col>
<el-col :span="12" style="color: #bd3124">30</el-col>
</el-row>
</div>
</div>
</el-card>
</div>
</div> -->
</div> </div>
<img <img
class="imgL" class="imgL"
@@ -273,7 +132,8 @@ const pointRef = ref()
const list: any = ref([ const list: any = ref([
{ {
title: '变电站', title: '变电站',
img: new URL(`@/assets/img/BDZ.png`, import.meta.url), img: [new URL(`@/assets/img/BDZ-ZS.png`, import.meta.url), new URL(`@/assets/img/BDZ-GJ.png`, import.meta.url)],
color: ['#000', '#bd3124'],
titleT: ['总数', '告警'], titleT: ['总数', '告警'],
list: [ list: [
{ {
@@ -299,9 +159,10 @@ const list: any = ref([
] ]
}, },
{ {
title: '终端统计', title: '终端',
img: new URL(`@/assets/img/ZD.png`, import.meta.url), img: [new URL(`@/assets/img/ZD-ZS.png`, import.meta.url), new URL(`@/assets/img/ZD-ZX.png`, import.meta.url)],
titleT: ['终端个数', '终端在线'], titleT: ['数', '在线'],
color: ['#000', '#2dcd28'],
list: [ list: [
{ {
numOne: 0, numOne: 0,
@@ -326,9 +187,10 @@ const list: any = ref([
] ]
}, },
{ {
title: '监测点统计', title: '监测点',
img: new URL(`@/assets/img/JCD.png`, import.meta.url), img: [new URL(`@/assets/img/JCD-ZS.png`, import.meta.url), new URL(`@/assets/img/JCD-ZX.png`, import.meta.url)],
titleT: ['总数', '在线'], titleT: ['总数', '在线'],
color: ['#000', '#2dcd28'],
list: [ list: [
{ {
numOne: 0, numOne: 0,
@@ -356,7 +218,7 @@ const list: any = ref([
const formRow: any = ref({}) const formRow: any = ref({})
const height = mainHeight(30) const height = mainHeight(30)
const boxHeight = mainHeight(40, 3) const boxHeight = mainHeight(40, 3)
const tabHeight: any = mainHeight(320, 3).height
// 详情 // 详情
const open = (e: any) => { const open = (e: any) => {
if (e == 0) { if (e == 0) {
@@ -376,7 +238,7 @@ const info = (row: any) => {
ids: [], ids: [],
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0], statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0],
isUpToGrid: row.isUpToGrid, isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid monitorFlag: row.isUpToGrid == 0 ? null : row.isUpToGrid
} }
formRow.value = form formRow.value = form
// 变电站 // 变电站
@@ -402,7 +264,7 @@ const info = (row: any) => {
}) })
} }
onMounted(() => {}) onMounted(() => {})
defineExpose({ info }) defineExpose({ info, show })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -410,6 +272,7 @@ defineExpose({ info })
background-color: #fff; background-color: #fff;
width: 100%; width: 100%;
padding: 10px 10px 10px 10px; padding: 10px 10px 10px 10px;
border-radius: 5px;
font-size: 13px; font-size: 13px;
overflow: hidden; overflow: hidden;
} }
@@ -421,15 +284,57 @@ defineExpose({ info })
margin-top: 10px; margin-top: 10px;
width: 48%; width: 48%;
margin-right: 2%; margin-right: 2%;
.cor {
display: flex;
align-items: center;
font-size: 12px;
color: #6d6d6d;
span {
font-size: 16px;
font-weight: 550;
}
}
img { img {
width: 40px; width: 40px;
height: 40px; height: 40px;
margin: 0 5%;
} }
.row { }
width: 80%; .BoxA {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 80px;
.card-Box {
display: grid;
grid-template-rows: 1fr 1fr;
align-items: center;
margin: 5px;
padding: 10px;
background-color: #edededc0;
border-radius: 10px;
max-height: 80px;
.line {
display: inline-block;
width: 0.5rem;
height: 0.5rem;
border-radius: 0.25rem;
background: var(--el-color-primary);
margin-right: 5px;
margin-bottom: 2px;
}
.num {
margin-left: 10px;
display: grid;
text-align: center; text-align: center;
font-size: 16px; grid-template-columns: 1fr 1fr;
font-size: 12px;
color: #6d6d6d;
span {
font-size: 14px;
font-weight: 550;
}
}
} }
} }
} }
@@ -438,52 +343,27 @@ defineExpose({ info })
// height: ; // height: ;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: 16px; font-size: 15px;
height: 22px;
line-height: 23px; line-height: 23px;
padding-left: 5px; padding-left: 5px;
width: 100%; width: 100%;
background-image: linear-gradient(to right, #a4e5da, #fff); font-weight: 550;
.info { .info {
font-weight: normal; font-weight: normal;
display: flex; display: flex;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
color: #757575;
} }
} }
.infoTop {
display: flex;
height: 50px;
padding-right: 10px;
.infoL {
width: 60px;
img {
width: 40px;
margin: 10px;
}
}
.infoR {
flex: 1;
.top {
// margin-top: 2px;
height: 22px;
border-bottom: 2px solid #93dee2;
}
.bottom {
margin-top: 3px;
display: flex;
font-size: 12px;
justify-content: space-around;
}
}
}
.imgL { .imgL {
position: absolute; position: absolute;
padding: 10px; padding: 10px;
top: calc(50% - 80px); top: calc(50% - 80px);
right: -23px; right: -23px;
z-index: 1;
transform: rotate(180deg); transform: rotate(180deg);
height: 200px; height: 200px;
cursor: pointer; cursor: pointer;

View File

@@ -2,7 +2,7 @@
<div :class="show ? 'show' : 'noshow'"> <div :class="show ? 'show' : 'noshow'">
<div class="boxLeft" :style="height"> <div class="boxLeft" :style="height">
<!-- 综合评估 --> <!-- 综合评估 -->
<div> <div style="height: 110px">
<div class="title"> <div class="title">
<span>综合评估</span> <span>综合评估</span>
<span class="info" @click="open(0)"> <span class="info" @click="open(0)">
@@ -10,9 +10,35 @@
<ArrowRight style="width: 12px" /> <ArrowRight style="width: 12px" />
</span> </span>
</div> </div>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<div class="mt10 TJTop">
<img src="@/assets/img/TJ.png" />
综合评估得分
<span :style="{
color:
assessList.score == 3.14159
? ''
:assessList.score > 4.5
? '#339966'
:assessList.score > 4
? '#3399ff'
:assessList.score > 3
? '#ffcc33'
:assessList.score > 2
? '#ff9900'
:assessList.score > 0
? '#cc0000'
: ''
}">{{assessList.score}}</span>
</div>
<div class="evaluate"> <div class="evaluate">
<div v-for="item in assessList" style="min-width: 50px"> <div v-for="item in assessList.children" style="min-width: 50px">
<div>{{ item.name }}</div> <div>
<span class="line"></span>
{{ item.name }}
</div>
<div <div
style="margin-top: 5px" style="margin-top: 5px"
:style="{ :style="{
@@ -46,14 +72,19 @@
<ArrowRight style="width: 12px" /> <ArrowRight style="width: 12px" />
</span> </span>
</div> </div>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<div :style="boxHeight" class="boxR"> <div :style="boxHeight" class="boxR">
<div class="top"> <div class="top">
<span> <div class="TJTop">
<img src="@/assets/img/TJ.png" />
监测点越限占比: 监测点越限占比:
<span class="num"> <span class="num">
{{ harmonicLineRatio == 3.14159 ? '暂无数据' : harmonicLineRatio + '%' }} {{ harmonicLineRatio == 3.14159 ? '0' : harmonicLineRatio + '%' }}
</span>
</span> </span>
</div>
<el-select v-model="harmonicType" style="width: 120px" @change="harmonicChange" size="small"> <el-select v-model="harmonicType" style="width: 120px" @change="harmonicChange" size="small">
<el-option <el-option
v-for="item in options" v-for="item in options"
@@ -63,7 +94,13 @@
/> />
</el-select> </el-select>
</div> </div>
<MyEChart :style="EchHeight" :options="harmonicCharts" /> <!-- <MyEChart :style="EchHeight" :options="harmonicList" /> -->
<div :style="EchHeight" class="harmonic mt5">
<div class="progress" v-for="item in harmonicList">
<span class="text">{{ item.deptName }}</span>
<el-progress :percentage="item.ratio" />
</div>
</div>
</div> </div>
</div> </div>
<!-- 暂态电能质量水平评估 --> <!-- 暂态电能质量水平评估 -->
@@ -75,37 +112,55 @@
<ArrowRight style="width: 12px" /> <ArrowRight style="width: 12px" />
</span> </span>
</div> </div>
<div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<div :style="boxHeight" class="boxR"> <div :style="boxHeight" class="boxR">
<div class="top"> <div class="top">
<div class="TJTop">
<img src="@/assets/img/TJ.png" />
<span> <span>
暂态事件严重度: 暂态事件严重度
<span class="num">{{ transientNum }}%</span> <span class="num">{{ transientNum }}%</span>
</span> </span>
</div>
<el-select v-model="value" style="width: 120px" size="small" @change="transientChange"> <el-select v-model="value" style="width: 120px" size="small" @change="transientChange">
<el-option v-for="item in options1" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in options1" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
<MyEChart :style="EchHeight" :options="WTCharts" /> <!-- <MyEChart :style="EchHeight" :options="WTList" /> -->
<div :style="EchHeight" class="harmonic mt5">
<div class="progress" v-for="item in WTList">
<span class="text">{{ item.orgName }}</span>
<el-progress :percentage="item.count" />
</div>
</div>
</div> </div>
</div> </div>
<!-- 技术监督管理 --> <!-- 技术监督管理 -->
<div> <div>
<div class="title"> <div class="title">
<span>技术监督管理(问题数)</span> <span>技术监督管理</span>
<span class="info" @click="open(3)"> <span class="info" @click="open(3)">
详情 详情
<ArrowRight style="width: 12px" /> <ArrowRight style="width: 12px" />
</span> </span>
</div> </div>
<div :style="boxHeight" class="boxR"> <div style="display: flex" class="mt2">
<img src="@/assets/img/FGX.png" />
</div>
<div style="height: 150px" class="boxR">
<div class="evaluate bottom"> <div class="evaluate bottom">
<div v-for="item in JDlist" style="width: 80px"> <div v-for="item in JDlist" style="width: 80px">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<div style="margin-top: 5px">{{ item.value }}</div> <div style="margin-top: 5px; font-weight: 550">{{ item.value }}</div>
</div> </div>
</div> </div>
<el-row style="height: calc(100% - 62px)"> <el-row
<el-col :span="12" class="col" style="border-right: 1px solid #ccc"> style="height: calc(100% - 45px); display: flex; justify-content: space-around"
class="ml10 mr10 mt5"
>
<el-col :span="11" class="col pt10">
<div> <div>
<span>异常问题总数</span> <span>异常问题总数</span>
<span style="color: #2dcd28">60</span> <span style="color: #2dcd28">60</span>
@@ -119,7 +174,7 @@
<span style="color: #338dff">60%</span> <span style="color: #338dff">60%</span>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="col"> <el-col :span="11" class="col pt10" :offset="0.5">
<div> <div>
<span>异常问题总数</span> <span>异常问题总数</span>
<span style="color: #2dcd28">60</span> <span style="color: #2dcd28">60</span>
@@ -168,8 +223,8 @@ import { getAssessOverview, getEvaluationOverview, getEventLevelEvaluation } fro
const dictData = useDictData() const dictData = useDictData()
const show = ref(false) const show = ref(false)
const height = mainHeight(30) const height = mainHeight(30)
const boxHeight: any = mainHeight(270, 3) const boxHeight: any = mainHeight(420, 2)
const EchHeight: any = mainHeight(370, 3) const EchHeight: any = mainHeight(490, 2)
const evaluateRef = ref() const evaluateRef = ref()
const steadyStateRef = ref() const steadyStateRef = ref()
const formRow: any = ref({}) const formRow: any = ref({})
@@ -214,6 +269,10 @@ const JDlist = ref([
name: '技术监督计划', name: '技术监督计划',
value: 5 value: 5
}, },
{
name: '在线监测',
value: 5
},
{ {
name: '用户投诉', name: '用户投诉',
value: 5 value: 5
@@ -221,15 +280,11 @@ const JDlist = ref([
{ {
name: '谐波普测', name: '谐波普测',
value: 5 value: 5
},
{
name: '在线系统',
value: 5
} }
]) ])
const harmonicCharts = ref() const harmonicList: any = ref([])
const harmonicLineRatio: any = ref(0) const harmonicLineRatio: any = ref(0)
const WTCharts = ref({}) const WTList: any = ref([])
const value = ref(options1[0].id) const value = ref(options1[0].id)
const open = (e: number) => { const open = (e: number) => {
@@ -252,7 +307,7 @@ const info = (row: any) => {
ids: [], ids: [],
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0], statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0],
isUpToGrid: row.isUpToGrid, isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid monitorFlag: row.isUpToGrid == 0 ? null : row.isUpToGrid
} }
formRow.value = form formRow.value = form
// 综合评估 // 综合评估
@@ -267,51 +322,55 @@ const info = (row: any) => {
const harmonicChange = () => { const harmonicChange = () => {
getEvaluationOverview({ ...formRow.value, harmonicType: harmonicType.value }).then(res => { getEvaluationOverview({ ...formRow.value, harmonicType: harmonicType.value }).then(res => {
harmonicLineRatio.value = res.data.lineRatio harmonicLineRatio.value = res.data.lineRatio
harmonicList.value = res.data.childrenList.map((item: any) => {
item.ratio = item.ratio == 3.14159 ? 0 : item.ratio
return item
})
harmonicCharts.value = { // harmonicList.value = {
tooltip: { // tooltip: {
formatter: function (params: any) { // formatter: function (params: any) {
return params[0].name + ':' + (params[0].value == 3.14159 ? '暂无数据' : params[0].value) + '%<br/>' // return params[0].name + ':' + (params[0].value == 3.14159 ? '暂无数据' : params[0].value) + '%<br/>'
} // }
}, // },
xAxis: { // xAxis: {
name: '%', // name: '%',
type: 'value', // type: 'value',
max: 100 // max: 100
}, // },
legend: { // legend: {
show: false // show: false
}, // },
yAxis: { // yAxis: {
type: 'category', // type: 'category',
data: res.data.childrenList.map((item: any) => item.deptName) // data: res.data.childrenList.map((item: any) => item.deptName)
}, // },
grid: { // grid: {
top: '10px', // top: '10px',
left: '30px', // left: '30px',
right: '30px', // right: '30px',
bottom: '0px' // bottom: '0px'
}, // },
options: { // options: {
dataZoom: null, // dataZoom: null,
series: [ // series: [
{ // {
name: '占比', // name: '占比',
type: 'bar', // type: 'bar',
data: res.data.childrenList.map((item: any) => item.ratio), // data: res.data.childrenList.map((item: any) => item.ratio),
label: { // label: {
show: true, // show: true,
position: 'right', // position: 'right',
fontSize: 12, // fontSize: 12,
formatter: function (params: any) { // formatter: function (params: any) {
return `${params.value == 3.14159 ? '' : params.value}` // return `${params.value == 3.14159 ? '' : params.value}`
} // }
} // }
} // }
] // ]
} // }
} // }
}) })
} }
const transientChange = () => { const transientChange = () => {
@@ -325,54 +384,54 @@ const transientChange = () => {
transientNum.value = res.data.gwData transientNum.value = res.data.gwData
data = res.data.gwInfo data = res.data.gwInfo
} }
WTList.value = data
// WTList.value = {
// tooltip: {
// formatter: function (params: any) {
// return params[0].name + ':' + (params[0].value == 3.14159 ? '暂无数据' : params[0].value) + '%<br/>'
// }
// },
// xAxis: {
// name: '%',
// type: 'value',
// max: 100
// },
// legend: {
// show: false
// },
// yAxis: {
// type: 'category',
// data: data.map((item: any) => item.orgName)
// },
// grid: {
// top: '10px',
// left: '30px',
// right: '30px',
// bottom: '0px'
// },
WTCharts.value = { // options: {
tooltip: { // dataZoom: null,
formatter: function (params: any) { // series: [
return params[0].name + ':' + (params[0].value == 3.14159 ? '暂无数据' : params[0].value) + '%<br/>' // {
} // name: '占比',
}, // type: 'bar',
xAxis: { // data: data.map((item: any) => item.count),
name: '%', // label: {
type: 'value', // show: true,
max: 100 // position: 'right',
}, // fontSize: 12,
legend: { // formatter: function (params: any) {
show: false // return `${params.value}`
}, // }
yAxis: { // }
type: 'category', // }
data: data.map((item: any) => item.orgName) // ]
}, // }
grid: { // }
top: '10px',
left: '30px',
right: '30px',
bottom: '0px'
},
options: {
dataZoom: null,
series: [
{
name: '占比',
type: 'bar',
data: data.map((item: any) => item.count),
label: {
show: true,
position: 'right',
fontSize: 12,
formatter: function (params: any) {
return `${params.value}`
}
}
}
]
}
}
}) })
} }
defineExpose({ info }) defineExpose({ info, show })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -382,41 +441,55 @@ defineExpose({ info })
padding: 10px 10px 10px 10px; padding: 10px 10px 10px 10px;
font-size: 13px; font-size: 13px;
overflow: hidden; overflow: hidden;
border-radius: 5px;
} }
.title { .title {
// height: ; // height: ;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: 16px; font-size: 15px;
height: 22px;
line-height: 23px; line-height: 23px;
padding-left: 5px; padding-left: 5px;
width: 100%; width: 100%;
background-image: linear-gradient(to right, #a4e5da, #fff); font-weight: 550;
.info { .info {
font-weight: normal; font-weight: normal;
display: flex; display: flex;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
color: #757575;
}
}
.TJTop {
display: flex;
img {
height: 1.2rem;
width: 1.2rem;
margin-right: 5px;
} }
} }
.evaluate { .evaluate {
height: 60px;
border: 1px solid #ccc;
margin: 10px 0; margin: 10px 0;
padding: 10px 0;
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
text-align: center; text-align: center;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
.line {
display: inline-block;
width: 0.5rem;
height: 0.5rem;
border-radius: 0.25rem;
background: var(--el-color-primary);
margin-right: 2px;
margin-bottom: 1px;
}
} }
.boxR { .boxR {
border: 1px solid #ccc; margin: 10px 0 0 0;
margin: 10px 0;
padding: 5px;
.num { .num {
color: #2478f2; color: #2478f2;
} }
@@ -428,6 +501,21 @@ defineExpose({ info })
margin: 0; margin: 0;
border: 0px; border: 0px;
} }
.harmonic {
display: grid;
.progress {
display: flex;
align-items: center;
.text {
width: 50px;
font-size: 12px;
}
.el-progress {
flex: 1;
}
}
}
} }
:deep(.el-select) { :deep(.el-select) {
min-width: 120px; min-width: 120px;
@@ -435,14 +523,16 @@ defineExpose({ info })
.col { .col {
display: grid; display: grid;
grid-template-columns: 1fr; grid-template-columns: 1fr;
border-radius: 10px;
text-align: center; text-align: center;
background-color: #edededc0;
} }
.imgR { .imgR {
position: absolute; position: absolute;
padding: 10px; padding: 10px;
top: calc(50% - 80px); top: calc(50% - 80px);
left: -23px; left: -23px;
z-index: 1;
height: 200px; height: 200px;
cursor: pointer; cursor: pointer;
} }
@@ -460,4 +550,7 @@ defineExpose({ info })
padding: 10px 10px 10px 10px; padding: 10px 10px 10px 10px;
} }
} }
:deep(.el-progress__text) {
font-size: 0.8rem !important ;
}
</style> </style>

View File

@@ -1,64 +1,61 @@
<template> <template>
<div class="default-main" :style="height"> <div class="panorama" :style="height">
<div class="box"> <div class="mapBox" v-show="lineInfo">
<DatePicker ref="datePickerRef" style="display: none" /> <DatePicker ref="datePickerRef" style="display: none" />
<el-form :inline="true" :model="form" class="demo-form-inline"> <el-form :inline="true" :model="form" class="demo-form-inline">
<el-form-item> <el-form-item>
<el-input v-model="form.name" placeholder="请输入设备名称" :suffix-icon="Search"> <!-- <Area
<template #prefix>
<img style="width: 30px" src="@/assets//img/GJDW.png" alt="" />
</template>
</el-input>
</el-form-item>
<el-form-item>
<Area
ref="areaRef" ref="areaRef"
:show-all-levels="false" :show-all-levels="false"
v-model="form.orgNo" v-model="form.orgNo"
style="width: 100px" style="width: 100px"
@changeValue="changeValue" @changeValue="changeValue"
/> /> -->
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-select v-model="form.isUpToGrid" style="width: 100px" @change="info"> <el-select v-model="form.isUpToGrid" style="width: 100px" @change="info">
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <!-- <el-form-item>
<el-button icon="el-icon-Refresh" @click="reset"></el-button> <el-button icon="el-icon-Refresh" @click="reset"></el-button>
</el-form-item> </el-form-item> -->
</el-form> </el-form>
</div> </div>
<!-- 地图 --> <!-- 地图 -->
<!-- <Map /> --> <!-- <Map ref="mapRef" @changeValue="changeValue" :lineInfo="lineInfo" @drop="drop" @show="infoShow" /> -->
<div v-show="lineInfo">
<!-- 省级 --> <!-- 省级 -->
<div v-show="control == 1"> <div v-show="control == 3">
<mapL ref="mapLRef" class="mapL" /> <mapL ref="mapLRef" class="mapL" />
<mapR ref="mapRRef" class="mapR" /> <mapR ref="mapRRef" class="mapR" />
</div> </div>
<!-- 市级 --> <!-- 市级 -->
<div v-show="control == 2"> <!-- <div v-show="control == 4"> -->
<div v-show="control > 3">
<cityMapL ref="cityMapLRef" class="mapL" /> <cityMapL ref="cityMapLRef" class="mapL" />
<cityMapB ref="cityMapBRef" class="mapB" />
<cityMapR ref="cityMapRRef" class="mapR" /> <cityMapR ref="cityMapRRef" class="mapR" />
</div> </div>
</div> </div>
<Info v-if="!lineInfo" ref="InfoRef" @back="lineInfo = true" />
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, ref, provide } from 'vue' import { onMounted, nextTick, ref, provide } from 'vue'
import Area from '@/components/form/area/index.vue' import Area from '@/components/form/area/index.vue'
// import Map from './components/map.vue' // import Map from './components/map1.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { Search, Refresh } from '@element-plus/icons-vue' import { Search, Refresh } from '@element-plus/icons-vue'
import mapL from './components/mapL.vue' import mapL from './components/mapL.vue'
import mapR from './components/mapR.vue'
import cityMapL from './components/cityMapL.vue' import cityMapL from './components/cityMapL.vue'
import cityMapR from './components/cityMapR.vue' import cityMapR from './components/cityMapR.vue'
import cityMapB from './components/cityMapB.vue'
import mapR from './components/mapR.vue' import Info from './components/line/info.vue'
import DatePicker from '@/components/form/datePicker/index.vue' import DatePicker from '@/components/form/datePicker/index.vue'
const dictData = useDictData() const dictData = useDictData()
defineOptions({ defineOptions({
@@ -66,10 +63,14 @@ defineOptions({
}) })
const datePickerRef = ref() const datePickerRef = ref()
const areaRef = ref() const areaRef = ref()
const lineInfo = ref(true)
const mapRef = ref()
const mapLRef = ref() const mapLRef = ref()
const InfoRef = ref()
const mapRRef = ref() const mapRRef = ref()
const cityMapLRef = ref() const cityMapLRef = ref()
const cityMapRRef = ref() const cityMapRRef = ref()
const list: any = [dictData.state.area[0], ...dictData.state.area[0].children]
const options: any = ref([ const options: any = ref([
{ {
name: dictData.state.area[0].name, name: dictData.state.area[0].name,
@@ -87,17 +88,31 @@ const form: any = ref({
isUpToGrid: 0 isUpToGrid: 0
}) })
const height = mainHeight(10) const height = mainHeight(10)
// 获取区域名称 // 获取区域名称
const changeValue = (e: any) => { const changeValue = (e: any) => {
options.value[0].name = e.label form.value.orgNo = list.filter((item: any) => item.code == e.orgId)[0]?.id || dictData.state.area[0].id
if (e.level == 1) { options.value[0].name = e.name
control.value = 1
} else { control.value = e.type
control.value = 2
}
info() info()
} }
//点击监测点详情
const drop = (id: string) => {
lineInfo.value = false
nextTick(() => {
InfoRef.value.open(id)
})
}
// 关闭左右数据展示
const infoShow = (e:boolean) => {
mapLRef.value.show = e
mapRRef.value.show = e
cityMapLRef.value.show = e
cityMapRRef.value.show = e
}
const reset = () => { const reset = () => {
form.value = { form.value = {
@@ -105,7 +120,7 @@ const reset = () => {
orgNo: dictData.state.area[0].id, orgNo: dictData.state.area[0].id,
isUpToGrid: 0 isUpToGrid: 0
} }
control.value = 1
info() info()
} }
const info = () => { const info = () => {
@@ -118,7 +133,7 @@ const info = () => {
// form.value.endTime = `2024-07-30` // form.value.endTime = `2024-07-30`
// form.value.searchEndTime = `2024-07-30` // form.value.searchEndTime = `2024-07-30`
form.value.type = datePickerRef.value.interval form.value.type = datePickerRef.value.interval
if (control.value == 1) { if (control.value == 3) {
mapLRef.value.info(form.value) mapLRef.value.info(form.value)
mapRRef.value.info(form.value) mapRRef.value.info(form.value)
} else { } else {
@@ -128,17 +143,24 @@ const info = () => {
} }
onMounted(() => { onMounted(() => {
info() info()
// aaa()
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.box) { :deep(.mapBox) {
position: absolute; position: absolute;
top: 10px; top: 10px;
left: 30%; left: calc(50% + 95px);
z-index: 1; z-index: 1;
.el-select { .el-select {
min-width: 100px; min-width: 100px;
.el-select__wrapper {
height: 46px;
border-radius: 8px;
}
} }
.el-form-item { .el-form-item {
margin-right: 15px; margin-right: 15px;
@@ -156,13 +178,10 @@ onMounted(() => {
// z-index: 1; // z-index: 1;
right: 10px; right: 10px;
} }
.mapB {
position: absolute; .panorama {
bottom: 0px;
left: 25%;
}
.default-main {
margin: 10px 0 0 0; margin: 10px 0 0 0;
position: relative;
} }
.el-button:focus { .el-button:focus {
color: var(--color); color: var(--color);

View File

@@ -53,7 +53,7 @@
<vxe-column field="sustationName" title="变电站"></vxe-column> <vxe-column field="sustationName" title="变电站"></vxe-column>
<vxe-column field="barName" title="母线"></vxe-column> <vxe-column field="barName" title="母线"></vxe-column>
<vxe-column field="measurementPointName" title="监测点名称"></vxe-column> <vxe-column field="measurementPointName" title="监测点名称"></vxe-column>
<vxe-column field="measurementPointId" title="监测点编号"></vxe-column> <vxe-column field=" " title="监测点编号"></vxe-column>
<vxe-column field="loadType" title="监测对象类型"></vxe-column> <vxe-column field="loadType" title="监测对象类型"></vxe-column>
<vxe-column field="objName" title="监测对象"></vxe-column> <vxe-column field="objName" title="监测对象"></vxe-column>
<vxe-column field="voltageLevel" title="电压等级"></vxe-column> <vxe-column field="voltageLevel" title="电压等级"></vxe-column>

View File

@@ -20,6 +20,7 @@
<Detail ref="detailRef" :detail="detail" @close="detail = null" v-if="detail"></Detail> <Detail ref="detailRef" :detail="detail" @close="detail = null" v-if="detail"></Detail>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue' import { ref, onMounted, provide } from 'vue'
@@ -39,6 +40,7 @@ const detail = ref<anyObj | null>(null)
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/system-boot/dictType/list', url: '/system-boot/dictType/list',
method: 'POST', method: 'POST',
column: [ column: [
{ title: '序号', type: 'seq', width: '60' }, { title: '序号', type: 'seq', width: '60' },
{ title: '名称', field: 'name' }, { title: '名称', field: 'name' },
@@ -54,9 +56,9 @@ const tableStore = new TableStore({
width: '80', width: '80',
render: 'tag', render: 'tag',
custom: { custom: {
'正常': 'success', 正常: 'success',
'删除': 'danger' 删除: 'danger'
}, }
}, },
{ {
title: '操作', title: '操作',

View File

@@ -43,6 +43,7 @@ const apiList = ref([])
const tableStore = new TableStore({ const tableStore = new TableStore({
showPage: false, showPage: false,
url: '/user-boot/function/getButtonById', url: '/user-boot/function/getButtonById',
publicHeight: 60,
column: [ column: [
{ title: '普通接口/接口名称', field: 'name' }, { title: '普通接口/接口名称', field: 'name' },
{ title: '接口类型', field: 'type' }, { title: '接口类型', field: 'type' },

View File

@@ -45,6 +45,7 @@ const popupRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
showPage: false, showPage: false,
url: '/user-boot/function/functionTree', url: '/user-boot/function/functionTree',
publicHeight: 60,
column: [ column: [
{ title: '菜单名称', field: 'title', align: 'left', treeNode: true }, { title: '菜单名称', field: 'title', align: 'left', treeNode: true },
{ {

View File

@@ -21,7 +21,8 @@
autocomplete="off" autocomplete="off"
> >
<template #prefix> <template #prefix>
<span class="iconfont icon-yonghu" style="color: var(--el-color-primary)"></span> <!-- <span class="iconfont icon-yonghu" style="color: var(--el-color-primary)"></span> -->
<Icon name="fa fa-user" style="color: var(--el-color-primary); font-size: 16px" />
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -34,7 +35,8 @@
autocomplete="off" autocomplete="off"
> >
<template #prefix> <template #prefix>
<span class="iconfont icon-mima" style="color: var(--el-color-primary)"></span> <Icon name="local-password" style="color: var(--el-color-primary); font-size: 16px" />
<!-- <span class="iconfont icon-mima" style="color: var(--el-color-primary)"></span> -->
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>

774
yarn.lock

File diff suppressed because it is too large Load Diff