pms换pqs
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="前置等级">
|
||||
<el-select v-model="tableStore.table.params.nodeGrade" clearable placeholder="请选择前置等级">
|
||||
<el-option v-for="item in fontdveoption" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="tableStore.table.params.searchState" clearable placeholder="请选择状态">
|
||||
<el-option v-for="item in statusoption" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" class="ml10" @click="add" icon="el-icon-Plus">新增</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef"></Table>
|
||||
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model="dialogFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
class="cn-operate-dialog"
|
||||
:before-close="resetForm"
|
||||
>
|
||||
<el-form :model="formData" label-width="120px" :rules="rules" ref="ruleFormRef">
|
||||
<el-form-item label="名称:" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="IP:" prop="ip" class="top">
|
||||
<el-input v-model="formData.ip" placeholder="请输入Ip"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="等级:" prop="nodeGrade" class="top">
|
||||
<el-select v-model="formData.nodeGrade" placeholder="请选择等级" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in fontdveoption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="最大装置数:" prop="nodeDevNum" class="top">
|
||||
<el-input
|
||||
v-model="formData.nodeDevNum"
|
||||
onkeyup="value = value.replace(/[^0-9]/g,'')"
|
||||
maxlength="5"
|
||||
placeholder="请输入最大装置数"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序:" prop="sort" class="top">
|
||||
<el-input v-model="formData.sort" placeholder="请输入排序"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述:" prop="remark" class="top">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
type="textarea"
|
||||
placeholder="请输入描述"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="resetForm">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, reactive, nextTick } from 'vue'
|
||||
import { addNode, delNode, updateNode } from '@/api/Business'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
defineOptions({
|
||||
name: 'BusinessAdministrator/TerminalManagement/FrontManagement'
|
||||
})
|
||||
|
||||
const fontdveoption: any = ref([
|
||||
{ id: 0, name: '极重要' },
|
||||
{ id: 1, name: '普通' },
|
||||
{ id: 2, name: '备用' }
|
||||
])
|
||||
const statusoption: any = ref([
|
||||
{ id: 0, name: '未启用' },
|
||||
{ id: 1, name: '启用' }
|
||||
])
|
||||
|
||||
const ruleFormRef = ref()
|
||||
|
||||
const formData: any = ref({
|
||||
name: '',
|
||||
ip: '',
|
||||
nodeGrade: '',
|
||||
nodeDevNum: '',
|
||||
sort: '',
|
||||
remark: ''
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '名称不可为空', trigger: 'blur' }],
|
||||
ip: [{ required: true, message: 'ip不可为空', trigger: 'blur' }],
|
||||
nodeGrade: [{ required: true, message: '等级不可为空', trigger: 'blur' }],
|
||||
nodeDevNum: [{ required: true, message: '最大装置数不可为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '排序不可为空', trigger: 'blur' }],
|
||||
remark: [{ required: true, message: '描述不可为空', trigger: 'blur' }]
|
||||
})
|
||||
const dialogFormVisible = ref(false)
|
||||
const dialogTitle = ref('新增前置机')
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/device-boot/node/nodeList',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '名称', field: 'name' },
|
||||
{ title: 'IP', field: 'ip' },
|
||||
{
|
||||
title: '等级',
|
||||
field: 'nodeGrade',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
0: 'success',
|
||||
1: 'warning',
|
||||
2: 'info'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '极重要',
|
||||
1: '普通',
|
||||
2: '备用'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '最大监测点数量',
|
||||
field: 'nodeDevNum'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
field: 'sort'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
field: 'state',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
0: 'warning',
|
||||
1: 'success'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '未启用',
|
||||
1: '启用'
|
||||
}
|
||||
},
|
||||
{ title: '描述', field: 'remark' },
|
||||
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: '180',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
title: '编辑',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-EditPen',
|
||||
render: 'basicButton',
|
||||
|
||||
click: async row => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '前置机修改'
|
||||
formData.value = JSON.parse(JSON.stringify(row))
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'del',
|
||||
title: '删除',
|
||||
type: 'danger',
|
||||
icon: 'el-icon-Delete',
|
||||
render: 'confirmButton',
|
||||
popconfirm: {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonType: 'danger',
|
||||
title: '确定删除吗?'
|
||||
},
|
||||
click: row => {
|
||||
delNode(row.id).then(res => {
|
||||
ElMessage.success('删除成功')
|
||||
tableStore.index()
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
for (let key in tableStore.table.params) {
|
||||
if (tableStore.table.params[key] === '') {
|
||||
delete tableStore.table.params[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
tableStore.table.params.orderBy = 'desc'
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '新增前置机'
|
||||
}
|
||||
|
||||
// 确认
|
||||
const onSubmit = () => {
|
||||
ruleFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
if (dialogTitle.value == '新增前置机') {
|
||||
addNode(formData.value).then(res => {
|
||||
ElMessage.success('新增前置机')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
} else {
|
||||
updateNode(formData.value).then(res => {
|
||||
ElMessage.success('修改成功')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 清空表格
|
||||
const resetForm = () => {
|
||||
dialogFormVisible.value = false
|
||||
formData.value = {
|
||||
name: '',
|
||||
ip: '',
|
||||
nodeGrade: '',
|
||||
nodeDevNum: '',
|
||||
sort: '',
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.qrcode-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
flex-direction: column;
|
||||
|
||||
.qrcode-label-title {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qrcode-label-img {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,376 @@
|
||||
<template>
|
||||
<div class="default-main" style="position: relative">
|
||||
<TableHeader>
|
||||
<template #select>
|
||||
<el-form-item label="终端型号">
|
||||
<el-select v-model="tableStore.table.params.teriminal" clearable placeholder="请选择终端型号">
|
||||
<el-option
|
||||
v-for="item in teriminaloption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端状态">
|
||||
<el-select v-model="tableStore.table.params.teriminalstatus" clearable placeholder="请选择终端状态">
|
||||
<el-option
|
||||
v-for="item in teriminalstatusoption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯状态">
|
||||
<el-select v-model="tableStore.table.params.state" clearable placeholder="请选择通讯状态">
|
||||
<el-option
|
||||
v-for="item in stateoption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="程序版本">
|
||||
<el-select v-model="tableStore.table.params.program" clearable placeholder="请选择程序版本">
|
||||
<el-option
|
||||
v-for="item in programoption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选">
|
||||
<el-input v-model="filterName" @keyup="searchEvent" placeholder="输入关键字筛选" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Download" type="primary" @click="add">导出</el-button>
|
||||
<el-button icon="el-icon-Check" type="primary" @click="add">批量升级</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<div :style="`height: calc(${tableStore.table.height} + 58px)`">
|
||||
<vxe-table
|
||||
v-loading="tableStore.table.loading"
|
||||
height="auto"
|
||||
auto-resize
|
||||
ref="tableRef"
|
||||
v-bind="defaultAttribute"
|
||||
:data="treeData"
|
||||
show-overflow
|
||||
:tree-config="{ transform: true, parentField: 'pid' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
>
|
||||
<vxe-column field="name" align="left" title="电网拓扑" min-width="200" tree-node></vxe-column>
|
||||
<vxe-column field="devType" title="终端型号" :formatter="formFilter"></vxe-column>
|
||||
<vxe-column field="versionName" title="版本号"></vxe-column>
|
||||
<vxe-column field="protocol" title="协议版本"></vxe-column>
|
||||
<vxe-column field="versionDate" title="版本日期"></vxe-column>
|
||||
<vxe-column field="runFlag" title="终端状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.runFlag === 0"
|
||||
style="color: #fff; background: #0099cc"
|
||||
size="small"
|
||||
>
|
||||
投运
|
||||
</el-tag>
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.runFlag === 1"
|
||||
style="color: #fff; background: #996600"
|
||||
size="small"
|
||||
>
|
||||
热备用
|
||||
</el-tag>
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.runFlag === 2"
|
||||
style="color: #fff; background: #cc0000"
|
||||
size="small"
|
||||
>
|
||||
停运
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="comFlag" title="通讯状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.comFlag === 0"
|
||||
style="color: #fff; background: #cc0000"
|
||||
size="small"
|
||||
>
|
||||
中断
|
||||
</el-tag>
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.comFlag === 1"
|
||||
style="color: #fff; background: #2e8b57"
|
||||
size="small"
|
||||
>
|
||||
正常
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="updateBy" title="升级人员">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.updateBy == null || row.updateBy == '/'">--</span>
|
||||
<span v-else>{{ row.updateBy }}</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="updateTime" title="最新升级时间"></vxe-column>
|
||||
<vxe-column title="操作" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.level == 4" type="primary" size="small" link @click="updateprogram(row)">
|
||||
升级
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.level == 4"
|
||||
:disabled="row.state == 1 ? true : false"
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="queryview(row)"
|
||||
>
|
||||
日志查看
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
:title="protitle + '#终端升级日志查看'"
|
||||
width="70%"
|
||||
>
|
||||
<div :style="{ height: dialogHeight.height }">
|
||||
<vxe-table height="auto" auto-resize :data="logtableData" v-bind="defaultAttribute">
|
||||
<vxe-column field="devTypeName" align="center" title="装置序号"></vxe-column>
|
||||
<vxe-column field="versionId" align="center" title="版本序号"></vxe-column>
|
||||
<vxe-column field="flag" align="center" title="版本状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" v-if="row.flag == true" style="color: #fff; background: #fc0">
|
||||
前期版本
|
||||
</el-tag>
|
||||
<el-tag type="primary" v-if="row.flag == false" style="color: #fff; background: #0c0">
|
||||
当前版本
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="result" align="center" title="升级结果" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" v-if="row.result == false" style="color: #fff; background: #f30">
|
||||
升级失败
|
||||
</el-tag>
|
||||
<el-tag type="primary" v-if="row.result == true" style="color: #fff; background: #093">
|
||||
升级成功
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="state" align="center" title="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" v-if="row.state == false" style="color: #fff; background: #f30">
|
||||
删除
|
||||
</el-tag>
|
||||
<el-tag type="primary" v-if="row.state == true" style="color: #fff; background: #093">
|
||||
正常
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="createBy" align="center" title="创建用户"></vxe-column>
|
||||
<vxe-column field="createTime" align="center" title="创建时间"></vxe-column>
|
||||
<vxe-column field="updateTime" align="center" title="升级时间"></vxe-column>
|
||||
<vxe-column field="updateBy" align="center" title="升级人员"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 升级 -->
|
||||
<el-dialog
|
||||
v-model="prodialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
:title="protitle + '#终端程序升级'"
|
||||
width="40%"
|
||||
>
|
||||
<el-col v-for="(item, index) in percentageoption" :key="index">
|
||||
<span style="font-size: 14px; font-weight: bold">{{ item.name }}</span>
|
||||
:
|
||||
<el-progress
|
||||
:text-inside="true"
|
||||
:stroke-width="24"
|
||||
:percentage="item.percentage"
|
||||
:status="item.status"
|
||||
:format="format"
|
||||
></el-progress>
|
||||
</el-col>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { getTerminalUpLog } from '@/api/Business'
|
||||
import XEUtils from 'xe-utils'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
defineOptions({
|
||||
name: 'BusinessAdministrator/TerminalManagement/ProgramManagement'
|
||||
})
|
||||
|
||||
const pageHeight = mainHeight(83)
|
||||
const dialogHeight = mainHeight(300)
|
||||
const dictData = useDictData()
|
||||
const teriminaloption: any = dictData.getBasicData('Dev_Type')
|
||||
const teriminalstatusoption = ref([
|
||||
{ name: '全部', id: '' },
|
||||
{ name: '投运', id: 0 },
|
||||
{ name: '热备用', id: 1 },
|
||||
{ name: '停运', id: 2 }
|
||||
])
|
||||
const stateoption = ref([
|
||||
{ name: '全部', id: '' },
|
||||
{ name: '正常', id: 1 },
|
||||
{ name: '中断', id: 0 }
|
||||
])
|
||||
const prodialogVisible = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
const protitle = ref('')
|
||||
const filterName = ref('')
|
||||
const treeData: any = ref([])
|
||||
const treeDataCopy: any = ref([])
|
||||
//进度条对象
|
||||
const percentageoption = ref([
|
||||
{
|
||||
name: '1号测试终端',
|
||||
status: 'exception',
|
||||
percentage: 20
|
||||
},
|
||||
{
|
||||
name: '2号测试终端',
|
||||
status: 'warning',
|
||||
percentage: 50
|
||||
},
|
||||
{
|
||||
name: '3号测试终端',
|
||||
status: 'success',
|
||||
percentage: 90
|
||||
}
|
||||
])
|
||||
const programoption: any = ref([])
|
||||
const logtableData: any = ref([])
|
||||
const tableRef = ref()
|
||||
const status = ref('')
|
||||
const tableStore = new TableStore({
|
||||
url: '/device-boot/version/getTerminalVersionList',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
if (item.children.length > 0) {
|
||||
item.id = item.children[0].pid
|
||||
}
|
||||
})
|
||||
treeData.value = tree2List(tableStore.table.data)
|
||||
treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value))
|
||||
setTimeout(() => {
|
||||
tableRef.value.setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
const tree2List = (list: any) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.searchValue = ''
|
||||
tableStore.table.params.searchState = 0
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const add = () => {}
|
||||
const updateprogram = (row: any) => {
|
||||
protitle.value = row.name
|
||||
prodialogVisible.value = true
|
||||
}
|
||||
const queryview = (row: any) => {
|
||||
dialogVisible.value = true
|
||||
protitle.value = row.name
|
||||
let data = {
|
||||
id: row.id
|
||||
}
|
||||
getTerminalUpLog(data).then((res: any) => {
|
||||
logtableData.value = res.data
|
||||
})
|
||||
}
|
||||
const format = (percentage: any) => {
|
||||
if (percentage <= 100 && percentage >= 90) {
|
||||
status.value = 'success'
|
||||
return percentage === 100 ? '升级成功' : `${percentage}%`
|
||||
} else if (percentage > 0 && percentage < 50) {
|
||||
status.value = 'exception'
|
||||
return percentage <= 20 ? '升级失败' + percentage + '%' : `${percentage}%`
|
||||
} else if (percentage > 0 && percentage <= 50) {
|
||||
status.value = 'warning'
|
||||
return percentage <= 50 ? '升级中断' : `${percentage}%`
|
||||
}
|
||||
}
|
||||
const formFilter = (row: any) => {
|
||||
let title = '/'
|
||||
if (row.cellValue != null) {
|
||||
teriminaloption.forEach((item: any) => {
|
||||
if (item.id == row.cellValue) {
|
||||
title = item.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
// 表格过滤
|
||||
const searchEvent = debounce(e => {
|
||||
const filterVal = XEUtils.toValueString(filterName.value).trim().toLowerCase()
|
||||
if (filterVal) {
|
||||
const options = { children: 'children' }
|
||||
const searchProps = ['name']
|
||||
const rest = XEUtils.searchTree(
|
||||
treeDataCopy,
|
||||
(item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1),
|
||||
options
|
||||
)
|
||||
|
||||
treeData.value = rest
|
||||
|
||||
// 搜索之后默认展开所有子节点
|
||||
} else {
|
||||
treeData.value = treeDataCopy
|
||||
}
|
||||
nextTick(() => {
|
||||
const $table = tableRef.value
|
||||
if ($table) {
|
||||
$table.setAllTreeExpand(true)
|
||||
}
|
||||
})
|
||||
}, 300)
|
||||
</script>
|
||||
@@ -0,0 +1,408 @@
|
||||
<template>
|
||||
<div class="default-main" style="position: relative">
|
||||
<TableHeader>
|
||||
<template #select>
|
||||
<el-form-item label="终端型号">
|
||||
<el-select v-model="tableStore.table.params.devType" clearable placeholder="请选择终端型号">
|
||||
<el-option
|
||||
v-for="item in teriminaloption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端状态">
|
||||
<el-select v-model="tableStore.table.params.runFlag" clearable placeholder="请选择终端状态">
|
||||
<el-option
|
||||
v-for="item in teriminalstatusoption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯状态">
|
||||
<el-select v-model="tableStore.table.params.comFlag" clearable placeholder="请选择通讯状态">
|
||||
<el-option
|
||||
v-for="item in stateoption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="筛选">
|
||||
<el-input v-model="filterName" @keyup="searchEvent" placeholder="输入关键字筛选" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<!-- <el-button icon="el-icon-Download" type="primary" @click="add">导出</el-button>
|
||||
<el-button icon="el-icon-Check" type="primary" @click="add">批量升级</el-button> -->
|
||||
<el-button type="primary" icon="el-icon-Success" @click="deviceData">终端状态管理</el-button>
|
||||
<el-button type="primary" icon="el-icon-s-order" @click="liuniangconfig">流量套餐配置</el-button>
|
||||
<el-button type="primary" icon="el-icon-Menu" @click="configliul">流量策略配置</el-button>
|
||||
<el-button type="primary" icon="el-icon-s-data" @click="liultjData">流量统计</el-button>
|
||||
<el-button type="primary" icon="el-icon-Setting" @click="resect">重启前置程序</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<div :style="`height: calc(${tableStore.table.height} + 58px)`">
|
||||
<vxe-table
|
||||
v-loading="tableStore.table.loading"
|
||||
height="auto"
|
||||
auto-resize
|
||||
ref="tableRef"
|
||||
v-bind="defaultAttribute"
|
||||
:data="treeData"
|
||||
show-overflow
|
||||
:tree-config="{ transform: true, parentField: 'pid' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
:checkbox-config="{ labelField: 'name' }"
|
||||
>
|
||||
<vxe-column
|
||||
field="name"
|
||||
align="left"
|
||||
type="checkbox"
|
||||
title="电网拓扑"
|
||||
min-width="200"
|
||||
tree-node
|
||||
></vxe-column>
|
||||
<vxe-column field="devType" title="终端型号"></vxe-column>
|
||||
<vxe-column field="version" title="版本信息"></vxe-column>
|
||||
<vxe-column field="baseFlowMeal" title="基础套餐(MB)"></vxe-column>
|
||||
<vxe-column field="reamFlowMeal" title="扩展套餐(MB)"></vxe-column>
|
||||
<vxe-column title="剩余流量(MB)">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.level === 4" type="primary">
|
||||
{{
|
||||
row.level === 4
|
||||
? (row.baseFlowMeal + row.reamFlowMeal - row.statisValue).toFixed(2)
|
||||
: ''
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="流量使用占比(%)">
|
||||
<template #default="{ row }">
|
||||
{{
|
||||
row.level === 4
|
||||
? ((row.statisValue / (row.baseFlowMeal + row.reamFlowMeal)) * 100).toFixed(2)
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="runFlag" title="终端状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.runFlag === 0"
|
||||
style="color: #fff; background: #0099cc"
|
||||
size="small"
|
||||
>
|
||||
投运
|
||||
</el-tag>
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.runFlag === 1"
|
||||
style="color: #fff; background: #996600"
|
||||
size="small"
|
||||
>
|
||||
热备用
|
||||
</el-tag>
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.runFlag === 2"
|
||||
style="color: #fff; background: #cc0000"
|
||||
size="small"
|
||||
>
|
||||
停运
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="comFlag" title="通讯状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.comFlag === 0"
|
||||
style="color: #fff; background: #cc0000"
|
||||
size="small"
|
||||
>
|
||||
中断
|
||||
</el-tag>
|
||||
<el-tag
|
||||
type="primary"
|
||||
v-if="row.comFlag === 1"
|
||||
style="color: #fff; background: #2e8b57"
|
||||
size="small"
|
||||
>
|
||||
正常
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
|
||||
<vxe-column title="操作" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="row.level === 4"
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="uesdealia(row)"
|
||||
icon="el-icon-view"
|
||||
>
|
||||
终端详情
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.level === 4"
|
||||
:disabled="row.state == 1 ? true : false"
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
icon="el-icon-view"
|
||||
@click="queryview(row)"
|
||||
>
|
||||
流量详情
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
<!-- 终端使用详情 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisiblexq"
|
||||
v-if="dialogVisiblexq"
|
||||
title="终端使用详情"
|
||||
width="70%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<MyEchart :options="echartsXq" style="width: 100%; height: 300px" />
|
||||
<vxe-table v-bind="defaultAttribute" height="400" :data="logtableData">
|
||||
<vxe-colgroup title="cup使用率">
|
||||
<vxe-column field="date" title="使用率"></vxe-column>
|
||||
<vxe-column field="date" title="总量"></vxe-column>
|
||||
<vxe-column field="date" title="使用量"></vxe-column>
|
||||
<vxe-column field="date" title="未使用量"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="内存使用率">
|
||||
<vxe-column field="date" title="使用率"></vxe-column>
|
||||
<vxe-column field="date" title="总量"></vxe-column>
|
||||
<vxe-column field="date" title="使用量"></vxe-column>
|
||||
<vxe-column field="date" title="未使用量"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="磁盘使用率">
|
||||
<vxe-column field="date" title="使用率"></vxe-column>
|
||||
<vxe-column field="date" title="总量"></vxe-column>
|
||||
<vxe-column field="date" title="使用量"></vxe-column>
|
||||
<vxe-column field="date" title="未使用量"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
</vxe-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { getTerminalUpLog } from '@/api/Business'
|
||||
import XEUtils from 'xe-utils'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
defineOptions({
|
||||
name: 'BusinessAdministrator/TerminalManagement/TerminalManagement'
|
||||
})
|
||||
|
||||
const pageHeight = mainHeight(83)
|
||||
|
||||
const dictData = useDictData()
|
||||
const teriminaloption: any = dictData.getBasicData('Dev_Type')
|
||||
const teriminalstatusoption = ref([
|
||||
{ name: '全部', id: '' },
|
||||
{ name: '投运', id: 0 },
|
||||
{ name: '热备用', id: 1 },
|
||||
{ name: '停运', id: 2 }
|
||||
])
|
||||
const stateoption = ref([
|
||||
{ name: '全部', id: '' },
|
||||
{ name: '正常', id: 1 },
|
||||
{ name: '中断', id: 0 }
|
||||
])
|
||||
const dialogVisiblexq = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
const prodialogVisible = ref(false)
|
||||
const liudialogVisible = ref(false)
|
||||
const condialogVisible = ref(false)
|
||||
const tjdialogVisible = ref(false)
|
||||
|
||||
const protitle = ref('')
|
||||
const filterName = ref('')
|
||||
const treeData: any = ref([])
|
||||
const treeDataCopy: any = ref([])
|
||||
const echartsXq: any = ref([])
|
||||
|
||||
const logtableData: any = ref([])
|
||||
const tableRef = ref()
|
||||
const status = ref('')
|
||||
const tableStore = new TableStore({
|
||||
url: '/device-boot/maintain/getTerminalMainList',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
if (item.children.length > 0) {
|
||||
item.id = item.children[0].pid
|
||||
}
|
||||
})
|
||||
treeData.value = tree2List(tableStore.table.data)
|
||||
treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value))
|
||||
setTimeout(() => {
|
||||
tableRef.value.setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
// 处理大数据卡顿
|
||||
const tree2List = (list: any) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.searchValue = ''
|
||||
tableStore.table.params.searchState = 0
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
|
||||
// 终端状态管理
|
||||
const deviceData = () => {}
|
||||
// 流量套餐配置
|
||||
const liuniangconfig = () => {}
|
||||
// 流量策略配置
|
||||
const configliul = () => {}
|
||||
// 流量统计
|
||||
const liultjData = () => {}
|
||||
// 重启前置程序
|
||||
const resect = () => {}
|
||||
|
||||
// 终端详情
|
||||
const uesdealia = (row: any) => {
|
||||
echartsXq.value = {
|
||||
title: {
|
||||
text: row.name + '性能详情'
|
||||
},
|
||||
|
||||
legend: {
|
||||
data: ['cpu使用率', '内存使用率', '磁盘使用率'],
|
||||
icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
name: '时间'
|
||||
},
|
||||
yAxis: {
|
||||
max: '100',
|
||||
name: '%'
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: 'cpu使用率',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [
|
||||
['2022-02-01 12:12:11', 10],
|
||||
['2022-02-01 12:12:12', 20],
|
||||
['2022-02-01 12:12:13', 30],
|
||||
['2022-02-01 12:12:14', 44],
|
||||
['2022-02-01 12:12:15', 50],
|
||||
['2022-02-01 12:12:16', 65],
|
||||
['2022-02-01 12:12:17', 76]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '内存使用率',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [
|
||||
['2022-02-01 12:12:11', 13],
|
||||
['2022-02-01 12:12:12', 54],
|
||||
['2022-02-01 12:12:13', 34],
|
||||
['2022-02-01 12:12:14', 44],
|
||||
['2022-02-01 12:12:15', 35],
|
||||
['2022-02-01 12:12:16', 53]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '磁盘使用率',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [
|
||||
['2022-02-01 12:12:11', 13],
|
||||
['2022-02-01 12:12:12', 2],
|
||||
['2022-02-01 12:12:13', 2],
|
||||
['2022-02-01 12:12:14', 32],
|
||||
['2022-02-01 12:12:15', 43],
|
||||
['2022-02-01 12:12:16', 23],
|
||||
['2022-02-01 12:12:17', 23]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
dialogVisiblexq.value = true
|
||||
}
|
||||
// 流量详情
|
||||
const queryview = (row: any) => {}
|
||||
// 关闭
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false
|
||||
prodialogVisible.value = false
|
||||
liudialogVisible.value = false
|
||||
condialogVisible.value = false
|
||||
tjdialogVisible.value = false
|
||||
dialogVisiblexq.value = false
|
||||
// this.getList()
|
||||
}
|
||||
// 表格过滤
|
||||
const searchEvent = debounce(e => {
|
||||
const filterVal = XEUtils.toValueString(filterName.value).trim().toLowerCase()
|
||||
if (filterVal) {
|
||||
const options = { children: 'children' }
|
||||
const searchProps = ['name']
|
||||
const rest = XEUtils.searchTree(
|
||||
treeDataCopy.value,
|
||||
(item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1),
|
||||
options
|
||||
)
|
||||
treeData.value = rest
|
||||
|
||||
// 搜索之后默认展开所有子节点
|
||||
} else {
|
||||
treeData.value = treeDataCopy.value
|
||||
}
|
||||
nextTick(() => {
|
||||
const $table = tableRef.value
|
||||
if ($table) {
|
||||
$table.setAllTreeExpand(true)
|
||||
}
|
||||
})
|
||||
}, 500)
|
||||
</script>
|
||||
481
src/views/pqs/Event-boot/Region/components/Compatibility.vue
Normal file
481
src/views/pqs/Event-boot/Region/components/Compatibility.vue
Normal file
@@ -0,0 +1,481 @@
|
||||
<template>
|
||||
<div class="flex" style="margin: 15px 0">
|
||||
<span style="width: 100px; margin-top: 3px">电压等级:</span>
|
||||
<el-checkbox
|
||||
:indeterminate="isIndeterminate"
|
||||
v-model="checkAll"
|
||||
@change="handleCheckAllChange"
|
||||
style="margin-right: 28px"
|
||||
>
|
||||
全选
|
||||
</el-checkbox>
|
||||
<el-checkbox-group
|
||||
v-model="checkedVoltage"
|
||||
@change="handleCheckedVoltageChange"
|
||||
style="height: 72px; overflow-y: auto"
|
||||
>
|
||||
<el-checkbox v-for="(item, index) in grade" :label="item" :key="index">{{ item.name }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="flex" style="margin: 15px 0">
|
||||
<span style="width: 100px; margin-top: 3px">干扰源类型:</span>
|
||||
<el-checkbox
|
||||
:indeterminate="isIndeterminate1"
|
||||
v-model="checkAll1"
|
||||
@change="handleCheckAllChange1"
|
||||
style="margin-right: 28px"
|
||||
>
|
||||
全选
|
||||
</el-checkbox>
|
||||
<el-checkbox-group
|
||||
v-model="checkedSource"
|
||||
@change="handleCheckedSourceChange"
|
||||
style="height: 72px; overflow-y: auto"
|
||||
>
|
||||
<el-checkbox v-for="(item, index) in type" :label="item" :key="index">{{ item.name }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="flex" style="margin: 15px 0">
|
||||
<span style="width: 100px; line-height: 32px">兼容曲线:</span>
|
||||
<el-radio-group v-model="radio" @change="radioChange">
|
||||
<el-radio label="ITIC">ITIC</el-radio>
|
||||
<el-radio label="F47">F47</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<my-echart class="bars_w" :options="echartList" />
|
||||
|
||||
<vxe-table class="dw" :data="TableData" height="50px" v-bind="defaultAttribute">
|
||||
<vxe-column field="name" title="名称" width="100px"></vxe-column>
|
||||
<vxe-column field="totalEvents" title="事件总数" width="100px"></vxe-column>
|
||||
<vxe-column field="tolerable" title="可容忍" width="100px"></vxe-column>
|
||||
<vxe-column field="Intolerable" title="不可容忍" width="100px"></vxe-column>
|
||||
</vxe-table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { ref, reactive } from 'vue'
|
||||
const dictData = useDictData()
|
||||
const isIndeterminate = ref(false)
|
||||
const isIndeterminate1 = ref(false)
|
||||
const checkAll = ref(true)
|
||||
const checkAll1 = ref(true)
|
||||
const radio = ref('ITIC')
|
||||
const echartList = ref({})
|
||||
const ITIC = ref({})
|
||||
const F47 = ref({})
|
||||
const pointI: any = ref([])
|
||||
const pointIun: any = ref([])
|
||||
const pointF: any = ref([])
|
||||
const pointFun: any = ref([])
|
||||
const datalist: any = ref([])
|
||||
const TableData = ref([
|
||||
{
|
||||
name: '事件个数',
|
||||
totalEvents: '',
|
||||
tolerable: '',
|
||||
Intolerable: ''
|
||||
}
|
||||
])
|
||||
const checkedVoltage: any = ref(ref(dictData.getBasicData('Dev_Voltage_Stand')))
|
||||
const checkedSource: any = ref(dictData.getBasicData('Interference_Source'))
|
||||
const grade = ref(dictData.getBasicData('Dev_Voltage_Stand'))
|
||||
const type = ref(dictData.getBasicData('Interference_Source'))
|
||||
// 电压等级多选
|
||||
const handleCheckedVoltageChange = (val: any) => {
|
||||
const checkedCount = val.length
|
||||
checkAll.value = checkedCount === grade.value.length
|
||||
isIndeterminate.value = checkedCount > 0 && checkedCount < grade.value.length
|
||||
}
|
||||
const handleCheckAllChange = (val: any) => {
|
||||
checkedVoltage.value = val ? grade.value : []
|
||||
isIndeterminate.value = false
|
||||
}
|
||||
// 干扰源类型多选
|
||||
const handleCheckAllChange1 = (val: any) => {
|
||||
checkedSource.value = val ? type.value : []
|
||||
isIndeterminate.value = false
|
||||
}
|
||||
const handleCheckedSourceChange = (val: any) => {
|
||||
const checkedCount = val.length
|
||||
checkAll1.value = checkedCount === type.value.length
|
||||
isIndeterminate1.value = checkedCount > 0 && checkedCount < type.value.length
|
||||
}
|
||||
|
||||
const info = async (list: any) => {
|
||||
datalist.value = []
|
||||
list.forEach((item: any) => {
|
||||
if (item.eventValue < 2 && item.eventValue > 0) {
|
||||
datalist.value.push(item)
|
||||
}
|
||||
})
|
||||
await gongfunction()
|
||||
ITIC.value = {
|
||||
title: {
|
||||
text: 'ITIC曲线'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (a: any) {
|
||||
if (a[0].value[4] == undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
let relVal = ''
|
||||
relVal = "<font style='color:" + "'>供电公司:" + ' ' + ' ' + a[0].value[3] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>变电站:" + ' ' + ' ' + a[0].value[4] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>发生时刻:" + ' ' + ' ' + a[0].value[2] + '</font><br/>'
|
||||
relVal +=
|
||||
"<font style='color:" +
|
||||
"'>持续时间:" +
|
||||
' ' +
|
||||
' ' +
|
||||
a[0].value[0].toFixed(3) +
|
||||
's</font><br/>'
|
||||
relVal +=
|
||||
"<font style='color:" + "'>特征幅值:" + ' ' + ' ' + a[0].value[1].toFixed(3) + '%</font>'
|
||||
return relVal
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
|
||||
// selectedMode: false,
|
||||
left: '10px'
|
||||
},
|
||||
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
|
||||
xAxis: {
|
||||
type: 'log',
|
||||
min: '0.001',
|
||||
max: '1000',
|
||||
name: 's',
|
||||
splitLine: { show: false }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitNumber: 10,
|
||||
minInterval: 3,
|
||||
name: '%'
|
||||
},
|
||||
dataZoom: {
|
||||
type: null,
|
||||
show: false
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '上限',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.001, 200],
|
||||
[0.003, 140],
|
||||
[0.003, 120],
|
||||
[0.5, 120],
|
||||
[0.5, 110],
|
||||
[10, 110],
|
||||
[1000, 110]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '下限',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.02, 0],
|
||||
[0.02, 70],
|
||||
[0.5, 70],
|
||||
[0.5, 80],
|
||||
[10, 80],
|
||||
[10, 90],
|
||||
[1000, 90]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: pointI.value
|
||||
},
|
||||
{
|
||||
name: '不可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: pointIun.value
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
F47.value = {
|
||||
title: {
|
||||
text: 'F47曲线'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (a: any) {
|
||||
if (a[0].value[4] == undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
let relVal = ''
|
||||
relVal = "<font style='color:" + "'>供电公司:" + ' ' + ' ' + a[0].value[3] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>变电站:" + ' ' + ' ' + a[0].value[4] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>发生时刻:" + ' ' + ' ' + a[0].value[2] + '</font><br/>'
|
||||
relVal +=
|
||||
"<font style='color:" +
|
||||
"'>持续时间:" +
|
||||
' ' +
|
||||
' ' +
|
||||
a[0].value[0].toFixed(3) +
|
||||
's</font><br/>'
|
||||
relVal +=
|
||||
"<font style='color:" + "'>特征幅值:" + ' ' + ' ' + a[0].value[1].toFixed(3) + '%</font>'
|
||||
return relVal
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['分割线', '可容忍事件', '不可容忍事件'],
|
||||
// selectedMode: false,
|
||||
left: '10px'
|
||||
},
|
||||
color: ['yellow', 'green', 'red'],
|
||||
xAxis: {
|
||||
type: 'log',
|
||||
min: '0.001',
|
||||
max: '1000',
|
||||
name: 's',
|
||||
splitLine: { show: false }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitNumber: 10,
|
||||
minInterval: 3,
|
||||
name: '%'
|
||||
},
|
||||
dataZoom: {
|
||||
type: null,
|
||||
show: false
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '分割线',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.05, 0],
|
||||
[0.05, 50],
|
||||
[0.2, 50],
|
||||
[0.2, 70],
|
||||
[0.5, 70],
|
||||
[0.5, 80],
|
||||
[10, 80],
|
||||
[1000, 80]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: pointF.value
|
||||
},
|
||||
{
|
||||
name: '不可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: pointFun.value
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
radioChange(radio.value)
|
||||
}
|
||||
const radioChange = (e: any) => {
|
||||
if (e == 'ITIC') {
|
||||
echartList.value = ITIC.value
|
||||
TableData.value[0].totalEvents = pointI.value.length + pointIun.value.length
|
||||
TableData.value[0].tolerable = pointI.value.length
|
||||
TableData.value[0].Intolerable = pointIun.value.length
|
||||
} else if (e == 'F47') {
|
||||
echartList.value = F47.value
|
||||
TableData.value[0].totalEvents = pointF.value.length + pointFun.value.length
|
||||
TableData.value[0].tolerable = pointF.value.length
|
||||
TableData.value[0].Intolerable = pointFun.value.length
|
||||
}
|
||||
}
|
||||
|
||||
const gongfunction = () => {
|
||||
var standI = 0
|
||||
var unstandI = 0
|
||||
var standF = 0
|
||||
var unstandF = 0
|
||||
pointI.value = []
|
||||
pointIun.value = []
|
||||
pointF.value = []
|
||||
pointFun.value = []
|
||||
var total = 0
|
||||
total = datalist.value.length
|
||||
if (total == 0) {
|
||||
} else {
|
||||
for (var i = 0; i < datalist.value.length; i++) {
|
||||
var point = []
|
||||
var xx = datalist.value[i].persistTime
|
||||
var yy = datalist.value[i].eventValue * 100
|
||||
var time = datalist.value[i].time.replace('T', ' ')
|
||||
var company = datalist.value[i].gdName
|
||||
var substation = datalist.value[i].subName
|
||||
var index = datalist.value[i].lineId
|
||||
var eventId = datalist.value[i].eventId
|
||||
point = [xx, yy, time, company, substation, index, eventId]
|
||||
|
||||
if (xx <= 0.003) {
|
||||
var line = 0
|
||||
line = 230 - 30000 * xx
|
||||
if (yy > line) {
|
||||
unstandI++
|
||||
pointIun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.02) {
|
||||
if (yy > 120) {
|
||||
unstandI++
|
||||
pointIun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.5) {
|
||||
if (yy > 120 || yy < 70) {
|
||||
unstandI++
|
||||
pointIun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 10) {
|
||||
if (yy > 110 || yy < 80) {
|
||||
unstandI++
|
||||
pointIun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 110 || yy < 90) {
|
||||
unstandI++
|
||||
pointIun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (xx < 0.05) {
|
||||
standF++
|
||||
pointF.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else if (xx < 0.2) {
|
||||
if (yy > 50) {
|
||||
standF++
|
||||
pointF.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
} else if (xx < 0.5) {
|
||||
if (yy > 70) {
|
||||
standF++
|
||||
pointF.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 80) {
|
||||
standF++
|
||||
pointF.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.value.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ checkedVoltage, checkedSource, info })
|
||||
const layout = mainHeight(390) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.bars_w {
|
||||
height: calc(v-bind('layout.height'));
|
||||
}
|
||||
.dw {
|
||||
position: absolute;
|
||||
top: 210px;
|
||||
right: 70px;
|
||||
}
|
||||
</style>
|
||||
121
src/views/pqs/Event-boot/Region/components/Tableabove.vue
Normal file
121
src/views/pqs/Event-boot/Region/components/Tableabove.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div>
|
||||
<span style="font-size: 14px; font-weight: bold">
|
||||
统计区域: 中国   统计时间: {{ Time[0] + '至' + Time[1] }}   统计次数: {{ frequency + '次' }}
|
||||
</span>
|
||||
<el-tabs tab-position="left" class="demo-tabs" style="margin-top: 10px">
|
||||
<el-tab-pane label="区域">
|
||||
<div class="default-main">
|
||||
<vxe-table :data="areaData" v-bind="defaultAttribute" height="auto" auto-resize>
|
||||
<vxe-column
|
||||
v-for="item in tableHeaderAera"
|
||||
:field="item.prop"
|
||||
:title="item.label"
|
||||
:min-width="item.width"
|
||||
:sortable="item.sortable"
|
||||
:formatter="formatter"
|
||||
></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="电压等级">
|
||||
<div class="default-main">
|
||||
<vxe-table :data="levelData" v-bind="defaultAttribute" height="auto" auto-resize>
|
||||
<vxe-column
|
||||
v-for="item in tableHeaderLevel"
|
||||
:field="item.prop"
|
||||
:title="item.label"
|
||||
:min-width="item.width"
|
||||
:sortable="item.sortable"
|
||||
></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="月份">
|
||||
<div class="default-main">
|
||||
<vxe-table :data="shareData" v-bind="defaultAttribute" height="auto" auto-resize>
|
||||
<vxe-column field="month" title="月份" min-width="120px" sortable></vxe-column>
|
||||
<vxe-column field="notAssociated" title="电压暂降次数" sortable></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, defineExpose, computed } from 'vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
|
||||
const areaData: any = ref([])
|
||||
const levelData: any = ref([])
|
||||
const shareData: any = ref([])
|
||||
const Time: any = ref([])
|
||||
|
||||
const tableHeaderAera = ref<any[]>([
|
||||
{ prop: 'areaName', label: '区域名称', width: '120px' },
|
||||
{ prop: 'monitoringPoints', label: '监测点数', sortable: true },
|
||||
{ prop: 'frequency', label: '电压暂降次数', sortable: true },
|
||||
{ prop: 'sarfi9', label: 'SARFI-90', sortable: true }
|
||||
])
|
||||
const tableHeaderLevel = ref<any[]>([
|
||||
{ prop: 'voltageLevel', label: '电压等级(kV)', width: '150px' },
|
||||
{ prop: 'monitoringPoints', label: '监测点数' },
|
||||
{ prop: 'frequency', label: '电压暂降次数' }
|
||||
])
|
||||
|
||||
const frequency = ref<number>(875)
|
||||
|
||||
const info = (list: any, searchBeginTime: any, searchEndTime: any) => {
|
||||
Time.value = [searchBeginTime, searchEndTime]
|
||||
frequency.value = list.areaStatistics.frequencySum
|
||||
areaData.value = [
|
||||
{
|
||||
areaName: '总计',
|
||||
monitoringPoints: list.areaStatistics.monitoringPointSum,
|
||||
frequency: list.areaStatistics.frequencySum,
|
||||
sarfi9: '/'
|
||||
},
|
||||
...list.areaStatistics.areaCalculation
|
||||
]
|
||||
|
||||
levelData.value = [
|
||||
{
|
||||
voltageLevel: '总计',
|
||||
monitoringPoints: list.voltageStatistics.monitoringPointSum,
|
||||
frequency: list.voltageStatistics.frequencySum
|
||||
},
|
||||
...list.voltageStatistics.voltageLevelCalculation
|
||||
]
|
||||
let all = 0
|
||||
|
||||
list.monthlyStatistics.monthCalculation.forEach((item: any) => {
|
||||
all += item.linked + item.notAssociated
|
||||
})
|
||||
shareData.value = [
|
||||
{
|
||||
month: '总计',
|
||||
notAssociated: all.toFixed(2)
|
||||
},
|
||||
...list.monthlyStatistics.monthCalculation
|
||||
]
|
||||
}
|
||||
const formatter = (row: any) => {
|
||||
if (row.column.field == 'areaName') {
|
||||
return (row.cellValue = row.cellValue.replace('\n', ''))
|
||||
} else {
|
||||
return row.cellValue
|
||||
}
|
||||
}
|
||||
defineExpose({ info })
|
||||
const layout = mainHeight(185) as any
|
||||
const defaultMain = mainHeight(195) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
::v-deep(.el-tabs--left, ) {
|
||||
height: v-bind('layout.height');
|
||||
}
|
||||
.default-main {
|
||||
height: v-bind('defaultMain.height');
|
||||
}
|
||||
</style>
|
||||
144
src/views/pqs/Event-boot/Region/components/TypeStatistics.vue
Normal file
144
src/views/pqs/Event-boot/Region/components/TypeStatistics.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<span style="color: red; font-size: 12px">注:暂降类型仅统计暂降原因为短路故障事件</span>
|
||||
|
||||
<div class="statistics-main">
|
||||
<template v-if="flag">
|
||||
<div>
|
||||
<my-echart :options="descent" />
|
||||
</div>
|
||||
<div>
|
||||
<vxe-table height="auto" auto-resize :data="descentData" v-bind="defaultAttribute">
|
||||
<vxe-column field="name" title="暂降原因"></vxe-column>
|
||||
<vxe-column field="value" title="暂降次数"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
<div>
|
||||
<my-echart :options="resemble" />
|
||||
</div>
|
||||
<div>
|
||||
<vxe-table height="auto" auto-resize :data="resembleData" v-bind="defaultAttribute">
|
||||
<vxe-column field="name" title="暂降原因"></vxe-column>
|
||||
<vxe-column field="value" title="暂降次数"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
const descent = ref({})
|
||||
const descentData = ref([])
|
||||
const resemble = ref({})
|
||||
const resembleData = ref([])
|
||||
const flag = ref(true)
|
||||
|
||||
const info = (res: any) => {
|
||||
flag.value = false
|
||||
descentData.value = res.reason
|
||||
resembleData.value = res.type
|
||||
|
||||
descent.value = {
|
||||
title: {
|
||||
text: '暂降原因'
|
||||
},
|
||||
legend: {
|
||||
type: 'scroll',
|
||||
orient: 'vertical',
|
||||
left: 10,
|
||||
top: '5%',
|
||||
tooltip: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
show: false
|
||||
},
|
||||
yAxis: {
|
||||
show: false
|
||||
},
|
||||
dataZoom: { show: false },
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} (次)'
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '暂降原因',
|
||||
type: 'pie',
|
||||
center: ['50%', '50%'],
|
||||
selectedOffset: 30,
|
||||
clockwise: true,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'outside',
|
||||
textStyle: {
|
||||
//数值样式
|
||||
}
|
||||
},
|
||||
|
||||
data: res.reason?.filter((item: any) => item.name != '总计')
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
resemble.value = {
|
||||
title: {
|
||||
text: '暂降类型'
|
||||
},
|
||||
legend: {
|
||||
type: 'scroll',
|
||||
orient: 'vertical',
|
||||
left: 10,
|
||||
top: '5%'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c} (次)',
|
||||
confine: true
|
||||
},
|
||||
xAxis: {
|
||||
show: false
|
||||
},
|
||||
yAxis: {
|
||||
show: false
|
||||
},
|
||||
dataZoom: { show: false },
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '暂降类型',
|
||||
type: 'pie',
|
||||
center: ['50%', '50%'],
|
||||
selectedOffset: 30,
|
||||
clockwise: true,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'outside'
|
||||
},
|
||||
|
||||
data: res.type?.filter((item: any) => item.name != '总计')
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
flag.value = true
|
||||
}
|
||||
|
||||
defineExpose({ info })
|
||||
const layout = mainHeight(175) as any
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.statistics-main {
|
||||
box-sizing: border-box;
|
||||
height: v-bind('layout.height');
|
||||
padding: 0 10px 10px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 600px;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
}
|
||||
</style>
|
||||
293
src/views/pqs/Event-boot/Region/components/echart.vue
Normal file
293
src/views/pqs/Event-boot/Region/components/echart.vue
Normal file
@@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<div>
|
||||
<my-echart class="bars_w" :options="areaStatistics" />
|
||||
<div class="separate">
|
||||
<my-echart class="bars_w" :options="voltageStatistics" />
|
||||
<my-echart class="bars_w" :options="monthlyStatistics" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { reactive, ref, defineExpose } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
let areaStatistics = ref({})
|
||||
let voltageStatistics = ref({})
|
||||
let monthlyStatistics = ref({})
|
||||
|
||||
const Processing = (list: any) => {
|
||||
// 区域
|
||||
let echartsndArr: string[] = []
|
||||
let echartsArr: string[] = []
|
||||
list.areaCalculation.forEach((item: any) => {
|
||||
echartsndArr.push(item.areaName)
|
||||
if (item.frequency == 0) {
|
||||
item.frequency = 1.1
|
||||
} else if (item.frequency == 1) {
|
||||
item.frequency = 1.3
|
||||
}
|
||||
echartsArr.push(item.frequency)
|
||||
})
|
||||
areaStatistics.value = {
|
||||
title: {
|
||||
text: '区域'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
let html = '区域:' + params[0].name
|
||||
params.forEach((item: any) => {
|
||||
if (item.value == 1.1) {
|
||||
html += `<br/>${item.seriesName}: ${0}次`
|
||||
} else if (item.value == 1.3) {
|
||||
html += `<br/>${item.seriesName}: ${1}次`
|
||||
} else {
|
||||
html += `<br/>${item.seriesName}: ${item.value}次`
|
||||
}
|
||||
})
|
||||
return html
|
||||
}
|
||||
},
|
||||
|
||||
legend: {
|
||||
data: ['暂降次数']
|
||||
},
|
||||
xAxis: {
|
||||
name: '区域', // 给X轴加单位
|
||||
data: echartsndArr
|
||||
},
|
||||
yAxis: {
|
||||
name: '次数' // 给X轴加单位
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
barMinHeight: 5,
|
||||
barMaxWidth: 30,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
//这里是颜色
|
||||
color: function (params: any) {
|
||||
if (params.data == 1.1) {
|
||||
return '#B3B3B3'
|
||||
} else {
|
||||
return '#07CCCA '
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
name: '暂降次数',
|
||||
type: 'bar',
|
||||
data: echartsArr
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
// 电压等级
|
||||
const Grade = (list: any) => {
|
||||
let echartsndArr: string[] = []
|
||||
let echartsArr: string[] = []
|
||||
list.voltageLevelCalculation.forEach((item: any) => {
|
||||
echartsndArr.push(item.voltageLevel)
|
||||
if (item.frequency == 0) {
|
||||
item.frequency = 1.1
|
||||
} else if (item.frequency == 1) {
|
||||
item.frequency = 1.3
|
||||
}
|
||||
echartsArr.push(item.frequency)
|
||||
})
|
||||
|
||||
voltageStatistics.value = {
|
||||
title: {
|
||||
text: '电压等级'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
let html = '电压等级:' + params[0].name
|
||||
params.forEach((item: any) => {
|
||||
if (item.value == 1.1) {
|
||||
html += `<br/>${item.seriesName}: ${0}次`
|
||||
} else if (item.value == 1.3) {
|
||||
html += `<br/>${item.seriesName}: ${1}次`
|
||||
} else {
|
||||
html += `<br/>${item.seriesName}: ${item.value}次`
|
||||
}
|
||||
})
|
||||
return html
|
||||
}
|
||||
},
|
||||
|
||||
legend: {
|
||||
data: ['暂降次数']
|
||||
},
|
||||
xAxis: {
|
||||
name: '电压等级',
|
||||
data: echartsndArr
|
||||
},
|
||||
yAxis: {
|
||||
name: '次数' // 给X轴加单位
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
//这里是颜色
|
||||
color: function (params: any) {
|
||||
if (params.data == 1.1) {
|
||||
return '#B3B3B3'
|
||||
} else {
|
||||
return '#07CCCA '
|
||||
}
|
||||
}
|
||||
}
|
||||
// color: echartsColor.FigureColor[0],
|
||||
},
|
||||
name: '暂降次数',
|
||||
type: 'bar',
|
||||
data: echartsArr
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
//时间
|
||||
const Relation = (list: any, interval: number) => {
|
||||
let echartsndArr: string[] = []
|
||||
let echartsArr: string[] = []
|
||||
let echartswArr: string[] = []
|
||||
list.monthCalculation.forEach((item: any, i: number) => {
|
||||
if (i != 0) {
|
||||
item.month = item.month.slice(5)
|
||||
} else if (i == 0) {
|
||||
let date = item.month.slice(5)
|
||||
// let t = item.month.slice(0, 4);
|
||||
// item.month = date + "\n" + "(" + t + ")";
|
||||
item.month = date
|
||||
}
|
||||
|
||||
echartsndArr.push(item.month)
|
||||
// if (item.linked == 0 || item.notAssociated == 0) {
|
||||
// item.linked = 3.14159;
|
||||
// item.notAssociated = 3.14159;
|
||||
// }
|
||||
if (item.linked == 0) {
|
||||
item.linked = 1.1
|
||||
} else if (item.linked == 1) {
|
||||
item.linked = 1.3
|
||||
}
|
||||
echartsArr.push(item.linked)
|
||||
if (item.notAssociated == 0) {
|
||||
item.notAssociated = 1.1
|
||||
} else if (item.notAssociated == 1) {
|
||||
item.notAssociated = 1.3
|
||||
}
|
||||
echartswArr.push(item.notAssociated)
|
||||
})
|
||||
monthlyStatistics.value = {
|
||||
title: {
|
||||
text: '时间'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
let html = '时间:' + params[0].name
|
||||
params.forEach((item: any) => {
|
||||
if (item.value == 1.1) {
|
||||
html += `<br/>${item.seriesName}: ${0}次`
|
||||
} else if (item.value == 1.3) {
|
||||
html += `<br/>${item.seriesName}: ${1}次`
|
||||
} else {
|
||||
html += `<br/>${item.seriesName}: ${item.value}次`
|
||||
}
|
||||
})
|
||||
return html
|
||||
}
|
||||
},
|
||||
|
||||
legend: {
|
||||
data: ['未关联暂降次数', '已关联处理事件']
|
||||
},
|
||||
color: ['#07CCCA', '#Ff6600'],
|
||||
xAxis: {
|
||||
name: '月份', // 给X轴加单位
|
||||
data: echartsndArr
|
||||
},
|
||||
yAxis: {
|
||||
name: '次数' // 给X轴加单位
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '未关联暂降次数',
|
||||
type: 'bar',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
data: echartswArr,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
// show: true, //数字开启显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
fontWeight: 600
|
||||
}
|
||||
},
|
||||
color: function (params: any) {
|
||||
if (params.data == 1.1) {
|
||||
return '#B3B3B3'
|
||||
} else {
|
||||
return '#07CCCA '
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '已关联处理事件',
|
||||
type: 'bar',
|
||||
barMaxWidth: 30,
|
||||
data: echartsArr,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
// show: true, //数字开启显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
fontWeight: 600
|
||||
}
|
||||
},
|
||||
color: function (params: any) {
|
||||
if (params.data == 1.1) {
|
||||
return '#B3B3B3'
|
||||
} else {
|
||||
return '#Ff6600'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
// Processing()
|
||||
defineExpose({ Processing, Grade, Relation })
|
||||
const layout = mainHeight(150) as any
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bars_w {
|
||||
width: 100%;
|
||||
height: calc(v-bind('layout.height') / 2);
|
||||
}
|
||||
.separate {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
316
src/views/pqs/Event-boot/Region/distribution.vue
Normal file
316
src/views/pqs/Event-boot/Region/distribution.vue
Normal file
@@ -0,0 +1,316 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader area ref="header">
|
||||
<template v-slot:select>
|
||||
<!-- <el-form-item label="区域">
|
||||
<Area ref="area" v-model="tableStore.table.params.deptIndex" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
value-key="id"
|
||||
placeholder="请选择统计类型"
|
||||
size="large"
|
||||
>
|
||||
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<div v-loading="tableStore.table.loading" class="pr10">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<MyEchartMap
|
||||
ref="EchartMap"
|
||||
:options="echartMapList"
|
||||
class="map"
|
||||
@eliminate="eliminate"
|
||||
@getRegionByRegion="getRegionByRegion"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<my-echart class="tall" :options="echartList" />
|
||||
<div class="tall">
|
||||
<vxe-table height="auto" auto-resize :data="distributionData" v-bind="defaultAttribute">
|
||||
>
|
||||
<vxe-column
|
||||
field="qy"
|
||||
:title="
|
||||
titleA == '电压等级'
|
||||
? '电压等级'
|
||||
: titleA == '终端厂家'
|
||||
? '终端厂家'
|
||||
: titleA == '干扰源类型'
|
||||
? '干扰源类型'
|
||||
: titleA == '电网拓扑'
|
||||
? '区域'
|
||||
: ''
|
||||
"
|
||||
show-overflow-tooltip
|
||||
></vxe-column>
|
||||
<vxe-column field="jcd" title="监测点数(个数)"></vxe-column>
|
||||
<vxe-column field="zc" title="通讯正常(个数)" sortable></vxe-column>
|
||||
<vxe-column field="zd" title="通讯中断(个数)" sortable></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
defineOptions({
|
||||
name: 'Region/distribution'
|
||||
})
|
||||
const EchartMap = ref()
|
||||
const dictData = useDictData()
|
||||
const options = dictData.getBasicData('Statistical_Type', ['Report_Type'])
|
||||
const echartMapList:any = ref({})
|
||||
const echartList = ref({})
|
||||
const titleA = ref('')
|
||||
const header = ref()
|
||||
const distributionData: any = ref([])
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/area/getAreaLineDetail',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
loadCallback: () => {
|
||||
titleA.value = tableStore.table.params.statisticalType.name
|
||||
header.value.areaRef.change()
|
||||
// 处理地图数据
|
||||
map(tableStore.table.data)
|
||||
tabulation(tableStore.table.data)
|
||||
histogram(tableStore.table.data)
|
||||
EchartMap.value.GetEchar(header.value.areaRef.areaName)
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
// tableStore.table.params.deptIndex = dictData.state.area[0].id
|
||||
tableStore.table.params.statisticalType = dictData.getBasicData('Statistical_Type', ['Report_Type'])[0]
|
||||
tableStore.table.params.monitorFlag = 2
|
||||
tableStore.table.params.powerFlag = 2
|
||||
tableStore.table.params.serverName = 'event-boot'
|
||||
|
||||
// 地图点击事件
|
||||
const getRegionByRegion = (list: any) => {
|
||||
tableStore.table.params.deptIndex = list.id
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
// 消除点
|
||||
const eliminate = (name: string) => {
|
||||
echartMapList.value.options.series = []
|
||||
EchartMap.value.GetEchar(name)
|
||||
}
|
||||
|
||||
// 地图数处理
|
||||
const map = (res: any) => {
|
||||
echartMapList.value = {
|
||||
name: '',
|
||||
title: {
|
||||
text: '监测网分布' //+ "(" + _this.titles + ")",
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
//console.log(params)
|
||||
var tips = ''
|
||||
if (params.value == 0) {
|
||||
tips = "<font style='color: #000'>暂无数据</font><br/>"
|
||||
} else {
|
||||
tips +=
|
||||
"<font style='color: #000'> " +
|
||||
params.name +
|
||||
'</font><br/>区域暂降评估' +
|
||||
"<font style='color: #000'>:" +
|
||||
params.value +
|
||||
'</font><br/>'
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
color: ['green', 'red'],
|
||||
legend: {
|
||||
data: [
|
||||
{
|
||||
name: '正常'
|
||||
},
|
||||
{
|
||||
name: '中断'
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
series: []
|
||||
}
|
||||
}
|
||||
let mapList:any = [[], [], []]
|
||||
if (res.substationDetailVOList != null) {
|
||||
res.substationDetailVOList.forEach((item: any) => {
|
||||
if (item.color == 'green') {
|
||||
mapList[0].push(item)
|
||||
} else if (item.color == 'red') {
|
||||
mapList[1].push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
mapList.forEach((item:any, ind:number) => {
|
||||
echartMapList.value.options.series.push({
|
||||
type: 'scatter',
|
||||
mapName: 'china',
|
||||
name: ind == 0 ? '正常' : ind == 1 ? '中断' : '变电站',
|
||||
coordinateSystem: 'geo',
|
||||
geoIndex: 0,
|
||||
animation: false, //坐标点是否显示动画
|
||||
roam: true,
|
||||
symbol: 'pin',
|
||||
symbolSize: function () {
|
||||
//坐标点大小
|
||||
return 30
|
||||
},
|
||||
label: {
|
||||
normal: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
data: item.map(function (itemOpt: any) {
|
||||
// console.log(itemOpt);
|
||||
return {
|
||||
name: itemOpt.srbName,
|
||||
value: [
|
||||
parseFloat(itemOpt.coordY), //经度
|
||||
parseFloat(itemOpt.coordX) //维度
|
||||
],
|
||||
|
||||
itemStyle: {
|
||||
//地图区域的多边形
|
||||
normal: {
|
||||
color: itemOpt.color, //坐标点颜色
|
||||
shadowBlur: 0, // 图形阴影的模糊大小
|
||||
shadowOffsetX: 0 // 阴影水平方向上的偏移距离。
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
//仅在 options中最外层的 tooltip.trigger 为 'item'时有效
|
||||
position: 'bottom', //提示框位置,仅在 options中最外层的 tooltip.trigger 为 'item'时有效
|
||||
formatter: function (params: any, ticket: any, callback: any) {
|
||||
var strHtml = '<div>变电站:' + itemOpt.subName + '<br/>' + '监测点:' + itemOpt.srbName
|
||||
|
||||
strHtml += '</div>'
|
||||
return strHtml
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 表格数据处理
|
||||
const tabulation = (res: any) => {
|
||||
distributionData.value = []
|
||||
for (var i = 0; i < res.areaValue.length; i++) {
|
||||
distributionData.value.push({
|
||||
qy: res.areaValue[i][0],
|
||||
jcd: res.areaValue[i][1],
|
||||
zc: res.areaValue[i][2],
|
||||
zd: res.areaValue[i][3]
|
||||
})
|
||||
}
|
||||
}
|
||||
// 柱状图数据处理
|
||||
const histogram = (res: any) => {
|
||||
echartList.value = {
|
||||
title: {
|
||||
text:
|
||||
titleA.value == '电压等级'
|
||||
? '电压等级'
|
||||
: titleA.value == '终端厂家'
|
||||
? '终端厂家'
|
||||
: titleA.value == '干扰源类型'
|
||||
? '干扰源类型'
|
||||
: titleA.value == '电网拓扑'
|
||||
? header.value.areaRef.areaName
|
||||
: '' // 给X轴加单位
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
// console.log(params);
|
||||
var tips = ''
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
tips += params[i].name + '</br/>'
|
||||
tips += '监测点数' + ':' + ' ' + ' ' + params[i].value + '</br/>'
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
name:
|
||||
titleA.value == '电压等级'
|
||||
? '(电压\n等级)'
|
||||
: titleA.value == '终端厂家'
|
||||
? '(终端\n厂家)'
|
||||
: titleA.value == '干扰源类型'
|
||||
? '(干扰\n源类型)'
|
||||
: titleA.value == '电网拓扑'
|
||||
? '(区域)'
|
||||
: '', // 给X轴加单位
|
||||
data: distributionData.value.map((item: any) => item.qy)
|
||||
},
|
||||
yAxis: {
|
||||
name: '监测点数(个)' // 给X轴加单位
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
// name: '暂降次数',
|
||||
type: 'bar',
|
||||
data: distributionData.value.map((item: any) => item.jcd),
|
||||
barMaxWidth: 30,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#07CCCA'
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: '#000'
|
||||
},
|
||||
fontSize: 12
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const layout = mainHeight(83) as any
|
||||
const layout1 = mainHeight(93) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.map {
|
||||
height: v-bind('layout.height');
|
||||
}
|
||||
.tall {
|
||||
height: calc(v-bind('layout1.height') / 2);
|
||||
}
|
||||
</style>
|
||||
63
src/views/pqs/Event-boot/Region/overview.vue
Normal file
63
src/views/pqs/Event-boot/Region/overview.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker area></TableHeader>
|
||||
<el-tabs v-model="activeName" type="border-card" v-loading="tableStore.table.loading">
|
||||
<el-tab-pane label="图形" name="1">
|
||||
<Echart ref="echarts" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="表格" name="2"><Tableabove ref="table" /></el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import Echart from './components/echart.vue'
|
||||
import Tableabove from './components/Tableabove.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { onMounted, reactive, ref, provide } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
defineOptions({
|
||||
name: 'Region/overview'
|
||||
})
|
||||
const activeName = ref('1')
|
||||
const echarts = ref()
|
||||
const Picker = ref()
|
||||
const table = ref()
|
||||
const dictData = useDictData()
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/areaStatistics/getAreaCalculation',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
loadCallback: () => {
|
||||
table.value.info(tableStore.table.data,tableStore.table.params.searchBeginTime,tableStore.table.params.searchEndTime)
|
||||
echarts.value.Processing(tableStore.table.data.areaStatistics)
|
||||
echarts.value.Grade(tableStore.table.data.voltageStatistics)
|
||||
echarts.value.Relation(JSON.parse(JSON.stringify(tableStore.table.data.monthlyStatistics)))
|
||||
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
tableStore.table.params.statisticalType = dictData.getBasicData('Statistical_Type', ['Load_Type'])[3]
|
||||
tableStore.table.params.monitorFlag = 2
|
||||
tableStore.table.params.powerFlag = 2
|
||||
tableStore.table.params.serverName = 'event-boot'
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const layout = mainHeight(123) as any
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bars_w {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
::v-deep(.el-tabs__content) {
|
||||
height: v-bind('layout.height');
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
79
src/views/pqs/Event-boot/Region/statistics.vue
Normal file
79
src/views/pqs/Event-boot/Region/statistics.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker area>
|
||||
<template v-slot:select></template>
|
||||
</TableHeader>
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick" v-loading="tableStore.table.loading">
|
||||
<el-tab-pane label="暂降原因及类型统计" name="1">
|
||||
<TypeStatistics ref="Statistics" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="电压容忍度曲线兼容性统计" name="2">
|
||||
<Compatibility ref="compatibility" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { onMounted, reactive, ref, provide } from 'vue'
|
||||
import TypeStatistics from './components/TypeStatistics.vue'
|
||||
import Compatibility from './components/Compatibility.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
defineOptions({
|
||||
name: 'Region/overview'
|
||||
})
|
||||
const activeName = ref('1')
|
||||
const Statistics = ref()
|
||||
const compatibility = ref()
|
||||
const dictData = useDictData()
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/areaAnalysis/getEventReason',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
loadCallback: () => {
|
||||
if (activeName.value == '1') {
|
||||
Statistics.value.info(tableStore.table.data)
|
||||
} else {
|
||||
compatibility.value.info(tableStore.table.data.voltageToleranceCurveDataList)
|
||||
}
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
tableStore.table.params.statisticalType = dictData.getBasicData('Statistical_Type', ['Load_Type'])[3]
|
||||
tableStore.table.params.monitorFlag = 2
|
||||
tableStore.table.params.powerFlag = 2
|
||||
tableStore.table.params.serverName = 'event-boot'
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const handleClick = async (e: any) => {
|
||||
if (e.paneName == '1') {
|
||||
tableStore.table.params.scale = null
|
||||
tableStore.table.params.loadType = null
|
||||
tableStore.url = '/event-boot/areaAnalysis/getEventReason'
|
||||
} else {
|
||||
tableStore.table.params.scale = compatibility.value.checkedVoltage
|
||||
tableStore.table.params.loadType = compatibility.value.checkedSource
|
||||
tableStore.url = '/event-boot/areaAnalysis/getVoltageToleranceCurve'
|
||||
}
|
||||
await tableStore.onTableAction('search', {})
|
||||
}
|
||||
const layout = mainHeight(123) as any
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bars_w {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
::v-deep(.el-tabs__content) {
|
||||
height: v-bind('layout.height');
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
352
src/views/pqs/Event-boot/Region/thermodynamicDiagram.vue
Normal file
352
src/views/pqs/Event-boot/Region/thermodynamicDiagram.vue
Normal file
@@ -0,0 +1,352 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader area date-picker ref="header" />
|
||||
<div v-loading="tableStore.table.loading" class="pr10">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<MyEchartMap
|
||||
ref="EchartMap"
|
||||
:options="echartMapList"
|
||||
class="map"
|
||||
@eliminate="eliminate"
|
||||
@getRegionByRegion="getRegionByRegion"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<my-echart class="tall" :options="echartList" />
|
||||
<div class="tall">
|
||||
<vxe-table height="auto" auto-resize :data="distributionData" v-bind="defaultAttribute">
|
||||
>
|
||||
<vxe-column field="areaName" title=" 区域" show-overflow-tooltip></vxe-column>
|
||||
<vxe-column field="ci" title="区域暂降评估">
|
||||
<template #default="{ row }">
|
||||
{{ row.ci == 0.05 ? '暂无数据' : row.ci.toFixed(2) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column sortable field="isCount" title="等级">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.ci == 0.05">暂无等级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 0.2 && row.ci < 0.4">1级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 0.4 && row.ci < 0.8">2级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 0.8 && row.ci < 1.2">3级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 1.2">4级</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
defineOptions({
|
||||
name: 'Region/distribution'
|
||||
})
|
||||
const EchartMap = ref()
|
||||
const dictData = useDictData()
|
||||
const echartMapList: any = ref({})
|
||||
const echartList = ref({})
|
||||
const header = ref()
|
||||
const distributionData: any = ref([])
|
||||
const list: any = ref([])
|
||||
const geoCoordMap: any = ref([])
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/area/getEventHeatMap',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
beforeSearchFun: () => {},
|
||||
loadCallback: () => {
|
||||
header.value.areaRef.change()
|
||||
// 处理地图数据
|
||||
tableStore.table.data.eventHeatMapValue.forEach(val => {
|
||||
val.forEach(item => {
|
||||
list.value.push(item)
|
||||
geoCoordMap.value.push([item.lng, item.lat, item.tail])
|
||||
})
|
||||
})
|
||||
map(tableStore.table.data)
|
||||
// tabulation(tableStore.table.data)
|
||||
// histogram(tableStore.table.data)
|
||||
EchartMap.value.GetEchar(header.value.areaRef.areaName)
|
||||
}
|
||||
})
|
||||
|
||||
tableStore.table.params.monitorFlag = 2
|
||||
tableStore.table.params.powerFlag = 1
|
||||
tableStore.table.params.reportFlag = 3
|
||||
tableStore.table.params.statFlag = true
|
||||
tableStore.table.params.statisticalType = dictData.getBasicData('Statistical_Type', ['Load_Type'])[3]
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
// 地图点击事件
|
||||
const getRegionByRegion = (list: any) => {
|
||||
tableStore.table.params.deptIndex = list.id
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
// 消除点
|
||||
const eliminate = (name: string) => {
|
||||
echartMapList.value.options.series = []
|
||||
EchartMap.value.GetEchar(name)
|
||||
}
|
||||
|
||||
// 地图数处理
|
||||
const map = (res: any) => {
|
||||
let areaData: any = []
|
||||
|
||||
if (geoCoordMap.value.lengt > 0) {
|
||||
geoCoordMap.value.map(item => {
|
||||
areaData.push(...new Array(3).fill(item))
|
||||
})
|
||||
}
|
||||
let maxNum = 0
|
||||
let minNum = 0
|
||||
let num: any = []
|
||||
|
||||
if (areaData.length > 0) {
|
||||
areaData.forEach(item => {
|
||||
num.push(item[2])
|
||||
})
|
||||
for (let i = 0; i < num.length; i++) {
|
||||
if (num[i] > maxNum) {
|
||||
maxNum = num[i]
|
||||
} else if (num[i] < minNum) {
|
||||
minNum = num[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echartMapList.value = {
|
||||
name: '',
|
||||
title: {
|
||||
text: '区域暂降热力图分布'
|
||||
},
|
||||
|
||||
visualMap: {
|
||||
left: 26,
|
||||
bottom: 40,
|
||||
show: true,
|
||||
color: ['#ff0000', '#37b70c'],
|
||||
min: minNum,
|
||||
max: maxNum,
|
||||
calculable: true,
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
mapType: 'nanshan',
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: '65%',
|
||||
height: '95%',
|
||||
|
||||
name: 'AQI',
|
||||
type: 'heatmap',
|
||||
coordinateSystem: 'geo',
|
||||
blurSize: 40,
|
||||
data: areaData
|
||||
// 鼠标移入
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 表格数据处理
|
||||
const tabulation = (res: any) => {
|
||||
distributionData.value = res
|
||||
distributionData.value.forEach((item: any) => {
|
||||
if (item.ci == 0) {
|
||||
item.ci = 0.05
|
||||
}
|
||||
})
|
||||
}
|
||||
// 柱状图数据处理
|
||||
const histogram = (res: any) => {
|
||||
echartList.value = {
|
||||
title: {
|
||||
text: header.value.areaRef.areaName
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
var tips = ''
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
if (params[i].value == 0.05) {
|
||||
tips += params[i].name + '</br>'
|
||||
tips += '评估值:0'
|
||||
} else {
|
||||
tips += params[i].name + '</br>'
|
||||
tips += '评估值:' + params[i].value
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
name: '(区域)',
|
||||
|
||||
data: res.map((item: any) => item.areaName)
|
||||
},
|
||||
yAxis: {
|
||||
name: ' 等级',
|
||||
min: 0,
|
||||
max: 2,
|
||||
// minInterval: 0.2,
|
||||
axisLabel: {
|
||||
fontSize: 14,
|
||||
// interval: 4,
|
||||
formatter: function (value: any) {
|
||||
var texts = ''
|
||||
if (value === 0.4) {
|
||||
texts = '1级'
|
||||
} else if (value === 0.8) {
|
||||
texts = '2级'
|
||||
} else if (value === 1.2) {
|
||||
texts = '3级'
|
||||
} else if (value === 2) {
|
||||
texts = '4级'
|
||||
}
|
||||
return texts
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
//
|
||||
{
|
||||
name: '',
|
||||
data: res.map((item: any) => {
|
||||
if (item.ci == 0) {
|
||||
return (item.ci = 0.05)
|
||||
}
|
||||
return item.ci.toFixed(2)
|
||||
}),
|
||||
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 1,
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value > 2 && params.value !== 0.05) {
|
||||
return '#339966'
|
||||
} else if (0.8 < params.value && params.value <= 1.2 && params.value !== 0.05) {
|
||||
return '#3399FF'
|
||||
} else if (0.4 < params.value && params.value <= 0.8 && params.value !== 0.05) {
|
||||
return '#FF9900'
|
||||
} else if (0 < params.value && params.value <= 0.4 && params.value !== 0.05) {
|
||||
return '#CC0000'
|
||||
} else if (params.value == 0.05) {
|
||||
return '#CC0000'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
markLine: {
|
||||
silent: false,
|
||||
symbol: 'circle',
|
||||
lineStyle: {
|
||||
color: 'red',
|
||||
width: 1
|
||||
},
|
||||
emphasis: {
|
||||
lineStyle: {
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
name: '',
|
||||
yAxis: 0.4,
|
||||
lineStyle: {
|
||||
color: '#CC0000'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#CC0000'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 0.8,
|
||||
lineStyle: {
|
||||
color: '#FF9900'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#FF9900'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 1.2,
|
||||
lineStyle: {
|
||||
color: '#3399FF'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#3399FF'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 2,
|
||||
lineStyle: {
|
||||
color: '#339966'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#339966'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 10)
|
||||
})
|
||||
const layout = mainHeight(83) as any
|
||||
const layout1 = mainHeight(93) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.map {
|
||||
height: v-bind('layout.height');
|
||||
}
|
||||
.tall {
|
||||
height: calc(v-bind('layout1.height') / 2);
|
||||
}
|
||||
</style>
|
||||
397
src/views/pqs/Event-boot/Region/transientassessment.vue
Normal file
397
src/views/pqs/Event-boot/Region/transientassessment.vue
Normal file
@@ -0,0 +1,397 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader area date-picker ref="header" />
|
||||
<div v-loading="tableStore.table.loading" class="pr10">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<MyEchartMap
|
||||
ref="EchartMap"
|
||||
:options="echartMapList"
|
||||
class="map"
|
||||
@eliminate="eliminate"
|
||||
@getRegionByRegion="getRegionByRegion"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<my-echart class="tall" :options="echartList" />
|
||||
<div class="tall">
|
||||
<vxe-table height="auto" auto-resize :data="distributionData" v-bind="defaultAttribute">
|
||||
>
|
||||
<vxe-column field="areaName" title=" 区域" show-overflow-tooltip></vxe-column>
|
||||
<vxe-column field="ci" title="区域暂降评估">
|
||||
<template #default="{ row }">
|
||||
{{ row.ci == 0.05 ? '暂无数据' : row.ci.toFixed(2) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column sortable field="isCount" title="等级">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.ci == 0.05">暂无等级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 0.2 && row.ci < 0.4">1级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 0.4 && row.ci < 0.8">2级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 0.8 && row.ci < 1.2">3级</span>
|
||||
<span v-if="row.ci !== 0.05 && row.ci >= 1.2">4级</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="dw">
|
||||
<el-popover placement="left" :width="600" trigger="hover">
|
||||
<template #reference>
|
||||
<span class="level">详细区域暂降评估等级</span>
|
||||
</template>
|
||||
<vxe-table :data="areaData1" v-bind="defaultAttribute">
|
||||
<vxe-column title="等级" field="level" min-width="90"></vxe-column>
|
||||
<vxe-column title="1级" field="one" min-width="80"></vxe-column>
|
||||
<vxe-column title="2级" field="two" min-width="90"></vxe-column>
|
||||
<vxe-column title="3级" field="three" min-width="90"></vxe-column>
|
||||
<vxe-column title="4级" field="four" min-width="90"></vxe-column>
|
||||
</vxe-table>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
defineOptions({
|
||||
name: 'Region/distribution'
|
||||
})
|
||||
const EchartMap = ref()
|
||||
const dictData = useDictData()
|
||||
const echartMapList: any = ref({})
|
||||
const echartList = ref({})
|
||||
const header = ref()
|
||||
const distributionData: any = ref([])
|
||||
const areaData1: any = ref([
|
||||
{
|
||||
level: '相对得分',
|
||||
one: '[0,0.4]',
|
||||
two: '(0.4,0.8)',
|
||||
three: '(0.8,1.2)',
|
||||
four: '(1.2,+∞)'
|
||||
}
|
||||
])
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/advance-boot/balance/getBalanceInfo',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.deptId = tableStore.table.params.deptIndex
|
||||
},
|
||||
loadCallback: () => {
|
||||
header.value.areaRef.change()
|
||||
// 处理地图数据
|
||||
map(tableStore.table.data)
|
||||
tabulation(tableStore.table.data)
|
||||
histogram(tableStore.table.data)
|
||||
EchartMap.value.GetEchar(header.value.areaRef.areaName)
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
tableStore.table.params.loadType = null
|
||||
tableStore.table.params.deptId = dictData.state.area[0].id
|
||||
|
||||
// 地图点击事件
|
||||
const getRegionByRegion = (list: any) => {
|
||||
tableStore.table.params.deptIndex = list.id
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
// 消除点
|
||||
const eliminate = (name: string) => {
|
||||
echartMapList.value.options.series = []
|
||||
EchartMap.value.GetEchar(name)
|
||||
}
|
||||
|
||||
// 地图数处理
|
||||
const map = (res: any) => {
|
||||
let list: any = []
|
||||
res.forEach((item: any) => {
|
||||
list.push({
|
||||
name: item.areaName,
|
||||
value: item.ci
|
||||
})
|
||||
})
|
||||
|
||||
echartMapList.value = {
|
||||
name: '',
|
||||
title: {
|
||||
text: '区域暂降评估'
|
||||
},
|
||||
|
||||
visualMap: {
|
||||
min: 0,
|
||||
max: 2,
|
||||
left: 26,
|
||||
bottom: 20,
|
||||
showLabel: !0,
|
||||
|
||||
pieces: [
|
||||
{
|
||||
gt: -2,
|
||||
lte: -1,
|
||||
label: '无数据'
|
||||
},
|
||||
{
|
||||
gte: 0,
|
||||
lte: 0.4,
|
||||
label: '1级--相对得分 [0,0.4]'
|
||||
},
|
||||
{
|
||||
gt: 0.4,
|
||||
lte: 0.9,
|
||||
label: '2级--得分 (0.4,0.8]'
|
||||
},
|
||||
{
|
||||
gt: 0.9,
|
||||
lte: 1.2,
|
||||
label: '3级--相对得分 (0.8,1.2]'
|
||||
},
|
||||
{
|
||||
gt: 1.2,
|
||||
label: '4级--相对得分 (1.2,+∞]'
|
||||
}
|
||||
],
|
||||
inRange: {
|
||||
color: ['#ccc', '#CC0000', '#FF9900', '#3399CC', '#339966']
|
||||
}
|
||||
},
|
||||
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
// type: "scatter",
|
||||
type: 'map',
|
||||
mapName: name,
|
||||
coordinateSystem: 'geo',
|
||||
geoIndex: 0,
|
||||
animation: false, //坐标点是否显示动画
|
||||
roam: true,
|
||||
selectedMode: 'false', //是否允许选中多个区域
|
||||
symbol: 'pin',
|
||||
rippleEffect: {
|
||||
brushType: 'fill' // stroke|fill
|
||||
},
|
||||
|
||||
label: {
|
||||
normal: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
},
|
||||
data: list
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 表格数据处理
|
||||
const tabulation = (res: any) => {
|
||||
distributionData.value = res
|
||||
distributionData.value.forEach((item: any) => {
|
||||
if (item.ci == 0) {
|
||||
item.ci = 0.05
|
||||
}
|
||||
})
|
||||
}
|
||||
// 柱状图数据处理
|
||||
const histogram = (res: any) => {
|
||||
echartList.value = {
|
||||
title: {
|
||||
text: header.value.areaRef.areaName
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
var tips = ''
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
if (params[i].value == 0.05) {
|
||||
tips += params[i].name + '</br>'
|
||||
tips += '评估值:0'
|
||||
} else {
|
||||
tips += params[i].name + '</br>'
|
||||
tips += '评估值:' + params[i].value
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
name: '(区域)',
|
||||
|
||||
data: res.map((item: any) => item.areaName)
|
||||
},
|
||||
yAxis: {
|
||||
name: ' 等级',
|
||||
min: 0,
|
||||
max: 2,
|
||||
// minInterval: 0.2,
|
||||
axisLabel: {
|
||||
fontSize: 14,
|
||||
// interval: 4,
|
||||
formatter: function (value: any) {
|
||||
var texts = ''
|
||||
if (value === 0.4) {
|
||||
texts = '1级'
|
||||
} else if (value === 0.8) {
|
||||
texts = '2级'
|
||||
} else if (value === 1.2) {
|
||||
texts = '3级'
|
||||
} else if (value === 2) {
|
||||
texts = '4级'
|
||||
}
|
||||
return texts
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
//
|
||||
{
|
||||
name: '',
|
||||
data: res.map((item: any) => {
|
||||
if (item.ci == 0) {
|
||||
return (item.ci = 0.05)
|
||||
}
|
||||
return item.ci.toFixed(2)
|
||||
}),
|
||||
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 1,
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value > 2 && params.value !== 0.05) {
|
||||
return '#339966'
|
||||
} else if (0.8 < params.value && params.value <= 1.2 && params.value !== 0.05) {
|
||||
return '#3399FF'
|
||||
} else if (0.4 < params.value && params.value <= 0.8 && params.value !== 0.05) {
|
||||
return '#FF9900'
|
||||
} else if (0 < params.value && params.value <= 0.4 && params.value !== 0.05) {
|
||||
return '#CC0000'
|
||||
} else if (params.value == 0.05) {
|
||||
return '#CC0000'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
markLine: {
|
||||
silent: false,
|
||||
symbol: 'circle',
|
||||
lineStyle: {
|
||||
color: 'red',
|
||||
width: 1
|
||||
},
|
||||
emphasis: {
|
||||
lineStyle: {
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
name: '',
|
||||
yAxis: 0.4,
|
||||
lineStyle: {
|
||||
color: '#CC0000'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#CC0000'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 0.8,
|
||||
lineStyle: {
|
||||
color: '#FF9900'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#FF9900'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 1.2,
|
||||
lineStyle: {
|
||||
color: '#3399FF'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#3399FF'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 2,
|
||||
lineStyle: {
|
||||
color: '#339966'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#339966'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 10)
|
||||
})
|
||||
const layout = mainHeight(83) as any
|
||||
const layout1 = mainHeight(93) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.map {
|
||||
height: v-bind('layout.height');
|
||||
}
|
||||
.tall {
|
||||
height: calc(v-bind('layout1.height') / 2);
|
||||
}
|
||||
.dw {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 50px;
|
||||
width: 200px;
|
||||
z-index: 2;
|
||||
.level {
|
||||
color: red;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
61
src/views/pqs/comptroller/list.vue
Normal file
61
src/views/pqs/comptroller/list.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker>
|
||||
<template v-slot:select>
|
||||
<!-- <el-form-item label="用户名">
|
||||
<el-select v-model="value" class="m-2" placeholder="Select" size="large">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作类型">
|
||||
<el-input v-model="tableStore.table.params.loginName" placeholder="Please input" />
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button :icon="Plus" type="primary" @click="addMenu">添加</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { saveLogParam } from '@/api/common'
|
||||
|
||||
defineOptions({
|
||||
name: 'comptroller/list'
|
||||
})
|
||||
const tableStore = new TableStore({
|
||||
url: '/system-boot/audit/getAuditLog',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '操作时间', field: 'time', align: 'center', width: 200 },
|
||||
{ title: '操作人员', field: 'userName', align: 'center', width: 120 },
|
||||
{ title: '操作类型', field: 'operate', align: 'center', width: 220 },
|
||||
{ title: '事件描述', field: 'describe', align: 'center', showOverflow: true,minWidth: 200 },
|
||||
{ title: '事件类型', field: 'type', align: 'center', width: 160 },
|
||||
{ title: '操作结果', field: 'type', align: 'center', width: 100 },
|
||||
{ title: '操作IP', field: 'ip', align: 'center', width: 160 },
|
||||
{ title: '事件等级', field: 'level', align: 'center', width: 100 }
|
||||
]
|
||||
})
|
||||
tableStore.table.params.loginName = ''
|
||||
tableStore.table.params.operateType = ''
|
||||
tableStore.table.params.type = ''
|
||||
tableStore.table.params.pageSize = 100
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
// saveLogParam().then(res => {
|
||||
// console.log(res)
|
||||
// })
|
||||
|
||||
onMounted(() => {
|
||||
// tableStore.index()
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
</script>
|
||||
2739
src/views/pqs/device-boot/deviceter.vue
Normal file
2739
src/views/pqs/device-boot/deviceter.vue
Normal file
File diff suppressed because it is too large
Load Diff
11
src/views/pqs/largeScreen/index.vue
Normal file
11
src/views/pqs/largeScreen/index.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
|
||||
<div> </div>
|
||||
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { ref, reactive } from 'vue'
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
146
src/views/pqs/voltage/sags/operationsManagement/index.vue
Normal file
146
src/views/pqs/voltage/sags/operationsManagement/index.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker area>
|
||||
<template v-slot:select>
|
||||
|
||||
<el-form-item label="终端状态">
|
||||
<el-select
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
v-model="tableStore.table.params.runFlag"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option label="投运" value="0" />
|
||||
<el-option label="热备用" value="1" />
|
||||
<el-option label="停运" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯状态">
|
||||
<el-select
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
v-model="tableStore.table.params.comFlag"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option label="正常" value="1" />
|
||||
<el-option label="中断" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="厂家">
|
||||
<el-select
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
v-model="manufacturerForm"
|
||||
placeholder="请选择"
|
||||
@change="onManufacturerChange"
|
||||
>
|
||||
<el-option v-for="item in manufacturer" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model="tableStore.table.params.searchValue"
|
||||
placeholder="根据变电站,终端编号,型号或网络参数查询"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="tsx">
|
||||
import { ref, onMounted, provide, reactive } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import Area from '@/components/form/area/index.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'voltage/sags/operationsManagement/index'
|
||||
})
|
||||
const dictData = useDictData()
|
||||
const manufacturer = dictData.getBasicData('Dev_Manufacturers')
|
||||
const manufacturerForm = ref<string[]>([])
|
||||
const tableStore = new TableStore({
|
||||
isWebPaging: true,
|
||||
url: '/device-boot/runManage/getRuntimeData',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '序号', type: 'seq', align: 'center', width: 60 },
|
||||
{ title: '区域', field: 'areaName', align: 'center', width: 120 },
|
||||
{ title: '供电公司', field: 'gdName', align: 'center', width: 120 },
|
||||
{ title: '变电站', field: 'bdName', align: 'center', showOverflow: true, minWidth: 100 },
|
||||
{ title: '终端编号', field: 'devName', align: 'center', width: 160 },
|
||||
{ title: '投运时间', field: 'loginTime', align: 'center', width: 200 },
|
||||
{ title: '厂家', field: 'manufacturer', align: 'center', width: 160 },
|
||||
{ title: '型号', field: 'devType', align: 'center', width: 200 },
|
||||
{ title: '网络参数', field: 'ip', align: 'center', width: 200 },
|
||||
{ title: '端口', field: 'port', align: 'center', width: 100 },
|
||||
{ title: '终端状态', field: 'runFlag', align: 'center', width: 100 },
|
||||
{ title: '通讯状态', field: 'comFlag', align: 'center', width: 100 },
|
||||
{ title: '最新数据', field: 'updateTime', align: 'center', width: 200 },
|
||||
{
|
||||
title: '评价',
|
||||
field: 'onlineEvaluate',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render: 'customRender',
|
||||
customRender: props => {
|
||||
if (props.renderValue == null) {
|
||||
return <span></span>
|
||||
} else if (props.renderValue * 100 > 90) {
|
||||
return (
|
||||
<el-tag effect="dark" type="success">
|
||||
优
|
||||
</el-tag>
|
||||
)
|
||||
} else if (props.renderValue * 100 > 60) {
|
||||
return (
|
||||
<el-tag effect="dark" type="warning">
|
||||
良
|
||||
</el-tag>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<el-tag effect="dark" type="danger">
|
||||
差
|
||||
</el-tag>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
resetCallback: () => {
|
||||
manufacturerForm.value = []
|
||||
}
|
||||
})
|
||||
tableStore.table.params.runFlag = []
|
||||
tableStore.table.params.comFlag = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.statisticalType = {}
|
||||
tableStore.table.params.serverName = 'event-boot'
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
|
||||
const onManufacturerChange = () => {
|
||||
tableStore.table.params.manufacturer = manufacturer
|
||||
.filter(item => {
|
||||
return manufacturerForm.value.includes(item.id)
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
...item,
|
||||
label: item.name,
|
||||
value: item.id
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
175
src/views/pqs/voltage/sags/operationsManagement/point.vue
Normal file
175
src/views/pqs/voltage/sags/operationsManagement/point.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker area>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
v-model="interferenceSourceForm"
|
||||
placeholder="请选择"
|
||||
@change="onLoadTypeChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in interferenceSource"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
v-model="scaleForm"
|
||||
placeholder="请选择"
|
||||
@change="onScaleChange"
|
||||
>
|
||||
<el-option v-for="item in level" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯状态">
|
||||
<el-select
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
v-model="tableStore.table.params.comFlag"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option label="正常" value="1" />
|
||||
<el-option label="中断" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model="tableStore.table.params.searchValue"
|
||||
placeholder="根据变电站,终端编号,型号或网络参数查询"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table isGroup ref="tableRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="tsx">
|
||||
import { ref, onMounted, provide, reactive } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import Area from '@/components/form/area/index.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'voltage/sags/operationsManagement/point'
|
||||
})
|
||||
const dictData = useDictData()
|
||||
const interferenceSource = dictData.getBasicData('Interference_Source')
|
||||
const level = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
const interferenceSourceForm = ref<string[]>([])
|
||||
const scaleForm = ref<string[]>([])
|
||||
const tableStore = new TableStore({
|
||||
isWebPaging: true,
|
||||
url: '/device-boot/runManage/getLineLedger',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ field: 'areaName', title: '省公司', width: 120 },
|
||||
{ field: 'gdName', title: '市公司', width: 120 },
|
||||
{ field: 'scale', title: '监测点电压等级', width: 150 },
|
||||
{ field: 'lineName', title: '监测点名称', width: 120 },
|
||||
{ field: 'bdName', title: '所属变电站', width: 120 },
|
||||
{ field: 'loadType', title: '干扰源类型', width: 120 },
|
||||
{ field: 'objName', title: '监测对象名称', width: 180 },
|
||||
{ field: 'shortCapacity', title: '最小短路容量(MVA)', width: 190 },
|
||||
{ field: 'devCapacity', title: '供电设备容量(MVA )', width: 190 },
|
||||
{ field: 'dealCapacity', title: '用户协议容量(MVA)', width: 190 },
|
||||
{ field: 'comFlag', title: '通讯状态 ', width: 120 },
|
||||
{ field: 'id', title: '监测点序号', width: 120 },
|
||||
{ field: 'devName', title: '监测终端编号 ', width: 140 },
|
||||
{ field: 'ptType', title: '监测终端接线方式', width: 160 },
|
||||
{ field: 'voltageDev', title: '电压偏差上限(%)', width: 160 },
|
||||
{ field: 'uvoltageDev', title: '电压偏差下限(%)', width: 160 },
|
||||
{
|
||||
field: 'limitValue',
|
||||
title: '限值',
|
||||
children: [
|
||||
{ field: 'freqDev', title: '频率(Hz)', width: 120 },
|
||||
{ field: 'ubalance', title: '三相电压不平衡度(%)', width: 190 },
|
||||
{ field: 'ineg', title: '负序电流(A)', width: 120 },
|
||||
{ field: 'flicker', title: '长时间闪变', width: 120 },
|
||||
{ field: 'uaberrance', title: '电压总谐波畸变率(%)', width: 190 },
|
||||
{ field: 'oddHarm', title: '奇数次谐波电压(%)', width: 180 },
|
||||
{ field: 'evenHarm', title: '偶数次谐波电压(%)', width: 180 }
|
||||
]
|
||||
},
|
||||
{
|
||||
field: 'evaluate',
|
||||
title: '电流限值',
|
||||
children: [
|
||||
{ field: 'iharm2', title: '2次谐波(A)', width: 120 },
|
||||
{ field: 'iharm3', title: '3次谐波(A)', width: 120 },
|
||||
{ field: 'iharm4', title: '4次谐波(A)', width: 120 },
|
||||
{ field: 'iharm5', title: '5次谐波(A)', width: 120 },
|
||||
{ field: 'iharm6', title: '6次谐波(A)', width: 120 },
|
||||
{ field: 'iharm7', title: '7次谐波(A)', width: 120 },
|
||||
{ field: 'iharm8', title: '8次谐波(A)', width: 120 },
|
||||
{ field: 'iharm9', title: '9次谐波(A)', width: 120 },
|
||||
{ field: 'iharm10', title: '10次谐波(A)', width: 140 },
|
||||
{ field: 'iharm11', title: '11次谐波(A)', width: 140 },
|
||||
{ field: 'iharm12', title: '12次谐波(A)', width: 140 },
|
||||
{ field: 'iharm13', title: '13次谐波(A)', width: 140 },
|
||||
{ field: 'iharm14', title: '14次谐波(A)', width: 140 },
|
||||
{ field: 'iharm15', title: '15次谐波(A)', width: 140 },
|
||||
{ field: 'iharm16', title: '16次谐波(A)', width: 140 },
|
||||
{ field: 'iharm17', title: '17次谐波(A)', width: 140 },
|
||||
{ field: 'iharm18', title: '18次谐波(A)', width: 140 },
|
||||
{ field: 'iharm19', title: '19次谐波(A)', width: 140 },
|
||||
{ field: 'iharm10', title: '20次谐波(A)', width: 140 },
|
||||
{ field: 'iharm21', title: '21次谐波(A)', width: 140 },
|
||||
{ field: 'iharm22', title: '22次谐波(A)', width: 140 },
|
||||
{ field: 'iharm23', title: '23次谐波(A)', width: 140 },
|
||||
{ field: 'iharm24', title: '24次谐波(A)', width: 140 },
|
||||
{ field: 'iharm25', title: '25次谐波(A)', width: 140 },
|
||||
{ field: 'inUharm', title: '0.5-1.5次间谐波(A)', width: 180 },
|
||||
{ field: 'inUharm16', title: '2.5-15.5次间谐波(A)', width: 190 }
|
||||
]
|
||||
}
|
||||
],
|
||||
resetCallback: () => {
|
||||
interferenceSourceForm.value = []
|
||||
scaleForm.value = []
|
||||
}
|
||||
})
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.comFlag = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.statisticalType = {}
|
||||
tableStore.table.params.serverName = 'event-boot'
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
|
||||
const onLoadTypeChange = () => {
|
||||
tableStore.table.params.loadType = interferenceSource
|
||||
.filter(item => {
|
||||
return interferenceSourceForm.value.includes(item.id)
|
||||
})
|
||||
.map(item => {
|
||||
return { ...item, label: item.name, value: item.id }
|
||||
})
|
||||
}
|
||||
const onScaleChange = () => {
|
||||
tableStore.table.params.scale = level
|
||||
.filter(item => {
|
||||
return scaleForm.value.includes(item.id)
|
||||
})
|
||||
.map(item => {
|
||||
return { ...item, label: item.name, value: item.id }
|
||||
})
|
||||
}
|
||||
</script>
|
||||
416
src/views/pqs/voltage/sags/operationsManagement/statistics.vue
Normal file
416
src/views/pqs/voltage/sags/operationsManagement/statistics.vue
Normal file
@@ -0,0 +1,416 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker >
|
||||
<template v-slot:select>
|
||||
<el-form-item label="区域">
|
||||
<Area v-model="tableStore.table.params.deptIndex" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<div style="font-weight: bold; background: #fff; text-indent: 1em">
|
||||
<span style="color: #000">
|
||||
(左柱):
|
||||
<span style="color: #0099cc">
|
||||
<span class="smallBlock" style="background: #0099cc"></span>
|
||||
投运
|
||||
</span>
|
||||
<span style="color: #996600">
|
||||
<span class="smallBlock" style="background: #996600"></span>
|
||||
热备用
|
||||
</span>
|
||||
<span style="color: #cc0000">
|
||||
<span class="smallBlock" style="background: #cc0000"></span>
|
||||
停运
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span style="color: #000">
|
||||
(右柱):
|
||||
<span style="color: #2e8b57">
|
||||
<span class="smallBlock" style="background: #2e8b57"></span>
|
||||
{{ '在线率≥90 %' }}
|
||||
</span>
|
||||
<span style="color: #daa520">
|
||||
<span class="smallBlock" style="background: #daa520"></span>
|
||||
{{ '60 %≤在线率 < 90 %' }}
|
||||
</span>
|
||||
<span style="color: #cc0000">
|
||||
<span class="smallBlock" style="background: #cc0000"></span>
|
||||
{{ '在线率 < 60 %' }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="statistics-main" v-loading="tableStore.table.loading">
|
||||
<template v-if="!tableStore.table.loading">
|
||||
<div>
|
||||
<my-echart :options="areaStatistics" />
|
||||
</div>
|
||||
<div>
|
||||
<vxe-table
|
||||
height="auto"
|
||||
auto-resize
|
||||
:data="tableStore.table.data.area.areaInfo"
|
||||
v-bind="defaultAttribute"
|
||||
>
|
||||
<vxe-column field="areaName" title="区域"></vxe-column>
|
||||
<vxe-column field="numberOfTerminals" title="终端个数" width="80"></vxe-column>
|
||||
<vxe-column field="normal" title="投运" width="80"></vxe-column>
|
||||
<vxe-column field="breaks" title="热备用" width="80"></vxe-column>
|
||||
<vxe-column field="shutdown" title="停运" width="80"></vxe-column>
|
||||
<vxe-column field="onlineRate" title="在线率(%)">
|
||||
<template v-slot:default="scoped">
|
||||
{{ scoped.row.onlineRate === 3.14159 ? '/' : scoped.row.onlineRate }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
<div>
|
||||
<my-echart :options="factoryStatistics" />
|
||||
</div>
|
||||
<div>
|
||||
<vxe-table
|
||||
height="auto"
|
||||
auto-resize
|
||||
:data="tableStore.table.data.factory.areaInfo"
|
||||
v-bind="defaultAttribute"
|
||||
>
|
||||
<vxe-column field="areaName" title="厂家"></vxe-column>
|
||||
<vxe-column field="numberOfTerminals" title="终端个数" width="80"></vxe-column>
|
||||
<vxe-column field="normal" title="投运" width="80"></vxe-column>
|
||||
<vxe-column field="breaks" title="热备用" width="80"></vxe-column>
|
||||
<vxe-column field="shutdown" title="停运" width="80"></vxe-column>
|
||||
<vxe-column field="onlineRate" title="在线率(%)">
|
||||
<template v-slot:default="scoped">
|
||||
{{ scoped.row.onlineRate === 3.14159 ? '/' : scoped.row.onlineRate }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import Area from '@/components/form/area/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { onMounted, provide, reactive, ref } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import * as echarts from 'echarts/core'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
|
||||
defineOptions({
|
||||
name: 'voltage/sags/operationsManagement/statistics'
|
||||
})
|
||||
const dictData = useDictData()
|
||||
const areaStatistics = ref()
|
||||
const factoryStatistics = ref()
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/area/getTerminalRunningStatistics',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
loadCallback: () => {
|
||||
areaStatistics.value = {
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
title: {
|
||||
text: '区域'
|
||||
},
|
||||
xAxis: {
|
||||
data: tableStore.table.data.area.areaInfo.map(
|
||||
(item: any) => item.areaName + `(${item.numberOfTerminals})`
|
||||
)
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params:any) {
|
||||
var tips = ''
|
||||
tips += params[0].name + '</br/>'
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
if (params[i].value == 3.14159) {
|
||||
tips += params[i].seriesName + ':暂无数据<br/>'
|
||||
} else {
|
||||
tips += params[i].seriesName + ':' + params[i].value + '%<br/>'
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
yAxis: { name: '%' },
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
stack: 'one',
|
||||
name: '投运',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
data: tableStore.table.data.area.areaInfo.map((item: any) => item.normalRate),
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value != 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#0099CC'
|
||||
}
|
||||
])
|
||||
} else if ((params.value = 3.14159)) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ccc'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
type: 'bar'
|
||||
},
|
||||
{
|
||||
name: '热备用',
|
||||
stack: 'one',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
data: tableStore.table.data.area.areaInfo.map((item: any) => item.shutdownRate),
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value != 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#cc0000'
|
||||
}
|
||||
])
|
||||
} else if ((params.value = 3.14159)) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ccc'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '在线率',
|
||||
stack: 'two',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
data: tableStore.table.data.area.areaInfo.map((item: any) => item.onlineRate),
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value >= 90) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#339966'
|
||||
}
|
||||
])
|
||||
} else if (params.value >= 60 && params.value <= 90) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FFCC33'
|
||||
}
|
||||
])
|
||||
} else if (params.value <= 60 && params.value != 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#CC0000'
|
||||
}
|
||||
])
|
||||
} else if ((params.value = 3.14159)) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ccc'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
type: 'bar'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
factoryStatistics.value = {
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
title: {
|
||||
text: '终端厂家'
|
||||
},
|
||||
xAxis: {
|
||||
data: tableStore.table.data.factory.areaInfo.map(
|
||||
(item: any) => item.areaName + `(${item.numberOfTerminals})`
|
||||
)
|
||||
},
|
||||
yAxis: {
|
||||
name: '%'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
var tips = ''
|
||||
tips += params[0].name + '</br/>'
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
if (params[i].value == 3.14159) {
|
||||
tips += params[i].seriesName + ':暂无数据<br/>'
|
||||
} else {
|
||||
tips += params[i].seriesName + ':' + params[i].value + '%<br/>'
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
stack: 'one',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
name: '投运',
|
||||
data: tableStore.table.data.factory.areaInfo.map((item: any) => item.normalRate),
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value != 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#0099CC'
|
||||
}
|
||||
])
|
||||
} else if ((params.value = 3.14159)) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ccc'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
type: 'bar'
|
||||
},
|
||||
{
|
||||
name: '热备用',
|
||||
stack: 'one',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
data: tableStore.table.data.factory.areaInfo.map((item: any) => item.shutdownRate),
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value != 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#cc0000'
|
||||
}
|
||||
])
|
||||
} else if ((params.value = 3.14159)) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ccc'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '在线率',
|
||||
stack: 'two',
|
||||
barMaxWidth: 30,
|
||||
barMinHeight: 5,
|
||||
data: tableStore.table.data.factory.areaInfo.map((item: any) => item.onlineRate),
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
if (params.value >= 90) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#339966'
|
||||
}
|
||||
])
|
||||
} else if (params.value >= 60 && params.value <= 90) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FFCC33'
|
||||
}
|
||||
])
|
||||
} else if (params.value <= 60 && params.value != 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#CC0000'
|
||||
}
|
||||
])
|
||||
} else if ((params.value = 3.14159)) {
|
||||
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ccc'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
type: 'bar'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.deptIndex = dictData.state.area[0].id
|
||||
tableStore.table.params.serverName = 'event-boot'
|
||||
tableStore.table.params.monitorFlag = 2
|
||||
tableStore.table.params.powerFlag = 2
|
||||
tableStore.table.params.statisticalType = {
|
||||
name: '电网拓扑',
|
||||
id: 'cc28974d259ad22642f6a1bff708f967',
|
||||
code: 'Power_Network',
|
||||
value: 'cc28974d259ad22642f6a1bff708f967',
|
||||
gvalue: null,
|
||||
label: '电网拓扑',
|
||||
sort: 0
|
||||
}
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const layout = mainHeight(104) as any
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.statistics-main {
|
||||
box-sizing: border-box;
|
||||
height: v-bind('layout.height');
|
||||
padding: 0 10px 10px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 600px;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
|
||||
}
|
||||
</style>
|
||||
161
src/views/pqs/voltageSags/analyse/eventCorrelation/index.vue
Normal file
161
src/views/pqs/voltageSags/analyse/eventCorrelation/index.vue
Normal file
@@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker>
|
||||
<template #select>
|
||||
<el-form-item label="筛选">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Tickets" type="primary" @click="analysis">分析记录管理</el-button>
|
||||
<el-button icon="el-icon-SuccessFilled" type="primary" @click="firing">启动关联分析</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" />
|
||||
<!-- 分析记录管理 -->
|
||||
<el-dialog v-model="dialogAnalysis" title="分析记录管理" width="60%">
|
||||
<vxe-table height="500" auto-resize :data="AnalysisData" v-bind="defaultAttribute">
|
||||
<vxe-column field="timeId" title="策略名称"></vxe-column>
|
||||
<vxe-column field="timeId" title="操作时间"></vxe-column>
|
||||
<vxe-column field="createName" title="操作人"></vxe-column>
|
||||
<vxe-column title="操作" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-popconfirm title="是否确认删除策略!" @confirm="details(row)">
|
||||
<template #reference>
|
||||
<el-button type="danger" link>删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { queryRelevantLogPage, delRelevantLog } from '@/api/advance-boot/analyse.ts'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
defineOptions({
|
||||
name: 'govern/log/operation'
|
||||
})
|
||||
const dialogAnalysis = ref(false)
|
||||
const AnalysisData = ref([])
|
||||
const tableStore = new TableStore({
|
||||
url: '/advance-boot/process/querySagEventsPage',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{
|
||||
field: 'index',
|
||||
title: '序号',
|
||||
width: '60',
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ field: 'startTime', title: '发生时间' },
|
||||
{ field: 'duration', title: '持续时间(s)' },
|
||||
{
|
||||
field: 'featureAmplitude',
|
||||
title: '暂降(骤升)幅值(%)'
|
||||
},
|
||||
{ field: 'gdName', title: '供电公司' },
|
||||
{ field: 'subName', title: '变电站' },
|
||||
{ field: 'lineName', title: '监测点' },
|
||||
{
|
||||
field: 'dealFlag',
|
||||
title: '暂降特征幅值计算',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
0: 'warning',
|
||||
1: 'success',
|
||||
2: 'success',
|
||||
3: 'warning'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '未处理',
|
||||
1: '已处理',
|
||||
2: '已处理,无结果',
|
||||
3: '计算失败'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'fileFlag',
|
||||
title: '录波文件',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
0: 'warning',
|
||||
1: 'success'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '不存在',
|
||||
1: '存在'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: '120',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
title: '波形分析',
|
||||
type: 'primary',
|
||||
disabled: row => {
|
||||
return row.fileFlag == 0
|
||||
},
|
||||
icon: 'el-icon-Plus',
|
||||
render: 'basicButton',
|
||||
click: row => {}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '暂无波形',
|
||||
type: '',
|
||||
disabled: row => {
|
||||
return row.fileFlag == 1
|
||||
},
|
||||
icon: 'el-icon-Plus',
|
||||
render: 'basicButton'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.failReason = item.failReason || '/'
|
||||
item.result = item.result === 1 ? '成功' : '失败'
|
||||
item.loginName = item.loginName || '/'
|
||||
})
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
//分析记录管理
|
||||
const analysis = () => {
|
||||
queryRelevantLogPage({}).then((res: any) => {
|
||||
AnalysisData.value = res.data.records
|
||||
})
|
||||
dialogAnalysis.value = true
|
||||
}
|
||||
// 启动关联分析
|
||||
const firing = () => {}
|
||||
// 删除策略
|
||||
const details = (row: any) => {
|
||||
delRelevantLog({ id: row.id }).then((res: any) => {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: res.message
|
||||
})
|
||||
queryRelevantLogPage({}).then((res: any) => {
|
||||
AnalysisData.value = res.data.records
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div>3</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
156
src/views/pqs/voltageSags/analyse/impactscope/index.vue
Normal file
156
src/views/pqs/voltageSags/analyse/impactscope/index.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker ref="TableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="筛选">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" />
|
||||
<!-- 分析记录管理 -->
|
||||
<el-dialog v-model="dialogAnalysis" title="分析记录管理" width="60%">
|
||||
<vxe-table height="500" auto-resize :data="AnalysisData" v-bind="defaultAttribute">
|
||||
<vxe-column field="timeId" title="策略名称"></vxe-column>
|
||||
<vxe-column field="timeId" title="操作时间"></vxe-column>
|
||||
<vxe-column field="createName" title="操作人"></vxe-column>
|
||||
<vxe-column title="操作" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-popconfirm title="是否确认删除策略!" @confirm="details(row)">
|
||||
<template #reference>
|
||||
<el-button type="danger" link>删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { queryRelevantLogPage, delRelevantLog } from '@/api/advance-boot/analyse.ts'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { queryEventsAssPage } from '@/api/advance-boot/analyse.ts'
|
||||
defineOptions({
|
||||
name: 'govern/log/operation'
|
||||
})
|
||||
const dialogAnalysis = ref(false)
|
||||
const AnalysisData = ref([])
|
||||
const tableRef = ref()
|
||||
const TableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
url: '/advance-boot/process/queryEventsAssPage',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{
|
||||
field: 'index',
|
||||
title: '序号',
|
||||
width: '60',
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ field: 'timeId', title: '时间', width: '200' },
|
||||
{ field: 'timeId', title: '事件关联分析名称', width: '200' },
|
||||
{
|
||||
field: 'contentDes',
|
||||
title: '事件关联分析描述'
|
||||
},
|
||||
|
||||
{
|
||||
title: '操作',
|
||||
width: '200',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
title: '暂降源定位',
|
||||
type: 'primary',
|
||||
|
||||
icon: 'el-icon-Plus',
|
||||
render: 'basicButton',
|
||||
click: row => {}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '范围查看',
|
||||
type: 'primary',
|
||||
|
||||
icon: 'el-icon-Plus',
|
||||
render: 'basicButton'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.failReason = item.failReason || '/'
|
||||
item.result = item.result === 1 ? '成功' : '失败'
|
||||
item.loginName = item.loginName || '/'
|
||||
})
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
TableHeaderRef.value.setDatePicker([
|
||||
{ label: '年份', value: 1 },
|
||||
{ label: '季度', value: 2 },
|
||||
{ label: '月份', value: 3 },
|
||||
{ label: '周', value: 4 }
|
||||
])
|
||||
})
|
||||
//分析记录管理
|
||||
const analysis = () => {
|
||||
queryRelevantLogPage({}).then((res: any) => {
|
||||
AnalysisData.value = res.data.records
|
||||
})
|
||||
dialogAnalysis.value = true
|
||||
}
|
||||
// 启动关联分析
|
||||
const firing = () => {}
|
||||
// 删除策略
|
||||
const details = (row: any) => {
|
||||
delRelevantLog({ id: row.id }).then((res: any) => {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: res.message
|
||||
})
|
||||
queryRelevantLogPage({}).then((res: any) => {
|
||||
AnalysisData.value = res.data.records
|
||||
})
|
||||
})
|
||||
}
|
||||
// 导出
|
||||
const exportEvent = () => {
|
||||
console.log('🚀 ~ exportEvent ~ tableRef.value:', tableRef.value)
|
||||
|
||||
queryEventsAssPage({
|
||||
searchBeginTime: tableStore.table.params.searchBeginTime,
|
||||
searchEndTime: tableStore.table.params.searchEndTime,
|
||||
searchValue: tableStore.table.params.searchValue,
|
||||
pageNum: 1,
|
||||
pageSize: tableStore.table.params.total
|
||||
}).then(res => {
|
||||
tableRef.value.getRef().exportData({
|
||||
filename: '影响范围分析', // 文件名字
|
||||
sheetName: 'Sheet1',
|
||||
type: 'xlsx', //导出文件类型 xlsx 和 csv
|
||||
useStyle: true,
|
||||
data: res.data.records, // 数据源 // 过滤那个字段导出
|
||||
columnFilterMethod: function (column, $columnIndex) {
|
||||
return !(column.$columnIndex === 0)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,351 @@
|
||||
<template>
|
||||
<div style='display: flex;flex-direction: column;height: 100%' v-loading='loading'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-descriptions
|
||||
class='mt2'
|
||||
direction='vertical'
|
||||
:column='4'
|
||||
border
|
||||
>
|
||||
<el-descriptions-item align='center' label='名称'>{{ data.name }}</el-descriptions-item>
|
||||
<el-descriptions-item align='center' label='事件总数'>{{ data.gs }}</el-descriptions-item>
|
||||
<el-descriptions-item align='center' label='可容忍'>{{ data.krr }}</el-descriptions-item>
|
||||
<el-descriptions-item align='center' label='不可容忍'> {{ data.bkrr }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div style='flex: 1;' class='mt10'>
|
||||
<my-echart :options='options' />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { getPlot } from '@/api/event-boot/monitor'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const loading = ref(true)
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const formData = reactive({
|
||||
lineIndex: monitoringPoint.state.lineId,
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const data = reactive({
|
||||
name: '事件个数',
|
||||
gs: 0,
|
||||
krr: 0,
|
||||
bkrr: 0
|
||||
})
|
||||
const options = ref({})
|
||||
|
||||
const init = () => {
|
||||
loading.value = true
|
||||
formData.startTime = datePickerRef.value.timeValue[0]
|
||||
formData.endTime = datePickerRef.value.timeValue[1]
|
||||
getPlot(formData).then(
|
||||
(res: any) => {
|
||||
const gongData = gongfunction(res.data.voltageToleranceCurveDataList)
|
||||
data.gs = res.data.voltageToleranceCurveDataList.length
|
||||
data.krr = gongData.pointI.length
|
||||
data.bkrr = gongData.pointIun.length
|
||||
console.log(gongData)
|
||||
options.value = {
|
||||
// backgroundColor: "#f9f9f9", //地图背景色深蓝
|
||||
title: {
|
||||
// text: `ITIC曲线(总统计:${gongData.pointI.length + gongData.pointIun.length}个,可容忍:${gongData.pointI.length}个,不可容忍:${gongData.pointIun.length}个)`
|
||||
text: `ITIC曲线`
|
||||
},
|
||||
legend: {
|
||||
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
|
||||
x: 'left'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
show: true,
|
||||
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,
|
||||
formatter: function(a: any) {
|
||||
var relVal = ''
|
||||
relVal =
|
||||
'<font style=\'color:' +
|
||||
'\'>发生时间:' +
|
||||
a.value[2] +
|
||||
'</font><br/>'
|
||||
relVal +=
|
||||
'<font style=\'color:' +
|
||||
'\'>持续时间:' +
|
||||
a.value[0] +
|
||||
's</font><br/>'
|
||||
relVal +=
|
||||
'<font style=\'color:' +
|
||||
'\'>特征幅值:' +
|
||||
a.value[1].toFixed(2) +
|
||||
'%</font>'
|
||||
return relVal
|
||||
}
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'log',
|
||||
min: 0.001,
|
||||
max: 1000,
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
name: 's'
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
splitNumber: 10,
|
||||
minInterval: 3,
|
||||
name: '%'
|
||||
}
|
||||
],
|
||||
options: {
|
||||
dataZoom: null,
|
||||
series: [
|
||||
{
|
||||
name: '上限',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.001, 200],
|
||||
[0.003, 140],
|
||||
[0.003, 120],
|
||||
[0.5, 120],
|
||||
[0.5, 110],
|
||||
[10, 110],
|
||||
[1000, 110]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '下限',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.02, 0],
|
||||
[0.02, 70],
|
||||
[0.5, 70],
|
||||
[0.5, 80],
|
||||
[10, 80],
|
||||
[10, 90],
|
||||
[1000, 90]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: gongData.pointI
|
||||
},
|
||||
{
|
||||
name: '不可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: gongData.pointIun
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
nextTick(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function gongfunction(arr: any) {
|
||||
let standI = 0
|
||||
let unstandI = 0
|
||||
let standF = 0
|
||||
let unstandF = 0
|
||||
let total = 0
|
||||
let pointIun = []
|
||||
let pointI = []
|
||||
let pointF = []
|
||||
let pointFun = []
|
||||
total = arr.length
|
||||
if (total == 0) {
|
||||
} else {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let point = []
|
||||
let xx = arr[i].persistTime
|
||||
let yy = arr[i].eventValue
|
||||
let time = arr[i].time
|
||||
let eventId = arr[i].eventId
|
||||
// let index =arr[i].eventDetailIndex;
|
||||
point = [xx, yy, time, eventId]
|
||||
|
||||
if (xx <= 0.003) {
|
||||
let line = 0
|
||||
line = 250 - 30000 * xx
|
||||
if (yy > line) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.02) {
|
||||
if (yy > 120) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.5) {
|
||||
if (yy > 120 || yy < 70) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 10) {
|
||||
if (yy > 110 || yy < 80) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 110 || yy < 90) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (xx < 0.05) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else if (xx < 0.2) {
|
||||
if (yy > 50) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
} else if (xx < 0.5) {
|
||||
if (yy > 70) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 80) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
standI,
|
||||
unstandI,
|
||||
pointI,
|
||||
pointIun,
|
||||
standF,
|
||||
unstandF,
|
||||
pointF,
|
||||
pointFun
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
<style></style>
|
||||
@@ -0,0 +1,337 @@
|
||||
<template>
|
||||
<div style='display: flex;flex-direction: column;height: 100%'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-descriptions
|
||||
class='mt2'
|
||||
direction='vertical'
|
||||
:column='4'
|
||||
border
|
||||
>
|
||||
<el-descriptions-item align='center' label='名称'>{{ data.name }}</el-descriptions-item>
|
||||
<el-descriptions-item align='center' label='事件总数'>{{ data.gs }}</el-descriptions-item>
|
||||
<el-descriptions-item align='center' label='可容忍'>{{ data.krr }}</el-descriptions-item>
|
||||
<el-descriptions-item align='center' label='不可容忍'> {{ data.bkrr }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div style='flex: 1;' class='mt10'>
|
||||
<my-echart :options='options' />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { getPlot } from '@/api/event-boot/monitor'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const loading = ref(true)
|
||||
const formData = reactive({
|
||||
lineIndex: monitoringPoint.state.lineId,
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const data = reactive({
|
||||
name: '事件个数',
|
||||
gs: 0,
|
||||
krr: 0,
|
||||
bkrr: 0
|
||||
})
|
||||
const options = ref({})
|
||||
|
||||
const init = () => {
|
||||
loading.value = true
|
||||
formData.startTime = datePickerRef.value.timeValue[0]
|
||||
formData.endTime = datePickerRef.value.timeValue[1]
|
||||
getPlot(formData).then(
|
||||
(res: any) => {
|
||||
const gongData = gongfunction(res.data.voltageToleranceCurveDataList)
|
||||
data.gs = res.data.voltageToleranceCurveDataList.length
|
||||
data.krr = gongData.pointI.length
|
||||
data.bkrr = gongData.pointIun.length
|
||||
console.log(gongData)
|
||||
options.value = {
|
||||
// backgroundColor: "#f9f9f9", //地图背景色深蓝
|
||||
title: {
|
||||
text: `SEMI F47曲线`
|
||||
},
|
||||
legend: {
|
||||
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
|
||||
x: 'left'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
show: true,
|
||||
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,
|
||||
formatter: function(a: any) {
|
||||
var relVal = ''
|
||||
relVal =
|
||||
'<font style=\'color:' +
|
||||
'\'>发生时间:' +
|
||||
a.value[2] +
|
||||
'</font><br/>'
|
||||
relVal +=
|
||||
'<font style=\'color:' +
|
||||
'\'>持续时间:' +
|
||||
a.value[0] +
|
||||
's</font><br/>'
|
||||
relVal +=
|
||||
'<font style=\'color:' +
|
||||
'\'>特征幅值:' +
|
||||
a.value[1].toFixed(2) +
|
||||
'%</font>'
|
||||
return relVal
|
||||
}
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'log',
|
||||
min: 0.001,
|
||||
max: 1000,
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
name: 's'
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
max: function(value: any) {
|
||||
return value.max + 20
|
||||
},
|
||||
splitNumber: 10,
|
||||
minInterval: 0.1,
|
||||
name: '%'
|
||||
}
|
||||
],
|
||||
options: {
|
||||
dataZoom: null,
|
||||
series: [
|
||||
{
|
||||
name: '边界线',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.05, 0],
|
||||
[0.05, 50],
|
||||
[0.2, 50],
|
||||
[0.2, 70],
|
||||
[0.5, 70],
|
||||
[0.5, 80],
|
||||
[10, 80],
|
||||
[1000, 80]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: gongData.pointI
|
||||
},
|
||||
{
|
||||
name: '不可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
data: gongData.pointIun
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
nextTick(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function gongfunction(arr: any) {
|
||||
let standI = 0
|
||||
let unstandI = 0
|
||||
let standF = 0
|
||||
let unstandF = 0
|
||||
let total = 0
|
||||
let pointIun = []
|
||||
let pointI = []
|
||||
let pointF = []
|
||||
let pointFun = []
|
||||
total = arr.length
|
||||
if (total == 0) {
|
||||
} else {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let point = []
|
||||
let xx = arr[i].persistTime
|
||||
let yy = arr[i].eventValue
|
||||
let time = arr[i].time
|
||||
let eventId = arr[i].eventId
|
||||
// let index =arr[i].eventDetailIndex;
|
||||
point = [xx, yy, time, eventId]
|
||||
|
||||
if (xx <= 0.003) {
|
||||
let line = 0
|
||||
line = 250 - 30000 * xx
|
||||
if (yy > line) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.02) {
|
||||
if (yy > 120) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.5) {
|
||||
if (yy > 120 || yy < 70) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 10) {
|
||||
if (yy > 110 || yy < 80) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 110 || yy < 90) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (xx < 0.05) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else if (xx < 0.2) {
|
||||
if (yy > 50) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
} else if (xx < 0.5) {
|
||||
if (yy > 70) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 80) {
|
||||
standF++
|
||||
pointF.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
} else {
|
||||
unstandF++
|
||||
pointFun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
standI,
|
||||
unstandI,
|
||||
pointI,
|
||||
pointIun,
|
||||
standF,
|
||||
unstandF,
|
||||
pointF,
|
||||
pointFun
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
<style></style>
|
||||
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div style='display: flex;flex-direction: column;height: 100%'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style='flex: 1;' class='mt10'>
|
||||
<my-echart :options='options' />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { getProbabilityDistribution } from '@/api/event-boot/monitor'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const loading = ref(true)
|
||||
const formData = reactive({
|
||||
lineIndex: monitoringPoint.state.lineId,
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const options = ref({})
|
||||
|
||||
const init = () => {
|
||||
loading.value = true
|
||||
formData.startTime = datePickerRef.value.timeValue[0]
|
||||
formData.endTime = datePickerRef.value.timeValue[1]
|
||||
getProbabilityDistribution(formData).then(
|
||||
(res: any) => {
|
||||
let data = res.data
|
||||
let sisttime = data.sisttime
|
||||
let persisttime = data.persisttime
|
||||
options.value = {
|
||||
backgroundColor: '#fff', //背景色,
|
||||
title: {
|
||||
text: '持续时间的概率分布函数',
|
||||
x: 'center'
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
left: 10,
|
||||
data: ['概率分布', '占比'],
|
||||
|
||||
textStyle: {
|
||||
rich: {
|
||||
a: {
|
||||
verticalAlign: 'middle'
|
||||
}
|
||||
},
|
||||
|
||||
padding: [2, 0, 0, 0] //[上、右、下、左]
|
||||
}
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
//提示框组件
|
||||
trigger: 'axis',
|
||||
|
||||
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
|
||||
},
|
||||
calculable: true,
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
name: '暂降幅值',
|
||||
nameGap: 10,
|
||||
nameTextStyle: {
|
||||
fontSize: 12
|
||||
},
|
||||
data: ['0.01', '0.1', '0.25', '0.5', '1', '3', '20', '60', '180']
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '概率分布',
|
||||
nameTextStyle: {
|
||||
fontSize: 15
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: '{value}%'
|
||||
},
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
// 使用深浅的间隔色
|
||||
type: 'dashed',
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '占比',
|
||||
|
||||
nameTextStyle: {
|
||||
fontSize: 15
|
||||
},
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: 'dashed',
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '概率分布',
|
||||
type: 'line',
|
||||
data: sisttime,
|
||||
itemStyle: {
|
||||
normal: { show: true }
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '占比',
|
||||
type: 'bar',
|
||||
data: persisttime,
|
||||
barWidth: 30,
|
||||
itemStyle: {
|
||||
normal: { show: true }
|
||||
}
|
||||
}
|
||||
],
|
||||
options: {
|
||||
dataZoom: null
|
||||
}
|
||||
}
|
||||
nextTick(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
<style></style>
|
||||
@@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<div v-loading='loading' class='dianyazanjiangbaojimidu'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class='mt10 dianyazanjiang'>
|
||||
<div class='first'>
|
||||
<div class='mb10'>DISDIP表格(国际发配电联盟UNIPEDE)</div>
|
||||
<div style='flex: 1;overflow: hidden'>
|
||||
<vxe-table v-bind='defaultAttribute' height='100%' size='mini' :data='firstData'>
|
||||
<vxe-colgroup title='剩余电压' field='name' width='80px'></vxe-colgroup>
|
||||
<vxe-colgroup title='持续事件'>
|
||||
<vxe-column field='twentyMs' title='20ms'></vxe-column>
|
||||
<vxe-column field='oneHundredMs' title='100ms'></vxe-column>
|
||||
<vxe-column field='fiveHundredMs' title='500ms'></vxe-column>
|
||||
<vxe-column field='oneS' title='1s'></vxe-column>
|
||||
<vxe-column field='threeS' title='2s'></vxe-column>
|
||||
<vxe-column field='twentyS' title='20s'></vxe-column>
|
||||
<vxe-column field='sixtyS' title='60s'></vxe-column>
|
||||
<vxe-column field='oneEightyS' title='180s'></vxe-column>
|
||||
</vxe-colgroup>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class='second'>
|
||||
<div class='mb10'>EC61000-4-11(用电终端的电压暂降抗度)</div>
|
||||
<div style='flex: 1;overflow: hidden'>
|
||||
<vxe-table v-bind='defaultAttribute' height='100%' size='mini' :data='secondData'>
|
||||
<vxe-colgroup title='剩余电压' field='name' width='80px'></vxe-colgroup>
|
||||
<vxe-colgroup title='持续事件'>
|
||||
<vxe-column field='tenTwentyMs' title='10-20ms'></vxe-column>
|
||||
<vxe-column field='twentyOneHundredMs' title='20-100ms'></vxe-column>
|
||||
<vxe-column field='zeroPiontOneTwoS' title='0.1-0.2s'></vxe-column>
|
||||
<vxe-column field='zeroPiontFive1S' title='0.2-0.5s'></vxe-column>
|
||||
<vxe-column field='zeroPiontTwoFiveS' title='0.5-1s'></vxe-column>
|
||||
<vxe-column field='role' title='>1s'></vxe-column>
|
||||
</vxe-colgroup>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class='third'>
|
||||
<div class='mb10'>IEC61000-2-8(公共用电暂降测量统计)</div>
|
||||
<div style='flex: 1;overflow: hidden'>
|
||||
<vxe-table v-bind='defaultAttribute' height='100%' size='mini' :data='thirdData'>
|
||||
<vxe-colgroup title='剩余电压' field='name' width='120px'></vxe-colgroup>
|
||||
<vxe-colgroup title='持续事件'>
|
||||
<vxe-column field='q' title='0.01-0.1s' align='center'></vxe-column>
|
||||
<vxe-column field='w' title='0.1-0.25s' align='center'></vxe-column>
|
||||
<vxe-column field='e' title='0.25-0.5s' align='center'></vxe-column>
|
||||
<vxe-column field='r' title='0.5-1s' align='center'></vxe-column>
|
||||
<vxe-column field='t' title='1-3s' align='center'></vxe-column>
|
||||
<vxe-column field='y' title='3-20s' align='center'></vxe-column>
|
||||
<vxe-column field='u' title='20-60s' align='center'></vxe-column>
|
||||
<vxe-column field='i' title='60-180s' align='center'></vxe-column>
|
||||
</vxe-colgroup>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class='charts' id='charts'>
|
||||
<MyEchart :options='options' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { eventDisdip, getCoords, IEC28, IEC411 } from '@/api/event-boot/monitor'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const loading = ref(true)
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const formData = reactive({
|
||||
lineIndex: monitoringPoint.state.lineId,
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const options = ref({})
|
||||
const firstData = ref([])
|
||||
const secondData = ref([])
|
||||
const thirdData = ref([])
|
||||
const chartsData = ref([])
|
||||
|
||||
const init = () => {
|
||||
formData.startTime = datePickerRef.value.timeValue[0]
|
||||
formData.endTime = datePickerRef.value.timeValue[1]
|
||||
loading.value = true
|
||||
Promise.all([eventDisdip(formData), IEC411(formData), IEC28(formData), getCoords(formData)]).then(res => {
|
||||
firstData.value = res[0].data
|
||||
secondData.value = res[1].data
|
||||
thirdData.value = res[2].data
|
||||
chartsData.value = res[3].data
|
||||
options.value = {
|
||||
options: {
|
||||
xAxis: null,
|
||||
yAxis: null,
|
||||
dataZoom: null,
|
||||
backgroundColor: '#fff',
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
title: {
|
||||
text: '暂降密度图',
|
||||
x: 'center'
|
||||
},
|
||||
toolbox: {
|
||||
show: true,
|
||||
feature: {
|
||||
// dataView: { show: true },
|
||||
// dataZoom: { show: true },
|
||||
//restore: { show: true },
|
||||
// saveAsImage: { show: true },
|
||||
myFull: {
|
||||
show: true,
|
||||
title: '全屏查看',
|
||||
icon: 'path://M432.45,595.444c0,2.177-4.661,6.82-11.305,6.82c-6.475,0-11.306-4.567-11.306-6.82s4.852-6.812,11.306-6.812C427.841,588.632,432.452,593.191,432.45,595.444L432.45,595.444z M421.155,589.876c-3.009,0-5.448,2.495-5.448,5.572s2.439,5.572,5.448,5.572c3.01,0,5.449-2.495,5.449-5.572C426.604,592.371,424.165,589.876,421.155,589.876L421.155,589.876z M421.146,591.891c-1.916,0-3.47,1.589-3.47,3.549c0,1.959,1.554,3.548,3.47,3.548s3.469-1.589,3.469-3.548C424.614,593.479,423.062,591.891,421.146,591.891L421.146,591.891zM421.146,591.891',
|
||||
onclick: () => {
|
||||
let element = document.getElementById('charts') as HTMLElement
|
||||
// 全屏,如果已经全屏,则退出全屏
|
||||
if (document.fullscreenElement) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen()
|
||||
}
|
||||
} else {
|
||||
if (element.requestFullscreen) {
|
||||
element.requestFullscreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
visualMap: {
|
||||
max: 20,
|
||||
show: false,
|
||||
inRange: {
|
||||
color: ['#313695', '#00BB00', '#ff8000', '#a50026']
|
||||
}
|
||||
},
|
||||
xAxis3D: {
|
||||
type: 'category',
|
||||
name: '剩余电压(%)',
|
||||
data: ['0-10', '10-20', '20-30', '30-40', '40-50', '50-60', '60-70', '70-80', '80-90', '90-100'],
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#111'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#111'
|
||||
}
|
||||
},
|
||||
yAxis3D: {
|
||||
type: 'category',
|
||||
name: '持续时间(cyc)',
|
||||
data: ['1cyc', '2cyc', '3cyc', '4cyc', '5cyc', '6~10cyc', '10~20cyc', '20~30cyc', '30~60cyc'],
|
||||
nameTextStyle: {
|
||||
color: '#111'
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#111'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#111'
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
// 使用深浅的间隔色
|
||||
color: ['#111'],
|
||||
type: 'dashed',
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
zAxis3D: {
|
||||
type: 'value',
|
||||
splitNumber: 10,
|
||||
minInterval: 10,
|
||||
name: '次数'
|
||||
},
|
||||
grid3D: {
|
||||
viewControl: {
|
||||
projection: 'perspective',
|
||||
distance: 250
|
||||
},
|
||||
boxWidth: 200,
|
||||
boxDepth: 80,
|
||||
light: {
|
||||
main: {
|
||||
intensity: 1.2
|
||||
},
|
||||
ambient: {
|
||||
intensity: 0.3
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'bar3D',
|
||||
data: chartsData.value.map(function(item: any) {
|
||||
return {
|
||||
value: [item['x'], item['y'], item['z']]
|
||||
}
|
||||
}),
|
||||
shading: 'realistic',
|
||||
label: {
|
||||
show: false,
|
||||
textStyle: {
|
||||
fontSize: 16,
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
|
||||
itemStyle: {
|
||||
opacity: 1
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
textStyle: {
|
||||
fontSize: 20,
|
||||
color: '#900'
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#900'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.dianyazanjiangbaojimidu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
|
||||
.dianyazanjiang {
|
||||
flex: 1;
|
||||
min-width: 1200px;
|
||||
min-height: 800px;
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
'first charts'
|
||||
'second charts'
|
||||
'third third '
|
||||
'third third ';
|
||||
grid-template-rows: 1fr 1fr 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
|
||||
.first {
|
||||
grid-area: first;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.second {
|
||||
grid-area: second;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.third {
|
||||
grid-area: third;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.charts {
|
||||
grid-area: charts;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-tabs v-model='activeName' type='border-card' class='event-statistics' tab-position='left' :style='height'>
|
||||
<el-tab-pane lazy label='ITIC曲线分析' name='1'>
|
||||
<ITICquxianfenxi />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label='SEMI F47 分析' name='2'>
|
||||
<SEMIF47fenxi />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label='电压暂降表及密度' name='3'>
|
||||
<Dianyazanjiangbiaojimidu />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label='暂降分布统计' name='4'>
|
||||
<Zanjiangfenbutongji />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label='暂降幅值概率分布' name='5'>
|
||||
<Zanjiangfuzhigailvfenbu />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label='持续时间概率分布' name='6'>
|
||||
<Chixushijiangailvfenbu />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { ref } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import ITICquxianfenxi from './ITICquxianfenxi/index.vue'
|
||||
import SEMIF47fenxi from './SEMIF47fenxi/index.vue'
|
||||
import Dianyazanjiangbiaojimidu from './dianyazanjiangbiaojimidu/index.vue'
|
||||
import Zanjiangfenbutongji from './zanjiangfenbutongji/index.vue'
|
||||
import Zanjiangfuzhigailvfenbu from './zanjiangfuzhigailvfenbu/index.vue'
|
||||
import Chixushijiangailvfenbu from './chixushijiangailvfenbu/index.vue'
|
||||
|
||||
const activeName = ref('1')
|
||||
const height = mainHeight(84)
|
||||
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.event-statistics {
|
||||
.el-tabs__header.is-left {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.el-tabs__content {
|
||||
height: 100%;
|
||||
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,324 @@
|
||||
<template>
|
||||
<div style='display: flex;flex-direction: column;height: 100%' v-loading='loading'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style='flex: 1;' class='mt10 zanjiangfenbutongji'>
|
||||
<my-echart :options='firstOptions' style='flex: 1;height: 100%' />
|
||||
<div style='width: 712px;height: 100%;display: flex;flex-direction: column'>
|
||||
<my-echart :options='secondOptions' style='flex: 1' />
|
||||
<my-echart :options='thirdOptions' style='flex: 1' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { getReasonTypeTime, getStatistic } from '@/api/event-boot/monitor'
|
||||
import { color } from '@/components/echarts/color'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const loading = ref(true)
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const formData = reactive({
|
||||
lineIndex: monitoringPoint.state.lineId,
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
flag: 1
|
||||
})
|
||||
const firstOptions = ref<any>({})
|
||||
const secondOptions = ref<any>({})
|
||||
const thirdOptions = ref<any>({})
|
||||
const firstData = ref<any>([])
|
||||
const secondData = ref<any>([])
|
||||
const thirdData = ref<any>([])
|
||||
|
||||
|
||||
const init = () => {
|
||||
|
||||
loading.value = true
|
||||
formData.startTime = datePickerRef.value.timeValue[0]
|
||||
formData.endTime = datePickerRef.value.timeValue[1]
|
||||
formData.flag = datePickerRef.value.interval
|
||||
Promise.all([getReasonTypeTime(formData), getStatistic(formData)]).then(res => {
|
||||
firstData.value = res[0].data
|
||||
secondData.value = res[1].data.reason
|
||||
thirdData.value = res[1].data.types
|
||||
initFirst()
|
||||
initSecond()
|
||||
initThird()
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
const initFirst = () => {
|
||||
let months = new Array()
|
||||
let handle = new Array()
|
||||
for (let i = 0; i < firstData.value.length; i++) {
|
||||
if ((firstData.value[i].month == '01') || (i == 0)) {
|
||||
if (formData.flag == 0) {
|
||||
months[i] = firstData.value[i].month
|
||||
} else {
|
||||
months[i] = firstData.value[i].month + '-' + firstData.value[i].day
|
||||
}
|
||||
} else {
|
||||
if (formData.flag == 0) {
|
||||
months[i] = firstData.value[i].month
|
||||
} else {
|
||||
months[i] = firstData.value[i].month + '-' + firstData.value[i].day
|
||||
}
|
||||
}
|
||||
handle[i] = firstData.value[i].times
|
||||
}
|
||||
|
||||
firstOptions.value = {
|
||||
backgroundColor: '#fff', //背景色,
|
||||
title: {
|
||||
text:
|
||||
formData.flag == 3
|
||||
? '月份统计'
|
||||
: formData.flag == 2
|
||||
? '季度统计'
|
||||
: formData.flag == 1
|
||||
? '年份统计'
|
||||
: '',
|
||||
x: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
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)',
|
||||
formatter: function(params: any) {
|
||||
let tips = ''
|
||||
tips += '<font>时间:' + params[0].name + '</font><br/>'
|
||||
tips += '<font>暂降次数:' + params[0].data + '</font>'
|
||||
return tips
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['暂降次数'],
|
||||
x: 'right'
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: months,
|
||||
name: '时间'
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '次',
|
||||
minInterval: 1
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '暂降次数',
|
||||
type: 'bar',
|
||||
barMinHeight: 10,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function(params: any) {
|
||||
if (params.data == 0) {
|
||||
return '#ccc'
|
||||
} else {
|
||||
return color[0]
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
label: { show: true, position: 'top' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: handle
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
const initSecond = () => {
|
||||
let reaArray = []
|
||||
let valueArray = []
|
||||
secondData.value.reverse()
|
||||
for (let i = 0; i < secondData.value.length; i++) {
|
||||
reaArray.push(secondData.value[i].reason)
|
||||
valueArray.push({
|
||||
name: secondData.value[i].reason,
|
||||
value: secondData.value[i].times
|
||||
})
|
||||
}
|
||||
secondOptions.value = {
|
||||
backgroundColor: '#fff', //背景色,
|
||||
animation: false,
|
||||
title: {
|
||||
text: '暂降原因',
|
||||
x: 'center'
|
||||
},
|
||||
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)',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: reaArray
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '暂降原因',
|
||||
type: 'pie',
|
||||
radius: '70%',
|
||||
center: ['50%', '53%'],
|
||||
label: {
|
||||
normal: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
lableLine: {
|
||||
normal: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: valueArray,
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
const initThird = () => {
|
||||
let typeArray = []
|
||||
let valueArray = []
|
||||
for (let i = 0; i < thirdData.value.length; i++) {
|
||||
typeArray.push(thirdData.value[i].type)
|
||||
valueArray.push({
|
||||
name: thirdData.value[i].type,
|
||||
value: thirdData.value[i].times
|
||||
}
|
||||
)
|
||||
}
|
||||
thirdOptions.value = {
|
||||
backgroundColor: '#fff', //背景色,
|
||||
animation: false,
|
||||
title: {
|
||||
text: '暂降类型',
|
||||
x: 'center'
|
||||
},
|
||||
|
||||
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)',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: typeArray
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '暂降类型',
|
||||
type: 'pie',
|
||||
radius: '70%',
|
||||
center: ['50%', '60%'],
|
||||
label: {
|
||||
normal: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
lableLine: {
|
||||
normal: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: valueArray,
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.zanjiangfenbutongji {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div style='display: flex;flex-direction: column;height: 100%'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style='flex: 1;' class='mt10'>
|
||||
<my-echart :options='options' />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { getProbabilityDistribution } from '@/api/event-boot/monitor'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const loading = ref(true)
|
||||
const formData = reactive({
|
||||
lineIndex: monitoringPoint.state.lineId,
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const options = ref({})
|
||||
|
||||
const init = () => {
|
||||
loading.value = true
|
||||
formData.startTime = datePickerRef.value.timeValue[0]
|
||||
formData.endTime = datePickerRef.value.timeValue[1]
|
||||
getProbabilityDistribution(formData).then(
|
||||
(res: any) => {
|
||||
let data = res.data
|
||||
let eventValue = data.eventvalue
|
||||
let pereventValue = data.pereventvalue
|
||||
options.value = {
|
||||
backgroundColor: '#fff', //背景色,
|
||||
title: {
|
||||
text: '暂降幅值的概率分布函数',
|
||||
x: 'center'
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
left: 10,
|
||||
data: ['概率分布', '占比'],
|
||||
|
||||
textStyle: {
|
||||
rich: {
|
||||
a: {
|
||||
verticalAlign: 'middle'
|
||||
}
|
||||
},
|
||||
|
||||
padding: [2, 0, 0, 0] //[上、右、下、左]
|
||||
}
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
//提示框组件
|
||||
trigger: 'axis',
|
||||
|
||||
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
|
||||
},
|
||||
calculable: true,
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
name: '暂降幅值',
|
||||
nameGap: 10,
|
||||
nameTextStyle: {
|
||||
fontSize: 12
|
||||
},
|
||||
data: [
|
||||
'0',
|
||||
'10%',
|
||||
'20%',
|
||||
'30%',
|
||||
'40%',
|
||||
'50%',
|
||||
'60%',
|
||||
'70%',
|
||||
'80%',
|
||||
'90%',
|
||||
'100%'
|
||||
]
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '概率分布',
|
||||
nameTextStyle: {
|
||||
fontSize: 15
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: '{value}%'
|
||||
},
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
// 使用深浅的间隔色
|
||||
type: 'dashed',
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '占比',
|
||||
|
||||
nameTextStyle: {
|
||||
fontSize: 15
|
||||
},
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: 'dashed',
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '占比',
|
||||
type: 'bar',
|
||||
data: pereventValue,
|
||||
barWidth: 30,
|
||||
itemStyle: {
|
||||
normal: { show: true }
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '概率分布',
|
||||
type: 'line',
|
||||
data: eventValue,
|
||||
itemStyle: {
|
||||
normal: { show: true }
|
||||
}
|
||||
}
|
||||
],
|
||||
options: {
|
||||
dataZoom: null
|
||||
}
|
||||
}
|
||||
nextTick(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
<style></style>
|
||||
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 表头 -->
|
||||
<TableHeader date-picker>
|
||||
<template v-slot:operation>
|
||||
<el-button :icon='Download' type='primary' @click='download'>波形下载</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<!-- 表格 -->
|
||||
<Table ref='tableRef' :checkboxConfig='checkboxConfig' />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { Download } from '@element-plus/icons-vue'
|
||||
import { ref, onMounted, provide, reactive } from 'vue'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { checkUser } from '@/api/user-boot/user'
|
||||
import { VxeTablePropTypes } from 'vxe-table'
|
||||
import { downloadWaveFile, getMonitorEventAnalyseWave } from '@/api/event-boot/transient'
|
||||
|
||||
const dictData = useDictData()
|
||||
const eventTypeOptions = dictData.getBasicData('Event_Statis')
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 60,
|
||||
url: '/event-boot/monitor/getMonitorEventAnalyseQuery',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ width: '60', type: 'checkbox' },
|
||||
{ title: '序号', type: 'seq', width: '60' },
|
||||
{ title: '变电站名称', field: 'subName', minWidth: '130' },
|
||||
{ title: '监测点名称', field: 'lineName', minWidth: '130' },
|
||||
{ title: '网络参数', field: 'ip', minWidth: '130' },
|
||||
{ title: '电压等级(kV)', field: 'voltageScale', width: '100' },
|
||||
{ title: '暂降发生时刻', field: 'startTime', width: '200' },
|
||||
{ title: '暂降类型', field: 'advanceType', minWidth: '130' },
|
||||
{ title: '暂降原因', field: 'advanceReason', minWidth: '130' },
|
||||
{ title: '触发类型', field: 'eventTypeName', minWidth: '80' },
|
||||
{ title: '暂降(骤升)幅值(%)', field: 'featureAmplitude', minWidth: '80' },
|
||||
{ title: '持续时间(s)', field: 'duration', minWidth: '80' },
|
||||
{ title: '严重度', field: 'severity', minWidth: '80' },
|
||||
{
|
||||
title: '操作',
|
||||
width: '180',
|
||||
render: 'buttons',
|
||||
fixed: 'right',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
title: '波形查看',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Lock',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return row.fileFlag === 0
|
||||
},
|
||||
click: row => {
|
||||
getMonitorEventAnalyseWave({
|
||||
id: row.eventId,
|
||||
systemType: 0,
|
||||
type: 0
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
ElMessage.error('暂无可下载的波形文件!')
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.eventTypeName = eventTypeOptions.find(item2 => item2.id === item.eventType)?.name
|
||||
item.featureAmplitude = (item.featureAmplitude * 100).toFixed(0)
|
||||
})
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.lineId = monitoringPoint.state.lineId
|
||||
tableStore.table.params.searchState = 0
|
||||
onMounted(() => {
|
||||
// 加载数据
|
||||
tableStore.index()
|
||||
})
|
||||
const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({
|
||||
checkMethod: ({ row }) => {
|
||||
return row.fileFlag === 1
|
||||
}
|
||||
})
|
||||
const download = () => {
|
||||
if (!tableStore.table.selection.length) {
|
||||
ElMessage.warning('请选择数据')
|
||||
return
|
||||
}
|
||||
downloadWaveFile({
|
||||
lineId: tableStore.table.selection.map((item: any) => item.eventId)
|
||||
}).then((res: any) => {
|
||||
if (res.type == 'application/json') {
|
||||
ElMessage.warning('暂无可下载的波形文件!')
|
||||
return
|
||||
}
|
||||
ElMessage.success('下载中。。。!')
|
||||
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a') // 创建a标签
|
||||
link.href = url
|
||||
link.download = '波形分析下载' // 设置下载的文件名
|
||||
document.body.appendChild(link)
|
||||
link.click() //执行下载
|
||||
document.body.removeChild(link) //释放标签
|
||||
})
|
||||
}
|
||||
</script>
|
||||
59
src/views/pqs/voltageSags/monitoringPoint/online/index.vue
Normal file
59
src/views/pqs/voltageSags/monitoringPoint/online/index.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div class='default-main' style='position: relative'>
|
||||
<el-tabs v-model='activeName' type='border-card' class='demo-tabs'>
|
||||
<el-tab-pane label='导航' name='1' :style='height' lazy>
|
||||
<Navigation @changeTab='changeTab' />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label='事件统计' name='2' lazy>
|
||||
<EventStatistics />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label='事件分析' name='3' lazy>
|
||||
<EventStudy />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label='运行情况' name='4' lazy :style='height'>
|
||||
<RunningCondition />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class='monitoring-point'>当前位置:{{ monitoringPoint.state.lineName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { defineOptions, ref, watch } from 'vue'
|
||||
import Navigation from './navigation/index.vue'
|
||||
import EventStatistics from './eventStatistics/index.vue'
|
||||
import EventStudy from './eventStudy/index.vue'
|
||||
import RunningCondition from './runningCondition/index.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import router from '@/router'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
|
||||
defineOptions({
|
||||
name: 'Descentsystem/monitoringpoint'
|
||||
})
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const height = mainHeight(82)
|
||||
const activeName = ref('1')
|
||||
watch(
|
||||
() => router.currentRoute.value.query.lineId,
|
||||
(newLineId, oldLineId) => {
|
||||
if (!newLineId) return
|
||||
// 在这里处理 lineId 的变化
|
||||
monitoringPoint.setValue('lineId', router.currentRoute.value.query.lineId)
|
||||
monitoringPoint.setValue('lineName', router.currentRoute.value.query.lineName)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
const changeTab = (e: string) => {
|
||||
activeName.value = e
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.monitoring-point {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<splitpanes style='height: 100%;' class='default-theme' id='navigation-splitpanes'>
|
||||
<pane :size='size'>
|
||||
<PointTree :default-expand-all='false'
|
||||
:default-expanded-keys='monitoringPoint.state.lineId?[monitoringPoint.state.lineId]:[]'
|
||||
:current-node-key='monitoringPoint.state.lineId'
|
||||
@node-click='handleNodeClick'
|
||||
@init='handleNodeClick'
|
||||
></PointTree>
|
||||
</pane>
|
||||
<pane>
|
||||
<Map v-bind='$attrs'></Map>
|
||||
</pane>
|
||||
</splitpanes>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
import { Splitpanes, Pane } from 'splitpanes'
|
||||
import PointTree from '@/components/tree/pms/pointTree.vue'
|
||||
import Map from './map.vue'
|
||||
import Tree from '@/components/tree/index.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const size = ref(0)
|
||||
onMounted(() => {
|
||||
const dom = document.getElementById('navigation-splitpanes')
|
||||
if (dom) {
|
||||
size.value = Math.round(240 / dom.offsetHeight * 100)
|
||||
}
|
||||
})
|
||||
const handleNodeClick = (data: any, node: any) => {
|
||||
if (data.level === 6) {
|
||||
monitoringPoint.setValue('lineId', data.id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.splitpanes.default-theme .splitpanes__pane {
|
||||
background: #eaeef1;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div style='position: relative; height: 100%' v-loading='loading'>
|
||||
<div style='display: none'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</div>
|
||||
<div class='iconBox'>
|
||||
<div class='div'>
|
||||
<img src='@/assets/jcd.png' alt='' />
|
||||
<span>变电站</span>
|
||||
</div>
|
||||
<div class='div'>
|
||||
<img src='@/assets/rby.png' alt='' />
|
||||
<span>热备用</span>
|
||||
</div>
|
||||
<div class='div'>
|
||||
<img src='@/assets/ty.png' alt='' />
|
||||
<span>停运</span>
|
||||
</div>
|
||||
<div class='div'>投运</div>
|
||||
<div class='div' style='padding-left: 10px'>
|
||||
<span>通讯正常</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txzcyzj.gif' alt='' />
|
||||
<span>有暂降</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txzcwzj.png' alt='' />
|
||||
<span>无暂降</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 10px'>
|
||||
<span>通讯异常</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txycyzj.gif' alt='' />
|
||||
<span>有暂降</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txzdwzj.png' alt='' />
|
||||
<span>无暂降</span>
|
||||
</div>
|
||||
</div>
|
||||
<baidu-map
|
||||
class='bm-view'
|
||||
:zoom='zoom'
|
||||
:map-click='false'
|
||||
:scroll-wheel-zoom='true'
|
||||
:center='center'
|
||||
@ready='handler'
|
||||
@zoomend='syncCenterAndZoom'
|
||||
>
|
||||
<bm-map-type
|
||||
:map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"
|
||||
anchor='BMAP_ANCHOR_TOP_RIGHT'
|
||||
></bm-map-type>
|
||||
<!-- 线-->
|
||||
<bm-polyline :path='path' v-for='(path, index) in polyline' :key='index'></bm-polyline>
|
||||
<!-- 变电站-->
|
||||
<template v-if='zoom > 12'>
|
||||
<bm-marker
|
||||
:position='path'
|
||||
v-for='path in siteList'
|
||||
:key='path.subId'
|
||||
:icon='path.icon'
|
||||
@click='markerClick(path)'
|
||||
></bm-marker>
|
||||
</template>
|
||||
<!-- 点 -->
|
||||
<BmlMarkerClusterer>
|
||||
<bm-marker
|
||||
:position='path'
|
||||
v-for='path in areaLineInfo'
|
||||
:key='path.lineId'
|
||||
:icon='path.icon'
|
||||
@click='markerClick(path)'
|
||||
></bm-marker>
|
||||
</BmlMarkerClusterer>
|
||||
<bm-marker :position='infoWindowPoint' :icon="{ url: '1', size: { width: 0, height: 0 } }">
|
||||
<bm-info-window :show='infoWindowPoint.show' @close='infoWindowPoint.show = false'>
|
||||
<el-descriptions :title='infoWindowPoint.lineName' :column='1' v-if='infoWindowPoint.lineId'>
|
||||
<el-descriptions-item label='供电公司'>{{ infoWindowPoint.gdName }}</el-descriptions-item>
|
||||
<el-descriptions-item label='变电站'>{{ infoWindowPoint.subName }}</el-descriptions-item>
|
||||
<el-descriptions-item label='母线'>{{ infoWindowPoint.voltageName }}</el-descriptions-item>
|
||||
<el-descriptions-item label='网络参数'>
|
||||
{{ infoWindowPoint.ip }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='PT变化'>{{ infoWindowPoint.pt2 }}</el-descriptions-item>
|
||||
<el-descriptions-item label='CT变化'>{{ infoWindowPoint.ct2 }}</el-descriptions-item>
|
||||
<el-descriptions-item label='生产厂家'>
|
||||
{{ infoWindowPoint.manufacturer }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='终端状态'>
|
||||
{{
|
||||
infoWindowPoint.runFlag == 0 ? '投运' : infoWindowPoint.runFlag == 1 ? '热备用' : '停运'
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='通讯状态'>
|
||||
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<el-button type='primary' size='small' @click='changeTab("2")'>事件统计</el-button>
|
||||
<el-button type='primary' size='small' @click='changeTab("3")'>事件分析</el-button>
|
||||
<el-button type='primary' size='small' @click='changeTab("4")'>运行情况</el-button>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions
|
||||
:title='infoWindowPoint.subName'
|
||||
:column='1'
|
||||
v-else-if='infoWindowPoint.subId'
|
||||
style='padding-top: 10px'
|
||||
></el-descriptions>
|
||||
</bm-info-window>
|
||||
</bm-marker>
|
||||
</baidu-map>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { BmlMarkerClusterer } from 'vue-baidu-map-3x'
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
|
||||
const emit = defineEmits(['changeTab'])
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const adminInfo = useAdminInfo()
|
||||
const datePickerRef = ref()
|
||||
const zoom = ref(11)
|
||||
const loading = ref(true)
|
||||
const params = ref({
|
||||
deptIndex: '',
|
||||
monitorFlag: 2,
|
||||
powerFlag: 2,
|
||||
searchBeginTime: '',
|
||||
searchEndTime: '',
|
||||
serverName: 'event-boot',
|
||||
statisticalType: {}
|
||||
})
|
||||
const center = ref({
|
||||
lng: 0,
|
||||
lat: 0
|
||||
})
|
||||
const infoWindowPoint = ref<anyObj>({
|
||||
lng: 0,
|
||||
lat: 0,
|
||||
show: false
|
||||
})
|
||||
const areaLineInfo = ref<any>([])
|
||||
const siteList = ref<any>([])
|
||||
const polyline = ref<any>([])
|
||||
const lineId = ref('')
|
||||
const handler = async ({ BMap, map }: any) => {
|
||||
params.value.deptIndex = adminInfo.$state.deptId
|
||||
params.value.searchBeginTime = datePickerRef.value.timeValue[0]
|
||||
params.value.searchEndTime = datePickerRef.value.timeValue[1]
|
||||
let { data } = await getAreaLineInfo(params.value)
|
||||
let r = 0.0035
|
||||
data.forEach((item: any) => {
|
||||
// 变电站图标
|
||||
item.icon = {
|
||||
url: new URL('@/assets/jcd.png', import.meta.url).href,
|
||||
size: {
|
||||
width: 40,
|
||||
height: 40
|
||||
}
|
||||
}
|
||||
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 = {
|
||||
url: '',
|
||||
size: {
|
||||
width: 40,
|
||||
height: 40
|
||||
}
|
||||
}
|
||||
switch (val.runFlag) {
|
||||
case 0:
|
||||
// 投运
|
||||
if (val.comFlag == 0) {
|
||||
// 异常
|
||||
if (val.noDealCount > 0) {
|
||||
// 异常有暂降
|
||||
val.icon.url = new URL('@/assets/txycyzj.gif', import.meta.url).href
|
||||
} else if (val.noDealCount == 0) {
|
||||
// 异常无暂降
|
||||
val.icon.url = new URL('@/assets/txzdwzj.png', import.meta.url).href
|
||||
}
|
||||
} else if (val.comFlag == 1) {
|
||||
// 正常
|
||||
if (val.noDealCount > 0) {
|
||||
// 正常有暂降
|
||||
val.icon.url = new URL('@/assets/txzcyzj.gif', import.meta.url).href
|
||||
} else if (val.noDealCount == 0) {
|
||||
// 正常无暂降
|
||||
val.icon.url = new URL('@/assets/txzcwzj.png', import.meta.url).href
|
||||
}
|
||||
}
|
||||
break
|
||||
case 1:
|
||||
val.icon.url = new URL('@/assets/rby.png', import.meta.url).href
|
||||
break
|
||||
case 2:
|
||||
val.icon.url = new URL('@/assets/ty.png', import.meta.url).href
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
polyline.value.push([
|
||||
{
|
||||
lng: item.lng,
|
||||
lat: item.lat
|
||||
},
|
||||
{
|
||||
lng: val.lng,
|
||||
lat: val.lat
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
areaLineInfo.value.push(...item.children)
|
||||
})
|
||||
siteList.value = data
|
||||
watch(
|
||||
() => monitoringPoint.state.lineId,
|
||||
(newLineId, oldLineId) => {
|
||||
let value = areaLineInfo.value.find((item: any) => item.lineId == newLineId)
|
||||
center.value.lng = value.lng
|
||||
center.value.lat = value.lat
|
||||
infoWindowPoint.value = value
|
||||
infoWindowPoint.value.show = true
|
||||
monitoringPoint.setValue('lineName', value.manufacturer + '>' + value.gdName + '>' + value.subName + '>' + value.lineName)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
zoom.value = 15
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
const syncCenterAndZoom = (e: any) => {
|
||||
zoom.value = e.target.getZoom()
|
||||
}
|
||||
const markerClick = (e: any) => {
|
||||
infoWindowPoint.value = e
|
||||
infoWindowPoint.value.show = true
|
||||
}
|
||||
const changeTab = (e: string) => {
|
||||
emit('changeTab', e)
|
||||
}
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
.bm-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.selectBox {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 165px;
|
||||
z-index: 2000;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.iconBox {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 2000;
|
||||
width: 150px;
|
||||
height: 260px;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.75) !important;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
|
||||
font-size: 12px;
|
||||
|
||||
.div {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
|
||||
img {
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,330 @@
|
||||
<template>
|
||||
<div v-loading='loading' class='running-condition'>
|
||||
<el-form :inline='true'>
|
||||
<el-form-item label='日期'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type='primary' @click='init'>查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style='flex: 1;' class='mt10 zanjiangfenbutongji'>
|
||||
<div
|
||||
style='position: absolute; right: 10px; top: 10px; z-index: 2;display: flex;align-items: center;font-size: 12px'>
|
||||
<el-tag style='width: 20px;height: 12px' :style='{background: gradeColor[2]}'></el-tag>
|
||||
<span class='ml2' :style='{color: gradeColor[2]}'> {{ 'X<60%' }} </span>
|
||||
<el-tag class='ml10' style='width: 20px;height: 12px' :style='{background: gradeColor[1]}'></el-tag>
|
||||
<span class='ml2' :style='{color: gradeColor[1]}'>{{ '60%≤X<90%' }} </span>
|
||||
<el-tag class='ml10' style='width: 20px;height: 12px' :style='{background: gradeColor[0]}'></el-tag>
|
||||
<span class='ml2' :style='{color: gradeColor[0]}'> {{ 'X≥90 %' }}</span>
|
||||
</div>
|
||||
<my-echart :options='secondOptions' style='flex: 1;height: 100%' />
|
||||
<my-echart :options='firstOptions' style='flex: 1;height: 100%' />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { useMonitoringPoint } from '@/views/pqs/voltageSags/monitoringPoint/online/store'
|
||||
import { getComFlagInfoData, getRunOnlineRateData } from '@/api/device-boot/communicate'
|
||||
import { gradeColor } from '@/components/echarts/color'
|
||||
|
||||
const datePickerRef = ref()
|
||||
const loading = ref(true)
|
||||
const monitoringPoint = useMonitoringPoint()
|
||||
const formData = reactive({
|
||||
id: monitoringPoint.state.lineId,
|
||||
searchBeginTime: '',
|
||||
searchEndTime: '',
|
||||
timeFlag: 1
|
||||
})
|
||||
const firstOptions = ref<any>({})
|
||||
const secondOptions = ref<any>({})
|
||||
const firstData = ref<any>([])
|
||||
const secondData = ref<any>([])
|
||||
|
||||
|
||||
const init = () => {
|
||||
|
||||
loading.value = true
|
||||
formData.searchBeginTime = datePickerRef.value.timeValue[0]
|
||||
formData.searchEndTime = datePickerRef.value.timeValue[1]
|
||||
formData.timeFlag = datePickerRef.value.interval
|
||||
Promise.all([getRunOnlineRateData(formData), getComFlagInfoData(formData)]).then(res => {
|
||||
firstData.value = res[0].data
|
||||
secondData.value = res[1].data
|
||||
initFirst()
|
||||
initSecond()
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
const initFirst = () => {
|
||||
let months = new Array()
|
||||
let handle = new Array()
|
||||
let year = firstData.value[0].year
|
||||
|
||||
for (let i = 0; i < firstData.value.length; i++) {
|
||||
if (formData.timeFlag == 0) {
|
||||
months[i] = firstData.value[i].month
|
||||
months[0] = firstData.value[i].month + '\n' + '(' + year + ')'
|
||||
} else {
|
||||
months[i] = firstData.value[i].month + '-' + firstData.value[i].day
|
||||
months[0] = firstData.value[i].month + '-' + firstData.value[i].day + '\n' + '(' + year + ')'
|
||||
}
|
||||
handle.push(firstData.value[i].onlineRate)
|
||||
}
|
||||
firstOptions.value = {
|
||||
title: {
|
||||
text: '在线率统计',
|
||||
x: 'center',
|
||||
textStyle: {
|
||||
fontWeight: 'normal'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
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)',
|
||||
formatter: function(params: any) {
|
||||
let tips = ''
|
||||
tips += '时间:' + year + '-' + params[0].name + '</br/>'
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
if (params[i].value == 3.14159) {
|
||||
tips += '在线率' + ':暂无数据<br/>'
|
||||
} else {
|
||||
tips += '在线率' + ':' + params[i].value + '%<br/>'
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: months,
|
||||
name: '时间',
|
||||
nameTextStyle: {
|
||||
verticalAlign: 'top', //标题位置
|
||||
padding: [-5, 0, 0, -10]
|
||||
},
|
||||
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
min: 0,
|
||||
max: 100,
|
||||
type: 'value',
|
||||
name: '%',
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
// 使用深浅的间隔色
|
||||
type: 'dashed',
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'bar',
|
||||
data: handle,
|
||||
itemStyle: {
|
||||
color: (params: any) => {
|
||||
if (params.value == 3.14159) {
|
||||
return '#ccc'
|
||||
} else {
|
||||
if (params.value < 60) {
|
||||
return gradeColor[2]
|
||||
} else if (params.value < 90) {
|
||||
return gradeColor[1]
|
||||
} else {
|
||||
return gradeColor[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
markLine: {
|
||||
silent: false,
|
||||
symbol: 'circle',
|
||||
data: [
|
||||
{
|
||||
yAxis: 100,
|
||||
lineStyle: {
|
||||
color: gradeColor[0]
|
||||
},
|
||||
label: {
|
||||
position: 'end',
|
||||
formatter: '100%'
|
||||
}
|
||||
},
|
||||
{
|
||||
yAxis: 90,
|
||||
lineStyle: {
|
||||
color: gradeColor[1]
|
||||
},
|
||||
label: {
|
||||
position: 'end',
|
||||
formatter: '90%'
|
||||
}
|
||||
},
|
||||
{
|
||||
yAxis: 60,
|
||||
lineStyle: {
|
||||
color: gradeColor[2]
|
||||
},
|
||||
label: {
|
||||
position: 'end',
|
||||
formatter: '60%'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
const initSecond = () => {
|
||||
let list = secondData.value.type
|
||||
let items = secondData.value.updateTime
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (i != 0) {
|
||||
i
|
||||
items[i] = items[i].slice(11)
|
||||
} else if (i == 0) {
|
||||
let date = items[i].slice(11)
|
||||
let t = items[i].slice(0, 10)
|
||||
items[i] = '(' + date + ')' + '\n' + t
|
||||
}
|
||||
}
|
||||
secondOptions.value = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
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)',
|
||||
formatter: function(params: any) {
|
||||
let res = '时间: ' + params[0].name + '<br/>运行状态:'
|
||||
let texts = ''
|
||||
if (params[0].value === 2 || params[0].value === '2') {
|
||||
texts = '退出'
|
||||
} else if (params[0].value === 0 || params[0].value === '0') {
|
||||
texts = '中断'
|
||||
} else if (params[0].value === 1 || params[0].value === '1') {
|
||||
texts = '正常'
|
||||
}
|
||||
res = res + texts
|
||||
return res
|
||||
}
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
height: 13,
|
||||
start: 0,
|
||||
end: 100,
|
||||
bottom: '25px'
|
||||
},
|
||||
|
||||
{ height: 13, start: 0, bottom: '25px', end: 100 }
|
||||
],
|
||||
|
||||
xAxis: {
|
||||
name: '时间',
|
||||
type: 'category',
|
||||
data: items,
|
||||
boundaryGap: false
|
||||
|
||||
},
|
||||
yAxis: {
|
||||
name: '状态',
|
||||
type: 'value',
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: 'blue'
|
||||
},
|
||||
// 这里重新定义就可以
|
||||
formatter: function(value: number) {
|
||||
let texts = []
|
||||
if (value === 2) {
|
||||
texts.push('退出')
|
||||
} else if (value === 0) {
|
||||
texts.push('中断')
|
||||
} else if (value === 1) {
|
||||
texts.push('正常')
|
||||
}
|
||||
return texts
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '运行状态',
|
||||
type: 'line',
|
||||
step: 'end',
|
||||
data: list
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.running-condition {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 14px;
|
||||
border: 1px solid var(--el-border-color);
|
||||
|
||||
.zanjiangfenbutongji {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
24
src/views/pqs/voltageSags/monitoringPoint/online/store.ts
Normal file
24
src/views/pqs/voltageSags/monitoringPoint/online/store.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { reactive } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
interface MonitoringPoint {
|
||||
lineId: string
|
||||
lineName: string
|
||||
}
|
||||
|
||||
export const useMonitoringPoint = defineStore(
|
||||
'monitoringPoint',
|
||||
() => {
|
||||
const state: MonitoringPoint = reactive({
|
||||
lineId: '',
|
||||
lineName: '',
|
||||
})
|
||||
const setValue = (key: keyof MonitoringPoint, val: any) => {
|
||||
state[key] = val
|
||||
}
|
||||
return { state, setValue }
|
||||
},
|
||||
{
|
||||
persist: true
|
||||
}
|
||||
)
|
||||
349
src/views/pqs/voltageSags/overview/index.vue
Normal file
349
src/views/pqs/voltageSags/overview/index.vue
Normal file
@@ -0,0 +1,349 @@
|
||||
<template>
|
||||
<div style='padding: 10px; display: flex; height: 100%' v-loading='loading'>
|
||||
<div style='position: relative; flex: 1'>
|
||||
<div style='display: none'>
|
||||
<DatePicker ref='datePickerRef'></DatePicker>
|
||||
</div>
|
||||
<div class='iconBox'>
|
||||
<div class='div'>
|
||||
<img src='@/assets/jcd.png' alt='' />
|
||||
<span>变电站</span>
|
||||
</div>
|
||||
<div class='div'>
|
||||
<img src='@/assets/rby.png' alt='' />
|
||||
<span>热备用</span>
|
||||
</div>
|
||||
<div class='div'>
|
||||
<img src='@/assets/ty.png' alt='' />
|
||||
<span>停运</span>
|
||||
</div>
|
||||
<div class='div'>投运</div>
|
||||
<div class='div' style='padding-left: 10px'>
|
||||
<span>通讯正常</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txzcyzj.gif' alt='' />
|
||||
<span>有暂降</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txzcwzj.png' alt='' />
|
||||
<span>无暂降</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 10px'>
|
||||
<span>通讯异常</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txycyzj.gif' alt='' />
|
||||
<span>有暂降</span>
|
||||
</div>
|
||||
<div class='div' style='padding-left: 20px'>
|
||||
<img src='@/assets/txzdwzj.png' alt='' />
|
||||
<span>无暂降</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='selectBox'>
|
||||
<el-select
|
||||
@change='pointChange'
|
||||
:popper-append-to-body='false'
|
||||
filterable
|
||||
clearable
|
||||
v-model='lineId'
|
||||
placeholder='输入监测点名称查询'
|
||||
>
|
||||
<el-option
|
||||
v-for='item in areaLineInfo'
|
||||
:key='item.lineId'
|
||||
:label='item.lineName'
|
||||
:value='item.lineId'
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<baidu-map
|
||||
class='bm-view'
|
||||
:zoom='zoom'
|
||||
:map-click='false'
|
||||
:scroll-wheel-zoom='true'
|
||||
:center='center'
|
||||
@ready='handler'
|
||||
@zoomend='syncCenterAndZoom'
|
||||
>
|
||||
<bm-map-type
|
||||
:map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"
|
||||
anchor='BMAP_ANCHOR_TOP_RIGHT'
|
||||
></bm-map-type>
|
||||
<!-- 线-->
|
||||
<bm-polyline :path='path' v-for='(path, index) in polyline' :key='index'></bm-polyline>
|
||||
<!-- 变电站-->
|
||||
<template v-if='zoom > 12'>
|
||||
<bm-marker
|
||||
:position='path'
|
||||
v-for='path in siteList'
|
||||
:key='path.subId'
|
||||
:icon='path.icon'
|
||||
@click='markerClick(path)'
|
||||
></bm-marker>
|
||||
</template>
|
||||
<!-- 点 -->
|
||||
<BmlMarkerClusterer>
|
||||
<bm-marker
|
||||
:position='path'
|
||||
v-for='path in areaLineInfo'
|
||||
:key='path.lineId'
|
||||
:icon='path.icon'
|
||||
@click='markerClick(path)'
|
||||
></bm-marker>
|
||||
</BmlMarkerClusterer>
|
||||
<bm-marker :position='infoWindowPoint' :icon="{ url: '1', size: { width: 0, height: 0 } }">
|
||||
<bm-info-window :show='infoWindowPoint.show' @close='infoWindowPoint.show = false'>
|
||||
<el-descriptions :title='infoWindowPoint.lineName' :column='1' v-if='infoWindowPoint.lineId'>
|
||||
<el-descriptions-item label='供电公司'>{{ infoWindowPoint.gdName }}</el-descriptions-item>
|
||||
<el-descriptions-item label='变电站'>{{ infoWindowPoint.subName }}</el-descriptions-item>
|
||||
<el-descriptions-item label='母线'>{{ infoWindowPoint.voltageName }}</el-descriptions-item>
|
||||
<el-descriptions-item label='网络参数'>
|
||||
{{ infoWindowPoint.ip }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='PT变化'>{{ infoWindowPoint.pt2 }}</el-descriptions-item>
|
||||
<el-descriptions-item label='CT变化'>{{ infoWindowPoint.ct2 }}</el-descriptions-item>
|
||||
<el-descriptions-item label='生产厂家'>
|
||||
{{ infoWindowPoint.manufacturer }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='终端状态'>
|
||||
{{
|
||||
infoWindowPoint.runFlag == 0
|
||||
? '投运'
|
||||
: infoWindowPoint.runFlag == 1
|
||||
? '热备用'
|
||||
: '停运'
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='通讯状态'>
|
||||
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<el-button type='primary' size='small' @click='lookPoint'>查看监测点</el-button>
|
||||
<el-button type='primary' size='small' @click='lookEvent'>
|
||||
未处理事件({{ infoWindowPoint.noDealCount }})
|
||||
</el-button>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions
|
||||
:title='infoWindowPoint.subName'
|
||||
:column='1'
|
||||
v-else-if='infoWindowPoint.subId'
|
||||
style='padding-top: 10px'
|
||||
></el-descriptions>
|
||||
</bm-info-window>
|
||||
</bm-marker>
|
||||
</baidu-map>
|
||||
</div>
|
||||
<div style='width: 600px; height: 100%'>
|
||||
<Right :params='params' v-if='params.deptIndex'></Right>
|
||||
</div>
|
||||
<PopupEvent ref='popupEvent'></PopupEvent>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { BmlMarkerClusterer } from 'vue-baidu-map-3x'
|
||||
import { ref } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import Right from './right.vue'
|
||||
import PopupEvent from './popupEvent.vue'
|
||||
import router from '@/router'
|
||||
|
||||
defineOptions({
|
||||
name: 'Descentsystem/overview'
|
||||
})
|
||||
const height = mainHeight(20)
|
||||
const adminInfo = useAdminInfo()
|
||||
const datePickerRef = ref()
|
||||
const zoom = ref(11)
|
||||
const loading = ref(true)
|
||||
const popupEvent = ref()
|
||||
const params = ref({
|
||||
deptIndex: '',
|
||||
monitorFlag: 2,
|
||||
powerFlag: 2,
|
||||
searchBeginTime: '',
|
||||
searchEndTime: '',
|
||||
serverName: 'event-boot',
|
||||
statisticalType: {}
|
||||
})
|
||||
const center = ref({
|
||||
lng: 0,
|
||||
lat: 0
|
||||
})
|
||||
const infoWindowPoint = ref<anyObj>({
|
||||
lng: 0,
|
||||
lat: 0,
|
||||
show: false
|
||||
})
|
||||
const areaLineInfo = ref<any>([])
|
||||
const siteList = ref<any>([])
|
||||
const polyline = ref<any>([])
|
||||
const lineId = ref('')
|
||||
const handler = async ({ BMap, map }: any) => {
|
||||
params.value.deptIndex = adminInfo.$state.deptId
|
||||
params.value.searchBeginTime = datePickerRef.value.timeValue[0]
|
||||
params.value.searchEndTime = datePickerRef.value.timeValue[1]
|
||||
let { data } = await getAreaLineInfo(params.value)
|
||||
let r = 0.0035
|
||||
data.forEach((item: any) => {
|
||||
// 变电站图标
|
||||
item.icon = {
|
||||
url: new URL('@/assets/jcd.png', import.meta.url).href,
|
||||
size: {
|
||||
width: 40,
|
||||
height: 40
|
||||
}
|
||||
}
|
||||
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 = {
|
||||
url: '',
|
||||
size: {
|
||||
width: 40,
|
||||
height: 40
|
||||
}
|
||||
}
|
||||
switch (val.runFlag) {
|
||||
case 0:
|
||||
// 投运
|
||||
if (val.comFlag == 0) {
|
||||
// 异常
|
||||
if (val.noDealCount > 0) {
|
||||
// 异常有暂降
|
||||
val.icon.url = new URL('@/assets/txycyzj.gif', import.meta.url).href
|
||||
} else if (val.noDealCount == 0) {
|
||||
// 异常无暂降
|
||||
val.icon.url = new URL('@/assets/txzdwzj.png', import.meta.url).href
|
||||
}
|
||||
} else if (val.comFlag == 1) {
|
||||
// 正常
|
||||
if (val.noDealCount > 0) {
|
||||
// 正常有暂降
|
||||
val.icon.url = new URL('@/assets/txzcyzj.gif', import.meta.url).href
|
||||
} else if (val.noDealCount == 0) {
|
||||
// 正常无暂降
|
||||
val.icon.url = new URL('@/assets/txzcwzj.png', import.meta.url).href
|
||||
}
|
||||
}
|
||||
break
|
||||
case 1:
|
||||
val.icon.url = new URL('@/assets/rby.png', import.meta.url).href
|
||||
break
|
||||
case 2:
|
||||
val.icon.url = new URL('@/assets/ty.png', import.meta.url).href
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
polyline.value.push([
|
||||
{
|
||||
lng: item.lng,
|
||||
lat: item.lat
|
||||
},
|
||||
{
|
||||
lng: val.lng,
|
||||
lat: val.lat
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
areaLineInfo.value.push(...item.children)
|
||||
})
|
||||
siteList.value = data
|
||||
center.value.lng = areaLineInfo.value[0].lng
|
||||
center.value.lat = areaLineInfo.value[0].lat
|
||||
infoWindowPoint.value = areaLineInfo.value[0]
|
||||
infoWindowPoint.value.show = true
|
||||
zoom.value = 15
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
const syncCenterAndZoom = (e: any) => {
|
||||
zoom.value = e.target.getZoom()
|
||||
}
|
||||
const pointChange = (val: string) => {
|
||||
if (!val) return
|
||||
let data = areaLineInfo.value.find((item: any) => item.lineId == val)
|
||||
center.value.lng = data.lng
|
||||
center.value.lat = data.lat
|
||||
infoWindowPoint.value = data
|
||||
infoWindowPoint.value.show = true
|
||||
zoom.value = 15
|
||||
}
|
||||
const markerClick = (e: any) => {
|
||||
infoWindowPoint.value = e
|
||||
infoWindowPoint.value.show = true
|
||||
}
|
||||
const lookEvent = (e: any) => {
|
||||
popupEvent.value.open({
|
||||
id: infoWindowPoint.value.lineId,
|
||||
searchBeginTime: datePickerRef.value.timeValue[0],
|
||||
searchEndTime: datePickerRef.value.timeValue[1]
|
||||
})
|
||||
}
|
||||
const lookPoint = () => {
|
||||
console.log(infoWindowPoint.value)
|
||||
router.replace({
|
||||
name: 'Descentsystem/monitoringpoint',
|
||||
query: {
|
||||
lineId: infoWindowPoint.value.lineId,
|
||||
lineName: infoWindowPoint.value.manufacturer + '>' + infoWindowPoint.value.gdName + '>' + infoWindowPoint.value.subName + '>' + infoWindowPoint.value.lineName
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
.bm-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.selectBox {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 165px;
|
||||
z-index: 2000;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.iconBox {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 2000;
|
||||
width: 150px;
|
||||
height: 260px;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.75) !important;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
|
||||
font-size: 12px;
|
||||
|
||||
.div {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
|
||||
img {
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
36
src/views/pqs/voltageSags/overview/popupEvent.vue
Normal file
36
src/views/pqs/voltageSags/overview/popupEvent.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<el-dialog class="cn-operate-dialog" v-model="dialogVisible" title="暂降事件列表">
|
||||
<vxe-table v-loading="loading" height="auto" auto-resize :data="tableData" v-bind="defaultAttribute">
|
||||
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
|
||||
<vxe-column field="startTime" title="发生时间" width="200"></vxe-column>
|
||||
<vxe-column field="duration" title="持续时间(s)" width="120"></vxe-column>
|
||||
<vxe-column field="featureAmplitude" title="暂降(骤升)幅值(%)" width="150">
|
||||
<template #default="{ row }">
|
||||
{{ (row.featureAmplitude * 100).toFixed(2) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="gdName" title="供电公司" width="200"></vxe-column>
|
||||
<vxe-column field="subName" title="变电站" min-width="200"></vxe-column>
|
||||
<vxe-column field="lineName" title="监测点" width="200"></vxe-column>
|
||||
</vxe-table>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, inject } from 'vue'
|
||||
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { getNoDealEventsByLineId } from '@/api/event-boot/areaInfo'
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const tableData = ref([])
|
||||
const loading = ref(true)
|
||||
const open = (params:any) => {
|
||||
dialogVisible.value = true
|
||||
loading.value = true
|
||||
getNoDealEventsByLineId(params).then(res => {
|
||||
tableData.value = res.data
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
92
src/views/pqs/voltageSags/overview/right.vue
Normal file
92
src/views/pqs/voltageSags/overview/right.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="overview-right">
|
||||
<div class="overview-right-item">
|
||||
<div class="overview-right-item-title">
|
||||
<span style="font-weight: 700">离线终端</span>
|
||||
</div>
|
||||
<div style="flex: 1; overflow: hidden">
|
||||
<vxe-table height="auto" auto-resize :data="tableData1" v-bind="defaultAttribute">
|
||||
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
|
||||
<vxe-column field="updateTime" title="中断时间"></vxe-column>
|
||||
<vxe-column field="subName" title="变电站"></vxe-column>
|
||||
<vxe-column field="devName" title="装置名称"></vxe-column>
|
||||
<vxe-column field="devType" title="装置型号"></vxe-column>
|
||||
<vxe-column field="ip" title="网络参数"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-right-item" style="padding-top: 0">
|
||||
<div class="overview-right-item-title">
|
||||
<div style="font-weight: 700">未处理暂态事件</div>
|
||||
<el-button type="primary" size="small" icon="el-icon-Promotion" @click="jump">事件关联分析</el-button>
|
||||
</div>
|
||||
<div style="flex: 1; overflow: hidden">
|
||||
<vxe-table height="auto" auto-resize :data="tableData" v-bind="defaultAttribute">
|
||||
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
|
||||
<vxe-column field="startTime" title="发生时刻"></vxe-column>
|
||||
<vxe-column field="lineName" title="监测点"></vxe-column>
|
||||
<vxe-column field="featureAmplitude" title="暂降(骤升)幅值(%)" width="150"></vxe-column>
|
||||
<vxe-column field="duration" title="持续时间(s)" width="120"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { getNoDealEvents } from '@/api/event-boot/areaInfo'
|
||||
import { getAreaOffDev } from '@/api/device-boot/device'
|
||||
import router from '@/router'
|
||||
|
||||
const props = defineProps({
|
||||
params: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const tableData = ref([])
|
||||
const tableData1 = ref([])
|
||||
getNoDealEvents(props.params).then(res => {
|
||||
console.log(res)
|
||||
tableData.value = res.data
|
||||
})
|
||||
getAreaOffDev(props.params).then(res => {
|
||||
tableData1.value = res.data
|
||||
})
|
||||
|
||||
const jump = () => {
|
||||
router.push({
|
||||
name: 'Advancedanalysis/eventcorrelation'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.overview-right {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.overview-right-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.overview-right-item-title {
|
||||
background: #fff;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user