冀北问题修改

This commit is contained in:
guanj
2025-12-08 16:28:34 +08:00
parent c779bec0cb
commit 8c41a8fc77
50 changed files with 7714 additions and 7287 deletions

View File

@@ -54,6 +54,24 @@
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe65d;</span>
<div class="name">停运事件管理</div>
<div class="code-name">&amp;#xe65d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe604;</span>
<div class="name">在运设备</div>
<div class="code-name">&amp;#xe604;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe666;</span>
<div class="name">异常类_14非智能表在运异常</div>
<div class="code-name">&amp;#xe666;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe82f;</span>
<div class="name">综合评价</div>
@@ -234,9 +252,9 @@
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1744179175277') format('woff2'),
url('iconfont.woff?t=1744179175277') format('woff'),
url('iconfont.ttf?t=1744179175277') format('truetype');
src: url('iconfont.woff2?t=1764826411334') format('woff2'),
url('iconfont.woff?t=1764826411334') format('woff'),
url('iconfont.ttf?t=1764826411334') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -262,6 +280,33 @@
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-tingyunshijianguanli"></span>
<div class="name">
停运事件管理
</div>
<div class="code-name">.icon-tingyunshijianguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zaiyunshebei"></span>
<div class="name">
在运设备
</div>
<div class="code-name">.icon-zaiyunshebei
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-yichanglei_14feizhinengbiaozaiyunyichang"></span>
<div class="name">
异常类_14非智能表在运异常
</div>
<div class="code-name">.icon-yichanglei_14feizhinengbiaozaiyunyichang
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zonghepingjia1"></span>
<div class="name">
@@ -532,6 +577,30 @@
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-tingyunshijianguanli"></use>
</svg>
<div class="name">停运事件管理</div>
<div class="code-name">#icon-tingyunshijianguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zaiyunshebei"></use>
</svg>
<div class="name">在运设备</div>
<div class="code-name">#icon-zaiyunshebei</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yichanglei_14feizhinengbiaozaiyunyichang"></use>
</svg>
<div class="name">异常类_14非智能表在运异常</div>
<div class="code-name">#icon-yichanglei_14feizhinengbiaozaiyunyichang</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zonghepingjia1"></use>

View File

@@ -1,10 +1,9 @@
@font-face {
font-family: "iconfont"; /* Project id 3482754 */
src: url('iconfont.woff2?t=1744179175277') format('woff2'),
url('iconfont.woff?t=1744179175277') format('woff'),
url('iconfont.ttf?t=1744179175277') format('truetype');
font-family: 'iconfont';
src: url('/src/assets/font/iconfont.woff2?t=1764826411334') format('woff2'),
url('/src/assets/font/iconfont.woff?t=1764826411334') format('woff'),
url('/src/assets/font/iconfont.ttf?t=1764826411334') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
@@ -13,6 +12,18 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-tingyunshijianguanli:before {
content: "\e65d";
}
.icon-zaiyunshebei:before {
content: "\e604";
}
.icon-yichanglei_14feizhinengbiaozaiyunyichang:before {
content: "\e666";
}
.icon-zonghepingjia1:before {
content: "\e82f";
}

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,27 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "25458995",
"name": "停运事件管理",
"font_class": "tingyunshijianguanli",
"unicode": "e65d",
"unicode_decimal": 58973
},
{
"icon_id": "35341056",
"name": "在运设备",
"font_class": "zaiyunshebei",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "22630860",
"name": "异常类_14非智能表在运异常",
"font_class": "yichanglei_14feizhinengbiaozaiyunyichang",
"unicode": "e666",
"unicode_decimal": 58982
},
{
"icon_id": "32402696",
"name": "综合评价",

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -6,7 +6,7 @@
</div> -->
<TableHeader :showSearch="false">
<template v-slot:select>
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef" :nextFlag="false" :theCurrentTime="true"></DatePicker>
</el-form-item>
</template>

View File

@@ -1,491 +1,491 @@
<template>
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="small" border>
<el-table-column label="序号" width="80px" type="index" />
<el-table-column
label="事件类型"
min-width="80px"
show-overflow-tooltip
:formatter="(row) => listenerEventTypeObject[row.event]"
/>
<el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip />
<el-table-column
label="监听器类型"
min-width="80px"
show-overflow-tooltip
:formatter="(row) => listenerTypeObject[row.listenerType]"
/>
<el-table-column label="操作" width="90px">
<template #default="scope">
<el-button size="small" link @click="openListenerForm(scope.row, scope.$index)"
>编辑</el-button
>
<el-divider direction="vertical" />
<el-button
size="small"
link
style="color: #ff4d4f"
@click="removeListener(scope.row, scope.$index)"
>移除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<XButton
size="small"
type="primary"
preIcon="ep:plus"
title="添加监听器"
@click="openListenerForm(null)"
/>
<XButton
type="success"
preIcon="ep:select"
title="选择监听器"
size="small"
@click="openProcessListenerDialog"
/>
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer
v-model="listenerFormModelVisible"
title="任务监听器"
:size="`${width}px`"
append-to-body
destroy-on-close
>
<el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef">
<el-form-item
label="事件类型"
prop="event"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-select v-model="listenerForm.event">
<el-option
v-for="i in Object.keys(listenerEventTypeObject)"
:key="i"
:label="listenerEventTypeObject[i]"
:value="i"
/>
</el-select>
</el-form-item>
<el-form-item
label="监听器ID"
prop="id"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.id" clearable />
</el-form-item>
<el-form-item
label="监听器类型"
prop="listenerType"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-select v-model="listenerForm.listenerType">
<el-option
v-for="i in Object.keys(listenerTypeObject)"
:key="i"
:label="listenerTypeObject[i]"
:value="i"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'classListener'"
label="Java类"
prop="class"
key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.class" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式"
prop="expression"
key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.expression" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式"
prop="delegateExpression"
key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item
label="脚本格式"
prop="scriptFormat"
key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
>
<el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item>
<el-form-item
label="脚本类型"
prop="scriptType"
key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
>
<el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容"
prop="value"
key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
>
<el-input v-model="listenerForm.value" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址"
prop="resource"
key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
>
<el-input v-model="listenerForm.resource" clearable />
</el-form-item>
</template>
<template v-if="listenerForm.event === 'timeout'">
<el-form-item label="定时器类型" prop="eventDefinitionType" key="eventDefinitionType">
<el-select v-model="listenerForm.eventDefinitionType">
<el-option label="日期" value="date" />
<el-option label="持续时长" value="duration" />
<el-option label="循环" value="cycle" />
<el-option label="无" value="null" />
</el-select>
</el-form-item>
<el-form-item
v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
label="定时器"
prop="eventTimeDefinitions"
key="eventTimeDefinitions"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写定时器配置' }"
>
<el-input v-model="listenerForm.eventTimeDefinitions" clearable />
</el-form-item>
</template>
</el-form>
<el-divider />
<p class="listener-filed__title">
<span><Icon icon="ep:menu" />注入字段</span>
<el-button size="small" type="primary" @click="openListenerFieldForm(null)"
>添加字段</el-button
>
</p>
<el-table
:data="fieldsListOfListener"
size="small"
max-height="240"
fit
border
style="flex: none"
>
<el-table-column label="序号" width="80px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column
label="字段类型"
min-width="80px"
show-overflow-tooltip
:formatter="(row) => fieldTypeObject[row.fieldType]"
/>
<el-table-column
label="字段值/表达式"
min-width="100px"
show-overflow-tooltip
:formatter="(row) => row.string || row.expression"
/>
<el-table-column label="操作" width="100px">
<template #default="scope">
<el-button size="small" link @click="openListenerFieldForm(scope.row, scope.$index)"
>编辑</el-button
>
<el-divider direction="vertical" />
<el-button
size="small"
link
style="color: #ff4d4f"
@click="removeListenerField(scope.row, scope.$index)"
>移除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="small" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog
title="字段配置"
v-model="listenerFieldFormModelVisible"
width="600px"
append-to-body
destroy-on-close
>
<el-form
:model="listenerFieldForm"
size="small"
label-width="96px"
ref="listenerFieldFormRef"
style="height: 136px"
>
<el-form-item
label="字段名称:"
prop="name"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item
label="字段类型:"
prop="fieldType"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-select v-model="listenerFieldForm.fieldType">
<el-option
v-for="i in Object.keys(fieldTypeObject)"
:key="i"
:label="fieldTypeObject[i]"
:value="i"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button size="small" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
<!-- 选择弹窗 -->
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
</template>
<script lang="ts" setup>
import { ElMessageBox } from 'element-plus'
import { createListenerObject, updateElementExtensions } from '../../utils'
import {
initListenerForm,
initListenerType,
eventType,
listenerType,
fieldType,
initListenerForm2
} from './utilSelf'
import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
defineOptions({ name: 'UserTaskListeners' })
const props = defineProps({
id: String,
type: String
})
const prefix = inject('prefix')
const width = inject('width')
const elementListenersList = ref<any[]>([])
const listenerEventTypeObject = ref(eventType)
const listenerTypeObject = ref(listenerType)
const listenerFormModelVisible = ref(false)
const listenerForm = ref<any>({})
const fieldTypeObject = ref(fieldType)
const fieldsListOfListener = ref<any[]>([])
const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态
const editingListenerIndex = ref(-1) // 监听器所在下标,-1 为新增
const editingListenerFieldIndex = ref(-1) // 字段所在下标,-1 为新增
const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单
const bpmnElement = ref()
const bpmnElementListeners = ref()
const otherExtensionList = ref()
const listenerFormRef = ref()
const listenerFieldFormRef = ref()
const bpmnInstances = () => (window as any)?.bpmnInstances
const resetListenersList = () => {
// console.log(
// bpmnInstances().bpmnElement,
// 'window.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElement'
// )
bpmnElement.value = bpmnInstances().bpmnElement
otherExtensionList.value = []
bpmnElementListeners.value =
bpmnElement.value.businessObject?.extensionElements?.values.filter(
(ex) => ex.$type === `${prefix}:TaskListener`
) ?? []
elementListenersList.value = bpmnElementListeners.value.map((listener) =>
initListenerType(listener)
)
}
const openListenerForm = (listener, index?) => {
if (listener) {
listenerForm.value = initListenerForm(listener)
editingListenerIndex.value = index
} else {
listenerForm.value = {}
editingListenerIndex.value = -1 // 标记为新增
}
if (listener && listener.fields) {
fieldsListOfListener.value = listener.fields.map((field) => ({
...field,
fieldType: field.string ? 'string' : 'expression'
}))
} else {
fieldsListOfListener.value = []
listenerForm.value['fields'] = []
}
// 打开侧边栏并清楚验证状态
listenerFormModelVisible.value = true
nextTick(() => {
if (listenerFormRef.value) listenerFormRef.value.clearValidate()
})
}
// 移除监听器
const removeListener = (listener, index?) => {
console.log(listener, 'listener')
ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
confirmButtonText: '确 认',
cancelButtonText: '取 消'
})
.then(() => {
bpmnElementListeners.value.splice(index, 1)
elementListenersList.value.splice(index, 1)
updateElementExtensions(
bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value)
)
})
.catch(() => console.info('操作取消'))
}
// 保存监听器
const saveListenerConfig = async () => {
let validateStatus = await listenerFormRef.value.validate()
if (!validateStatus) return // 验证不通过直接返回
const listenerObject = createListenerObject(listenerForm.value, true, prefix)
if (editingListenerIndex.value === -1) {
bpmnElementListeners.value.push(listenerObject)
elementListenersList.value.push(listenerForm.value)
} else {
bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value)
}
// 保存其他配置
otherExtensionList.value =
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type !== `${prefix}:TaskListener`
) ?? []
updateElementExtensions(
bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value)
)
// 4. 隐藏侧边栏
listenerFormModelVisible.value = false
listenerForm.value = {}
}
// 打开监听器字段编辑弹窗
const openListenerFieldForm = (field, index?) => {
listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {}
editingListenerFieldIndex.value = field ? index : -1
listenerFieldFormModelVisible.value = true
nextTick(() => {
if (listenerFieldFormRef.value) listenerFieldFormRef.value.clearValidate()
})
}
// 保存监听器注入字段
const saveListenerFiled = async () => {
let validateStatus = await listenerFieldFormRef.value.validate()
if (!validateStatus) return // 验证不通过直接返回
if (editingListenerFieldIndex.value === -1) {
fieldsListOfListener.value.push(listenerFieldForm.value)
listenerForm.value.fields.push(listenerFieldForm.value)
} else {
fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
}
listenerFieldFormModelVisible.value = false
nextTick(() => {
listenerFieldForm.value = {}
})
}
// 移除监听器字段
const removeListenerField = (field, index) => {
console.log(field, 'field')
ElMessageBox.confirm('确认移除该字段吗?', '提示', {
confirmButtonText: '确 认',
cancelButtonText: '取 消'
})
.then(() => {
fieldsListOfListener.value.splice(index, 1)
listenerForm.value.fields.splice(index, 1)
})
.catch(() => console.info('操作取消'))
}
// 打开监听器弹窗
const processListenerDialogRef = ref()
const openProcessListenerDialog = async () => {
processListenerDialogRef.value.open('task')
}
const selectProcessListener = (listener) => {
const listenerForm = initListenerForm2(listener)
const listenerObject = createListenerObject(listenerForm, true, prefix)
bpmnElementListeners.value.push(listenerObject)
elementListenersList.value.push(listenerForm)
// 保存其他配置
otherExtensionList.value =
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type !== `${prefix}:TaskListener`
) ?? []
updateElementExtensions(
bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value)
)
}
watch(
() => props.id,
(val) => {
val &&
val.length &&
nextTick(() => {
resetListenersList()
})
},
{ immediate: true }
)
</script>
<template>
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="small" border>
<el-table-column label="序号" width="80px" type="index" />
<el-table-column
label="事件类型"
min-width="80px"
show-overflow-tooltip
:formatter="(row) => listenerEventTypeObject[row.event]"
/>
<el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip />
<el-table-column
label="监听器类型"
min-width="80px"
show-overflow-tooltip
:formatter="(row) => listenerTypeObject[row.listenerType]"
/>
<el-table-column label="操作" width="90px">
<template #default="scope">
<el-button size="small" link @click="openListenerForm(scope.row, scope.$index)"
>编辑</el-button
>
<el-divider direction="vertical" />
<el-button
size="small"
link
style="color: #ff4d4f"
@click="removeListener(scope.row, scope.$index)"
>移除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<XButton
size="small"
type="primary"
preIcon="ep:plus"
title="添加监听器"
@click="openListenerForm(null)"
/>
<XButton
type="success"
preIcon="ep:select"
title="选择监听器"
size="small"
@click="openProcessListenerDialog"
/>
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer
v-model="listenerFormModelVisible"
title="任务监听器"
:size="`${width}px`"
append-to-body
destroy-on-close
>
<el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef">
<el-form-item
label="事件类型"
prop="event"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-select v-model="listenerForm.event">
<el-option
v-for="i in Object.keys(listenerEventTypeObject)"
:key="i"
:label="listenerEventTypeObject[i]"
:value="i"
/>
</el-select>
</el-form-item>
<el-form-item
label="监听器ID"
prop="id"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.id" clearable />
</el-form-item>
<el-form-item
label="监听器类型"
prop="listenerType"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-select v-model="listenerForm.listenerType">
<el-option
v-for="i in Object.keys(listenerTypeObject)"
:key="i"
:label="listenerTypeObject[i]"
:value="i"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'classListener'"
label="Java类"
prop="class"
key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.class" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式"
prop="expression"
key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.expression" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式"
prop="delegateExpression"
key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item
label="脚本格式"
prop="scriptFormat"
key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
>
<el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item>
<el-form-item
label="脚本类型"
prop="scriptType"
key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
>
<el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容"
prop="value"
key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
>
<el-input v-model="listenerForm.value" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址"
prop="resource"
key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
>
<el-input v-model="listenerForm.resource" clearable />
</el-form-item>
</template>
<template v-if="listenerForm.event === 'timeout'">
<el-form-item label="定时器类型" prop="eventDefinitionType" key="eventDefinitionType">
<el-select v-model="listenerForm.eventDefinitionType">
<el-option label="统计时间" value="date" />
<el-option label="持续时长" value="duration" />
<el-option label="循环" value="cycle" />
<el-option label="无" value="null" />
</el-select>
</el-form-item>
<el-form-item
v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
label="定时器"
prop="eventTimeDefinitions"
key="eventTimeDefinitions"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写定时器配置' }"
>
<el-input v-model="listenerForm.eventTimeDefinitions" clearable />
</el-form-item>
</template>
</el-form>
<el-divider />
<p class="listener-filed__title">
<span><Icon icon="ep:menu" />注入字段</span>
<el-button size="small" type="primary" @click="openListenerFieldForm(null)"
>添加字段</el-button
>
</p>
<el-table
:data="fieldsListOfListener"
size="small"
max-height="240"
fit
border
style="flex: none"
>
<el-table-column label="序号" width="80px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column
label="字段类型"
min-width="80px"
show-overflow-tooltip
:formatter="(row) => fieldTypeObject[row.fieldType]"
/>
<el-table-column
label="字段值/表达式"
min-width="100px"
show-overflow-tooltip
:formatter="(row) => row.string || row.expression"
/>
<el-table-column label="操作" width="100px">
<template #default="scope">
<el-button size="small" link @click="openListenerFieldForm(scope.row, scope.$index)"
>编辑</el-button
>
<el-divider direction="vertical" />
<el-button
size="small"
link
style="color: #ff4d4f"
@click="removeListenerField(scope.row, scope.$index)"
>移除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="small" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog
title="字段配置"
v-model="listenerFieldFormModelVisible"
width="600px"
append-to-body
destroy-on-close
>
<el-form
:model="listenerFieldForm"
size="small"
label-width="96px"
ref="listenerFieldFormRef"
style="height: 136px"
>
<el-form-item
label="字段名称:"
prop="name"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item
label="字段类型:"
prop="fieldType"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-select v-model="listenerFieldForm.fieldType">
<el-option
v-for="i in Object.keys(fieldTypeObject)"
:key="i"
:label="fieldTypeObject[i]"
:value="i"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button size="small" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
<!-- 选择弹窗 -->
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
</template>
<script lang="ts" setup>
import { ElMessageBox } from 'element-plus'
import { createListenerObject, updateElementExtensions } from '../../utils'
import {
initListenerForm,
initListenerType,
eventType,
listenerType,
fieldType,
initListenerForm2
} from './utilSelf'
import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
defineOptions({ name: 'UserTaskListeners' })
const props = defineProps({
id: String,
type: String
})
const prefix = inject('prefix')
const width = inject('width')
const elementListenersList = ref<any[]>([])
const listenerEventTypeObject = ref(eventType)
const listenerTypeObject = ref(listenerType)
const listenerFormModelVisible = ref(false)
const listenerForm = ref<any>({})
const fieldTypeObject = ref(fieldType)
const fieldsListOfListener = ref<any[]>([])
const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态
const editingListenerIndex = ref(-1) // 监听器所在下标,-1 为新增
const editingListenerFieldIndex = ref(-1) // 字段所在下标,-1 为新增
const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单
const bpmnElement = ref()
const bpmnElementListeners = ref()
const otherExtensionList = ref()
const listenerFormRef = ref()
const listenerFieldFormRef = ref()
const bpmnInstances = () => (window as any)?.bpmnInstances
const resetListenersList = () => {
// console.log(
// bpmnInstances().bpmnElement,
// 'window.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElement'
// )
bpmnElement.value = bpmnInstances().bpmnElement
otherExtensionList.value = []
bpmnElementListeners.value =
bpmnElement.value.businessObject?.extensionElements?.values.filter(
(ex) => ex.$type === `${prefix}:TaskListener`
) ?? []
elementListenersList.value = bpmnElementListeners.value.map((listener) =>
initListenerType(listener)
)
}
const openListenerForm = (listener, index?) => {
if (listener) {
listenerForm.value = initListenerForm(listener)
editingListenerIndex.value = index
} else {
listenerForm.value = {}
editingListenerIndex.value = -1 // 标记为新增
}
if (listener && listener.fields) {
fieldsListOfListener.value = listener.fields.map((field) => ({
...field,
fieldType: field.string ? 'string' : 'expression'
}))
} else {
fieldsListOfListener.value = []
listenerForm.value['fields'] = []
}
// 打开侧边栏并清楚验证状态
listenerFormModelVisible.value = true
nextTick(() => {
if (listenerFormRef.value) listenerFormRef.value.clearValidate()
})
}
// 移除监听器
const removeListener = (listener, index?) => {
console.log(listener, 'listener')
ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
confirmButtonText: '确 认',
cancelButtonText: '取 消'
})
.then(() => {
bpmnElementListeners.value.splice(index, 1)
elementListenersList.value.splice(index, 1)
updateElementExtensions(
bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value)
)
})
.catch(() => console.info('操作取消'))
}
// 保存监听器
const saveListenerConfig = async () => {
let validateStatus = await listenerFormRef.value.validate()
if (!validateStatus) return // 验证不通过直接返回
const listenerObject = createListenerObject(listenerForm.value, true, prefix)
if (editingListenerIndex.value === -1) {
bpmnElementListeners.value.push(listenerObject)
elementListenersList.value.push(listenerForm.value)
} else {
bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value)
}
// 保存其他配置
otherExtensionList.value =
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type !== `${prefix}:TaskListener`
) ?? []
updateElementExtensions(
bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value)
)
// 4. 隐藏侧边栏
listenerFormModelVisible.value = false
listenerForm.value = {}
}
// 打开监听器字段编辑弹窗
const openListenerFieldForm = (field, index?) => {
listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {}
editingListenerFieldIndex.value = field ? index : -1
listenerFieldFormModelVisible.value = true
nextTick(() => {
if (listenerFieldFormRef.value) listenerFieldFormRef.value.clearValidate()
})
}
// 保存监听器注入字段
const saveListenerFiled = async () => {
let validateStatus = await listenerFieldFormRef.value.validate()
if (!validateStatus) return // 验证不通过直接返回
if (editingListenerFieldIndex.value === -1) {
fieldsListOfListener.value.push(listenerFieldForm.value)
listenerForm.value.fields.push(listenerFieldForm.value)
} else {
fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
}
listenerFieldFormModelVisible.value = false
nextTick(() => {
listenerFieldForm.value = {}
})
}
// 移除监听器字段
const removeListenerField = (field, index) => {
console.log(field, 'field')
ElMessageBox.confirm('确认移除该字段吗?', '提示', {
confirmButtonText: '确 认',
cancelButtonText: '取 消'
})
.then(() => {
fieldsListOfListener.value.splice(index, 1)
listenerForm.value.fields.splice(index, 1)
})
.catch(() => console.info('操作取消'))
}
// 打开监听器弹窗
const processListenerDialogRef = ref()
const openProcessListenerDialog = async () => {
processListenerDialogRef.value.open('task')
}
const selectProcessListener = (listener) => {
const listenerForm = initListenerForm2(listener)
const listenerObject = createListenerObject(listenerForm, true, prefix)
bpmnElementListeners.value.push(listenerObject)
elementListenersList.value.push(listenerForm)
// 保存其他配置
otherExtensionList.value =
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type !== `${prefix}:TaskListener`
) ?? []
updateElementExtensions(
bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value)
)
}
watch(
() => props.id,
(val) => {
val &&
val.length &&
nextTick(() => {
resetListenersList()
})
},
{ immediate: true }
)
</script>

View File

@@ -364,6 +364,7 @@ watch(
)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints {
display: flex;
.statistics {

View File

@@ -340,6 +340,7 @@ watch(
)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints {
display: flex;
.statistics {

View File

@@ -177,7 +177,9 @@ const tableStore: any = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList
abnormal.value = tableStore.table.data.citDetailList.filter(
(k: any) => k.citName != '上送国网' && k.citName != '非上送国网'
)
}
})
tableStore.table.params.deptIndex = dictData.state.area[0].id
@@ -338,6 +340,7 @@ watch(
)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints {
display: flex;
.statistics {

View File

@@ -18,24 +18,48 @@
>
<div style="flex: 1">
<div class="title">终端统计</div>
<div style="height: 135px" class="box1">
<div class="boxDiv hexagon">
<div style="color: #fff">{{ statisticsList.allNum }}</div>
<div class="mt10 divBot">总数</div>
<div
class="box1"
:style="{
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px - 30px )`,
overflow: 'auto'
}"
>
<div class="statistics">
<div class="divBox div1">
<span class="iconfont icon-qiyezongshu" style="color: #57bc6e"></span>
<span class="divBox_title">终端总数</span>
<span class="divBox_num text-style" style="color: #57bc6e">
{{ statisticsList.allNum }}
</span>
</div>
<div class="divBox div2">
<span class="iconfont icon-zaiyunshebei" style="color: #67c23a"></span>
<span class="divBox_title">在运终端数</span>
<span class="divBox_num text-style" style="color: #67c23a">
{{ statisticsList.runNum }}
</span>
</div>
</div>
<div class="boxDiv hexagon hexagon1">
<div style="color: #fff">{{ statisticsList.runNum }}</div>
<div class="mt10 divBot">在运</div>
</div>
</div>
<div style="height: 135px" class="box1">
<div class="boxDiv hexagon hexagon2">
<div style="color: #fff">{{ statisticsList.checkNum }}</div>
<div class="mt10 divBot">调试</div>
</div>
<div class="boxDiv hexagon hexagon3">
<div style="color: #fff">{{ statisticsList.stopRunNum }}</div>
<div class="mt10 divBot">停运</div>
<div class="statistics">
<div class="divBox div3">
<span
class="iconfont icon-yichanglei_14feizhinengbiaozaiyunyichang"
style="color: #ffbf00"
></span>
<span class="divBox_title">调试终端数</span>
<span class="divBox_num text-style" style="color: #ffbf00">
{{ statisticsList.checkNum }}
</span>
</div>
<div class="divBox div4">
<span class="iconfont icon-tingyunshijianguanli" style="color: #f56c6c"></span>
<span class="divBox_title">停运终端数</span>
<span class="divBox_num text-style" style="color: #f56c6c">
{{ statisticsList.stopRunNum }}
</span>
</div>
</div>
</div>
</div>
@@ -65,7 +89,7 @@
<span style="width: 90px">终端总数</span>
<span style="flex: 1">完整性(%)</span>
<span style="flex: 1">在线率(%)</span>
<span style="flex: 1">合格(%)</span>
<span style="flex: 1">异常(%)</span>
</div>
<div
:style="{
@@ -205,7 +229,7 @@ const tableStore: any = new TableStore({
statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length
statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length
abnormal.value = tableStore.table.data
abnormal.value = tableStore.table.data.filter((k: any) => k.name != '上送国网' && k.name != '非上送国网')
}
})
tableStore.table.params.deptIndex = dictData.state.area[0].id
@@ -234,6 +258,7 @@ watch(
)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints {
display: flex;
}
@@ -344,32 +369,7 @@ watch(
color: #fff;
border-radius: 8px;
}
.box1 {
display: flex;
align-items: center;
justify-content: space-around;
.boxDiv {
// flex: 1;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
margin: 0 5px;
div:nth-child(1) {
position: absolute;
font-size: 30px;
top: -10px;
font-weight: 700;
}
.divBot {
font-size: 16px;
position: absolute;
top: 20px;
}
color: #fff;
}
}
.hexagon {
position: relative;
width: 100px;
@@ -427,4 +427,44 @@ watch(
border-top: 27.5px solid #a52a2a;
}
}
.statistics {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.divBox {
width: 100%;
height: 70px;
padding: 10px;
display: flex;
margin-bottom: 10px;
.iconfont {
font-size: 40px;
margin-right: 5px;
}
.divBox_title {
font-weight: 550;
}
.divBox_num {
font-size: 20px;
font-weight: 550;
margin-left: auto;
font-family: AlimamaDongFangDaKai;
}
align-items: center;
// text-align: center;
border-radius: 5px;
}
.div1 {
background-color: #eef8f0;
}
.div2 {
background-color: #67c23a24;
}
.div3 {
background-color: #ffbf0024;
}
.div4 {
background-color: #f56c6c24;
}
}
</style>

View File

@@ -11,7 +11,7 @@
>
<el-form-item v-if="datePicker" style="grid-column: span 2; max-width: 630px">
<template #label>
<el-checkbox v-if="showTimeAll" v-model="timeAll" label="时间" />
<el-checkbox v-if="showTimeAll" v-model="timeAll" label="统计时间" />
<span v-else>{{ dateLabel }}</span>
</template>
<DatePicker
@@ -111,7 +111,7 @@ const props = withDefaults(defineProps<Props>(), {
showReset: true,
showExport: false,
showTimeAll: false,
dateLabel: '时间'
dateLabel: '统计日期'
})
// 动态计算table高度
const resizeObserver = new ResizeObserver(entries => {

View File

@@ -362,3 +362,4 @@ export function getTimeOfTheMonth(key: string): [string, string] {
throw new Error('Invalid key')
}
}

View File

@@ -14,7 +14,7 @@
<pane style="background: #fff">
<TableHeader :showSearch="false" v-show="props.rowList.id == undefined">
<template #select>
<el-form-item label="时间">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
</template>

View File

@@ -2,7 +2,7 @@
<div class="default-main">
<TableHeader :showSearch="false" v-show="flag">
<template v-slot:select>
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker
ref="datePickerRef"
:nextFlag="false"

View File

@@ -6,7 +6,7 @@
</div> -->
<TableHeader :showSearch="false">
<template v-slot:select>
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef" :nextFlag="false" :theCurrentTime="true"></DatePicker>
</el-form-item>
</template>

View File

@@ -2,7 +2,7 @@
<div class="default-main">
<TableHeader :showSearch="false" v-show="flag">
<template v-slot:select>
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker
ref="datePickerRef"
:nextFlag="false"

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader date-picker ref="TableHeaderRef" :dateLabel="`数据统计时间`">
<TableHeader date-picker ref="TableHeaderRef" >
<template v-slot:select>
<el-form-item label="运行状态">
<el-select v-model="tableStore.table.params.lineRunFlag" clearable placeholder="请选择运行状态">
@@ -474,6 +474,7 @@ tableStore.table.params.name = ''
provide('tableStore', tableStore)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.card-list {
display: flex;
.monitoringPoints {

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader date-picker ref="TableHeaderRef" :dateLabel="`数据统计时间`">
<TableHeader date-picker ref="TableHeaderRef">
<template v-slot:select>
<el-form-item label="运行状态">
<el-select v-model="tableStore.table.params.lineRunFlag" clearable placeholder="请选择运行状态">
@@ -34,7 +34,11 @@
<div class="divBox">
<span class="iconfont icon-qiyezongshu" style="color: #57bc6e"></span>
<span class="divBox_title">终端总数</span>
<span class="divBox_num text-style" style="color: #57bc6e" @click="totalTable(100001, '')">
<span
class="divBox_num text-style"
style="color: #57bc6e"
@click="totalTable(100001, '')"
>
{{ monitoringPoints.runNum }}
</span>
</div>
@@ -200,6 +204,7 @@
</template>
<script setup lang="ts">
// import '@/assets/font/iconfont.css'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
@@ -262,10 +267,13 @@ const tableStore = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList
abnormal.value = tableStore.table.data.citDetailList.filter(
(k: any) => k.citName != '上送国网' && k.citName != '非上送国网'
)
// 合并子集数据 并去重
totalData.value = Array.from(
tableStore.table.data.citDetailList
.map((item: any) => item.detailList)
.flat()
.reduce((map: any, item: any) => {
@@ -470,6 +478,7 @@ tableStore.table.params.name = ''
provide('tableStore', tableStore)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.card-list {
display: flex;
.monitoringPoints {

View File

@@ -1,430 +1,430 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%; position: relative">
<el-form :inline="true">
<el-form-item label="多监测点">
<el-checkbox v-model="checked" @change="checkChange" />
</el-form-item>
<el-form-item label="日期">
<DatePicker ref="datePickerRef" ></DatePicker>
</el-form-item>
<el-form-item label="指标类型:">
<el-select
v-model="formData.condition"
multiple
collapse-tags
:multiple-limit="5"
filterable
placeholder="请选择指标"
@change="conditionChange"
>
<el-option-group v-for="group in indexOptions" :key="group.label" :label="group.label">
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-if="showXieBoCiShu">
<el-select style="width: 100%" v-model="formData.harmonic" placeholder="请选择谐波">
<el-option
v-for="item in harmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="showJianXieBoCiShu" label="间谐波次数:">
<el-select style="width: 100%" v-model="formData.inHarmonic" placeholder="请选择间谐波">
<el-option
v-for="item in inharmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
<div style="flex: 1; overflow: hidden" class="mt10" v-loading="loading">
<vxe-table height="auto" v-bind="defaultAttribute" :data="tableData">
<vxe-column field="subName" title="变电站" min-width="120px"></vxe-column>
<vxe-column field="lineName" title="监测点名称" min-width="120px"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="120px"></vxe-column>
<vxe-column field="phaseType" title="相别" min-width="100px"></vxe-column>
<vxe-column field="scale" title="电压等级" min-width="100px"></vxe-column>
<vxe-column field="timeId" title="时间" min-width="130px"></vxe-column>
<vxe-column field="unit" title="单位" min-width="100px"></vxe-column>
<vxe-column field="maxData" title="最大值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 3, '最大值')"
:style="{ color: scope.row.statisticalType === 3 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.maxData }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
<vxe-column field="minData" title="最小值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 2, '最小值')"
:style="{ color: scope.row.statisticalType === 2 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.minData }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
<vxe-column field="avgData" title="平均值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 1, '平均值')"
:style="{ color: scope.row.statisticalType === 1 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.avgData }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
<vxe-column field="cp95Data" title="CP95值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 4, 'CP95值')"
:style="{ color: scope.row.statisticalType === 4 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.cp95Data }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
</vxe-table>
<SecondSheet v-if="options" style="background: #fff; z-index: 10">
<el-button
style="position: absolute; right: 0; top: 0; cursor: pointer; z-index: 3"
icon="el-icon-Back"
size="small"
@click="close"
>
返回
</el-button>
<MyEChart :options="options"></MyEChart>
</SecondSheet>
</div>
</div>
</template>
<script setup lang="ts">
import { nextTick, onMounted, reactive, ref } from 'vue'
import { Close } from '@element-plus/icons-vue'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { indexOptions, harmonicOptions, inharmonicOptions } from '@/utils/dictionary'
import { getHistoryTableData, getHistoryLineData } from '@/api/harmonic-boot/normLimit'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import SecondSheet from '@/components/secondSheet/index.vue'
import MyEChart from '@/components/echarts/MyEchart.vue'
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const checked = ref(monitoringPoint.state.showCheckBox)
const formData = reactive<{
lineId: string[]
searchBeginTime: string
searchEndTime: string
condition: string[]
harmonic: number
inHarmonic: number
}>({
lineId: [],
searchBeginTime: '',
searchEndTime: '',
condition: ['10', '11', '12'],
harmonic: 2,
inHarmonic: 1
})
const tableData = ref([])
const showXieBoCiShu = ref(false)
const showJianXieBoCiShu = ref(false)
const options = ref<any>(null)
onMounted(() => {
init()
})
const init = () => {
loading.value = true
formData.lineId = checked.value ? monitoringPoint.state.lineIds : [monitoringPoint.state.lineId]
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
getHistoryTableData(formData).then((res: any) => {
tableData.value = res.data.map((item: any) => {
return {
...item,
maxData: item.maxData.toFixed(2),
minData: item.minData.toFixed(2),
avgData: item.avgData.toFixed(2),
cp95Data: item.cp95Data.toFixed(2)
}
})
nextTick(() => {
loading.value = false
})
})
}
const checkChange = () => {
if (checked.value) {
monitoringPoint.setShowCheckBox(true)
} else {
monitoringPoint.setShowCheckBox(false)
init()
}
}
const close = () => {
console.log('====================================')
console.log(2123123)
console.log('====================================')
options.value = null
}
const showCharts = (row: any, valueType: number, name: string) => {
getHistoryLineData({
lineId: row.lineId,
number: row.number,
phaseType: row.phaseType,
searchTime: row.timeId,
targetCode: row.targetCode,
valueType
}).then(res => {
options.value = {
title: {
text: row.subName + ' ' + row.lineName + ' ' + row.targetName + ' ' + row.phaseType + '相' + name
},
legend: {
show: false
},
xAxis: {
type: 'category',
name: '时间',
data: res.data[0]?.value.map((item: any[]) => item[0])
},
yAxis: {
name: '%',
type: 'value'
},
series: [
{
name: name,
data: res.data[0]?.value.map((item: any[]) => item[1]),
type: 'line'
}
],
options: {
grid: {
top: '50px',
left: '40px',
right: '60px',
bottom: '10px',
containLabel: true
},
dataZoom: null
}
}
})
}
const conditionChange = () => {
//判断一个指标时
if (formData.condition.length == 1) {
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
}
//判断2个指标时
if (formData.condition.length == 2) {
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
(formData.condition.includes('45') && formData.condition.includes('46')) ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
}
//判断3个指标时
if (formData.condition.length == 3) {
if (
(formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')) &&
(formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49'))
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
}
//判断4个指标时
if (formData.condition.length == 4) {
if (
(formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')) &&
(formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49'))
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
}
//判断5个指标时
if (formData.condition.length == 5) {
if (
(formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')) &&
(formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49'))
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
}
//判断无指标时
if (formData.condition.length == 0) {
showJianXieBoCiShu.value = false
showXieBoCiShu.value = false
}
}
</script>
<style></style>
<template>
<div style="display: flex; flex-direction: column; height: 100%; position: relative">
<el-form :inline="true">
<el-form-item label="多监测点">
<el-checkbox v-model="checked" @change="checkChange" />
</el-form-item>
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef" ></DatePicker>
</el-form-item>
<el-form-item label="指标类型:">
<el-select
v-model="formData.condition"
multiple
collapse-tags
:multiple-limit="5"
filterable
placeholder="请选择指标"
@change="conditionChange"
>
<el-option-group v-for="group in indexOptions" :key="group.label" :label="group.label">
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-if="showXieBoCiShu">
<el-select style="width: 100%" v-model="formData.harmonic" placeholder="请选择谐波">
<el-option
v-for="item in harmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="showJianXieBoCiShu" label="间谐波次数:">
<el-select style="width: 100%" v-model="formData.inHarmonic" placeholder="请选择间谐波">
<el-option
v-for="item in inharmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
<div style="flex: 1; overflow: hidden" class="mt10" v-loading="loading">
<vxe-table height="auto" v-bind="defaultAttribute" :data="tableData">
<vxe-column field="subName" title="变电站" min-width="120px"></vxe-column>
<vxe-column field="lineName" title="监测点名称" min-width="120px"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="120px"></vxe-column>
<vxe-column field="phaseType" title="相别" min-width="100px"></vxe-column>
<vxe-column field="scale" title="电压等级" min-width="100px"></vxe-column>
<vxe-column field="timeId" title="时间" min-width="130px"></vxe-column>
<vxe-column field="unit" title="单位" min-width="100px"></vxe-column>
<vxe-column field="maxData" title="最大值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 3, '最大值')"
:style="{ color: scope.row.statisticalType === 3 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.maxData }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
<vxe-column field="minData" title="最小值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 2, '最小值')"
:style="{ color: scope.row.statisticalType === 2 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.minData }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
<vxe-column field="avgData" title="平均值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 1, '平均值')"
:style="{ color: scope.row.statisticalType === 1 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.avgData }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
<vxe-column field="cp95Data" title="CP95值(%)" min-width="100px">
<template #default="scope">
<el-button
@click="showCharts(scope.row, 4, 'CP95值')"
:style="{ color: scope.row.statisticalType === 4 ? '#A52a2a' : '#07d75a' }"
type="text"
size="small"
>
{{ scope.row.cp95Data }}
</el-button>
<el-button v-if="scope.row.statisticalType === 3.14159">/</el-button>
</template>
</vxe-column>
</vxe-table>
<SecondSheet v-if="options" style="background: #fff; z-index: 10">
<el-button
style="position: absolute; right: 0; top: 0; cursor: pointer; z-index: 3"
icon="el-icon-Back"
size="small"
@click="close"
>
返回
</el-button>
<MyEChart :options="options"></MyEChart>
</SecondSheet>
</div>
</div>
</template>
<script setup lang="ts">
import { nextTick, onMounted, reactive, ref } from 'vue'
import { Close } from '@element-plus/icons-vue'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { indexOptions, harmonicOptions, inharmonicOptions } from '@/utils/dictionary'
import { getHistoryTableData, getHistoryLineData } from '@/api/harmonic-boot/normLimit'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import SecondSheet from '@/components/secondSheet/index.vue'
import MyEChart from '@/components/echarts/MyEchart.vue'
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const checked = ref(monitoringPoint.state.showCheckBox)
const formData = reactive<{
lineId: string[]
searchBeginTime: string
searchEndTime: string
condition: string[]
harmonic: number
inHarmonic: number
}>({
lineId: [],
searchBeginTime: '',
searchEndTime: '',
condition: ['10', '11', '12'],
harmonic: 2,
inHarmonic: 1
})
const tableData = ref([])
const showXieBoCiShu = ref(false)
const showJianXieBoCiShu = ref(false)
const options = ref<any>(null)
onMounted(() => {
init()
})
const init = () => {
loading.value = true
formData.lineId = checked.value ? monitoringPoint.state.lineIds : [monitoringPoint.state.lineId]
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
getHistoryTableData(formData).then((res: any) => {
tableData.value = res.data.map((item: any) => {
return {
...item,
maxData: item.maxData.toFixed(2),
minData: item.minData.toFixed(2),
avgData: item.avgData.toFixed(2),
cp95Data: item.cp95Data.toFixed(2)
}
})
nextTick(() => {
loading.value = false
})
})
}
const checkChange = () => {
if (checked.value) {
monitoringPoint.setShowCheckBox(true)
} else {
monitoringPoint.setShowCheckBox(false)
init()
}
}
const close = () => {
console.log('====================================')
console.log(2123123)
console.log('====================================')
options.value = null
}
const showCharts = (row: any, valueType: number, name: string) => {
getHistoryLineData({
lineId: row.lineId,
number: row.number,
phaseType: row.phaseType,
searchTime: row.timeId,
targetCode: row.targetCode,
valueType
}).then(res => {
options.value = {
title: {
text: row.subName + ' ' + row.lineName + ' ' + row.targetName + ' ' + row.phaseType + '相' + name
},
legend: {
show: false
},
xAxis: {
type: 'category',
name: '时间',
data: res.data[0]?.value.map((item: any[]) => item[0])
},
yAxis: {
name: '%',
type: 'value'
},
series: [
{
name: name,
data: res.data[0]?.value.map((item: any[]) => item[1]),
type: 'line'
}
],
options: {
grid: {
top: '50px',
left: '40px',
right: '60px',
bottom: '10px',
containLabel: true
},
dataZoom: null
}
}
})
}
const conditionChange = () => {
//判断一个指标时
if (formData.condition.length == 1) {
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
}
//判断2个指标时
if (formData.condition.length == 2) {
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
(formData.condition.includes('45') && formData.condition.includes('46')) ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
}
//判断3个指标时
if (formData.condition.length == 3) {
if (
(formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')) &&
(formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49'))
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
}
//判断4个指标时
if (formData.condition.length == 4) {
if (
(formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')) &&
(formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49'))
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
}
//判断5个指标时
if (formData.condition.length == 5) {
if (
(formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')) &&
(formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49'))
) {
showXieBoCiShu.value = true
showJianXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('46') ||
// formData.condition.includes('47') ||
// formData.condition.includes('48') ||
formData.condition.includes('49')
) {
showJianXieBoCiShu.value = true
} else {
showJianXieBoCiShu.value = false
}
if (
formData.condition.includes('40') ||
formData.condition.includes('43') ||
formData.condition.includes('44') ||
formData.condition.includes('45')
) {
showXieBoCiShu.value = true
} else {
showXieBoCiShu.value = false
}
}
//判断无指标时
if (formData.condition.length == 0) {
showJianXieBoCiShu.value = false
showXieBoCiShu.value = false
}
}
</script>
<style></style>

View File

@@ -6,7 +6,7 @@
<el-form-item label="多监测点">
<el-checkbox v-model="checked" @change="checkChange" />
</el-form-item>
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef" :theCurrentTime="true"></DatePicker>
</el-form-item>
<el-form-item label="指标类型:">

View File

@@ -1,315 +1,315 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<TableHeader ref="TableHeaderRef" :showSearch="false">
<template v-slot:select>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="对比">
<el-select v-model="searchType" clearable placeholder="可选择同比、环比">
<el-option
v-for="item in searchTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</template>
</TableHeader>
<div style="flex: 1" class="mt10" v-loading="loading">
<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 '@/stores/monitoringPoint'
import { getSteadyData } from '@/api/harmonic-boot/pollution'
import { gradeColor3 } from '@/components/echarts/color'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const formData = reactive({
id: '',
searchBeginTime: '',
searchEndTime: '',
periodBeginTime: '',
periodEndTime: ''
})
const options = ref({})
const searchType = ref('')
const searchTypeOptions = [
{
label: '同比',
value: '1'
},
{
label: '环比',
value: '2'
}
]
const gradeNames = ['优质', '良好', '一般', '较差', '极差']
const init = () => {
loading.value = true
formData.id = monitoringPoint.state.lineId
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
if (searchType.value == '1') {
;[formData.periodBeginTime, formData.periodEndTime] = datePickerRef.value.getYearOnYear(
formData.searchBeginTime,
formData.searchEndTime
)
} else if (searchType.value == '2') {
;[formData.periodBeginTime, formData.periodEndTime] = datePickerRef.value.getMonthOnMonth(
formData.searchBeginTime,
formData.searchEndTime
)
} else {
formData.periodBeginTime = ''
formData.periodEndTime = ''
}
getSteadyData(formData).then((res: any) => {
const { steadyInfoData, steadyInfoList } = res.data
let yData = [],
yData2 = []
for (let i = 0; i < steadyInfoList.length; i++) {
// if (steadyInfoList[i] == 3.1415) {
// steadyInfoList[i] = 1
// yData.push(steadyInfoList[i])
// } else if (steadyInfoList[i] == 3.14159) {
// steadyInfoList[i] = 1
// yData.push(steadyInfoList[i])
// } else if (steadyInfoList[i] !== 3.14159) {
yData.push(steadyInfoList[i])
// }
}
for (let i = 0; i < steadyInfoData.length; i++) {
yData2.push(steadyInfoData[i])
// if (steadyInfoData[i] == 3.14159) {
// steadyInfoData[i] = 0
// yData2.push(steadyInfoData[i])
// } else if (steadyInfoData[i] == 3.14159) {
// steadyInfoData[i] = 0
// yData2.push(steadyInfoData[i])
// } else if (steadyInfoData[i] !== 3.14159) {
// yData2.push(steadyInfoData[i])
// }
}
let series: any[] = [
{
name: formData.searchBeginTime + '至' + formData.searchEndTime,
type: 'bar',
barMaxWidth: 30,
label: {
show: true,
position: 'top',
distance: 2,
color: '#fff',
fontWeight: 'bolder'
},
data: yData,
markLine: {
silent: false,
symbol: 'circle',
data: [
{
name: '',
yAxis: 100,
lineStyle: {
color: gradeColor3[0]
},
label: {
show: true,
formatter: '优质',
color: gradeColor3[0]
}
},
{
name: '',
yAxis: 90,
lineStyle: {
color: gradeColor3[1]
},
label: {
show: true,
color: gradeColor3[1],
formatter: '良好'
}
},
{
name: '',
yAxis: 60,
lineStyle: {
color: gradeColor3[2]
},
label: {
show: true,
color: gradeColor3[2],
formatter: '合格'
}
}
]
},
itemStyle: {
color: (params: any) => {
if (params.value > 90) {
return gradeColor3[0]
} else if (params.value > 60) {
return gradeColor3[1]
} else if (params.value == 3.14159) {
return '#ccc'
} else {
return gradeColor3[2]
}
}
}
}
]
if (searchType.value) {
series.push({
name: formData.periodBeginTime + '至' + formData.periodEndTime,
type: 'bar',
barMaxWidth: 30,
// label: {
// show: true,
// position: 'top',
// distance: 2,
// color: '#fff',
// fontWeight: 'bolder'
// },
data: yData2,
itemStyle: {
color: (params: any) => {
if (params.value > 90) {
return gradeColor3[0]
} else if (params.value > 60) {
return gradeColor3[1]
} else if (params.value == 3.14159) {
return '#ccc'
} else {
return gradeColor3[2]
}
}
}
})
}
options.value = {
title: {
text: '稳态指标合格率'
},
legend: {
show: false
},
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.55)',
formatter: function (params: any) {
//console.log(params)
let msg = ''
msg += params[0].name + '<br/>'
for (let i in params) {
if (params[i].data == 3.14159) {
msg +=params[i].marker+ params[i].seriesName + ': 暂无数据<br/>'
} else {
msg += params[i].marker+ params[i].seriesName + ': ' + params[i].data + '<br/>'
}
}
return msg
}
},
xAxis: {
name: '指标类型',
type: 'category',
axisLine: {
lineStyle: {
width: 1
},
symbol: ['none', 'arrow']
},
axisLabel: {
textStyle: {
fontFamily: 'dinproRegular'
}
},
data: [
'频率偏差',
'闪变',
'三相电压不平衡',
'谐波电压',
'谐波电流',
'电压偏差',
'负序电流',
'间谐波电压含有率'
]
},
yAxis: [
{
name: '%',
type: 'value',
min: 0,
max: 100,
position: 'left',
splitLine: {
show: false
},
axisLine: {
lineStyle: {
width: 1
},
symbol: ['none', 'arrow']
}
},
{
position: 'left',
axisLine: {
show: true,
symbol: ['none', 'arrow']
},
splitLine: {
//分割线配置
lineStyle: {
color: '#fff'
}
}
}
],
series
}
nextTick(() => {
loading.value = false
})
})
}
provide('tableStore', tableStore)
onMounted(() => {
init()
})
</script>
<style></style>
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<TableHeader ref="TableHeaderRef" :showSearch="false">
<template v-slot:select>
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="对比">
<el-select v-model="searchType" clearable placeholder="可选择同比、环比">
<el-option
v-for="item in searchTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</template>
</TableHeader>
<div style="flex: 1" class="mt10" v-loading="loading">
<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 '@/stores/monitoringPoint'
import { getSteadyData } from '@/api/harmonic-boot/pollution'
import { gradeColor3 } from '@/components/echarts/color'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const formData = reactive({
id: '',
searchBeginTime: '',
searchEndTime: '',
periodBeginTime: '',
periodEndTime: ''
})
const options = ref({})
const searchType = ref('')
const searchTypeOptions = [
{
label: '同比',
value: '1'
},
{
label: '环比',
value: '2'
}
]
const gradeNames = ['优质', '良好', '一般', '较差', '极差']
const init = () => {
loading.value = true
formData.id = monitoringPoint.state.lineId
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
if (searchType.value == '1') {
;[formData.periodBeginTime, formData.periodEndTime] = datePickerRef.value.getYearOnYear(
formData.searchBeginTime,
formData.searchEndTime
)
} else if (searchType.value == '2') {
;[formData.periodBeginTime, formData.periodEndTime] = datePickerRef.value.getMonthOnMonth(
formData.searchBeginTime,
formData.searchEndTime
)
} else {
formData.periodBeginTime = ''
formData.periodEndTime = ''
}
getSteadyData(formData).then((res: any) => {
const { steadyInfoData, steadyInfoList } = res.data
let yData = [],
yData2 = []
for (let i = 0; i < steadyInfoList.length; i++) {
// if (steadyInfoList[i] == 3.1415) {
// steadyInfoList[i] = 1
// yData.push(steadyInfoList[i])
// } else if (steadyInfoList[i] == 3.14159) {
// steadyInfoList[i] = 1
// yData.push(steadyInfoList[i])
// } else if (steadyInfoList[i] !== 3.14159) {
yData.push(steadyInfoList[i])
// }
}
for (let i = 0; i < steadyInfoData.length; i++) {
yData2.push(steadyInfoData[i])
// if (steadyInfoData[i] == 3.14159) {
// steadyInfoData[i] = 0
// yData2.push(steadyInfoData[i])
// } else if (steadyInfoData[i] == 3.14159) {
// steadyInfoData[i] = 0
// yData2.push(steadyInfoData[i])
// } else if (steadyInfoData[i] !== 3.14159) {
// yData2.push(steadyInfoData[i])
// }
}
let series: any[] = [
{
name: formData.searchBeginTime + '至' + formData.searchEndTime,
type: 'bar',
barMaxWidth: 30,
label: {
show: true,
position: 'top',
distance: 2,
color: '#fff',
fontWeight: 'bolder'
},
data: yData,
markLine: {
silent: false,
symbol: 'circle',
data: [
{
name: '',
yAxis: 100,
lineStyle: {
color: gradeColor3[0]
},
label: {
show: true,
formatter: '优质',
color: gradeColor3[0]
}
},
{
name: '',
yAxis: 90,
lineStyle: {
color: gradeColor3[1]
},
label: {
show: true,
color: gradeColor3[1],
formatter: '良好'
}
},
{
name: '',
yAxis: 60,
lineStyle: {
color: gradeColor3[2]
},
label: {
show: true,
color: gradeColor3[2],
formatter: '合格'
}
}
]
},
itemStyle: {
color: (params: any) => {
if (params.value > 90) {
return gradeColor3[0]
} else if (params.value > 60) {
return gradeColor3[1]
} else if (params.value == 3.14159) {
return '#ccc'
} else {
return gradeColor3[2]
}
}
}
}
]
if (searchType.value) {
series.push({
name: formData.periodBeginTime + '至' + formData.periodEndTime,
type: 'bar',
barMaxWidth: 30,
// label: {
// show: true,
// position: 'top',
// distance: 2,
// color: '#fff',
// fontWeight: 'bolder'
// },
data: yData2,
itemStyle: {
color: (params: any) => {
if (params.value > 90) {
return gradeColor3[0]
} else if (params.value > 60) {
return gradeColor3[1]
} else if (params.value == 3.14159) {
return '#ccc'
} else {
return gradeColor3[2]
}
}
}
})
}
options.value = {
title: {
text: '稳态指标合格率'
},
legend: {
show: false
},
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.55)',
formatter: function (params: any) {
//console.log(params)
let msg = ''
msg += params[0].name + '<br/>'
for (let i in params) {
if (params[i].data == 3.14159) {
msg +=params[i].marker+ params[i].seriesName + ': 暂无数据<br/>'
} else {
msg += params[i].marker+ params[i].seriesName + ': ' + params[i].data + '<br/>'
}
}
return msg
}
},
xAxis: {
name: '指标类型',
type: 'category',
axisLine: {
lineStyle: {
width: 1
},
symbol: ['none', 'arrow']
},
axisLabel: {
textStyle: {
fontFamily: 'dinproRegular'
}
},
data: [
'频率偏差',
'闪变',
'三相电压不平衡',
'谐波电压',
'谐波电流',
'电压偏差',
'负序电流',
'间谐波电压含有率'
]
},
yAxis: [
{
name: '%',
type: 'value',
min: 0,
max: 100,
position: 'left',
splitLine: {
show: false
},
axisLine: {
lineStyle: {
width: 1
},
symbol: ['none', 'arrow']
}
},
{
position: 'left',
axisLine: {
show: true,
symbol: ['none', 'arrow']
},
splitLine: {
//分割线配置
lineStyle: {
color: '#fff'
}
}
}
],
series
}
nextTick(() => {
loading.value = false
})
})
}
provide('tableStore', tableStore)
onMounted(() => {
init()
})
</script>
<style></style>

View File

@@ -1,212 +1,212 @@
<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" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
import { getQualityAssessData } from '@/api/harmonic-boot/asses'
import { gradeColor5 } from '@/components/echarts/color'
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const formData = reactive({
id: '',
searchBeginTime: '',
searchEndTime: '',
periodBeginTime: '',
periodEndTime: ''
})
const options = ref({})
const gradeNames = ['优质', '良好', '一般', '较差', '极差']
const grade = gradeColor5.map((item, index) => {
return {
name: gradeNames[index],
color: item
}
})
const init = () => {
loading.value = true
if (!monitoringPoint.state.lineId) {
return
}
formData.id = monitoringPoint.state.lineId
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
getQualityAssessData(formData).then((res: any) => {
let data = res.data.syn[0]
if (data == 3.14159) {
data = 0.25
} else if (data == 3.1415) {
data = 0.15
}
options.value = {
title: {
text: '稳态综合评估',
x: 'center',
y: '0%'
},
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
borderColor: '#fff',
backgroundColor: 'rgba(0,0,0,0.55)',
formatter: function (params: any) {
if (params.value >= 5) {
return params.name + ' : ' + '优质'
} else if (params.value > 4 && params.value <= 5) {
return params.name + ' : ' + '良好'
} else if (params.value > 3 && params.value <= 4) {
return params.name + ' : ' + '合格'
} else if (params.value > 2 && params.value <= 3) {
return params.name + ' : ' + '较差'
} else if (params.value <= 2 && params.value >= 1) {
return params.name + ' : ' + '极差'
} else if (params.value >= 0.25 && params.value < 1) {
return params.name + ' : ' + '暂无数据'
} else if (params.value <= 0.15 && params.value >= 0) {
return params.name + ' : ' + '/'
}
}
},
legend: {
show: false
},
xAxis: [
{
name: '指标',
type: 'category',
data: ['稳态综合评估'],
axisLabel: {
margin: 10
},
axisTick: {
show: false
},
axisLine: {
symbol: ['none', 'arrow']
}
}
],
yAxis: {
name: '等级',
type: 'value',
min: 0,
max: 5,
axisLabel: {
show: true,
// 这里重新定义就可以
formatter: function (value: number) {
var texts = []
if (value === 1) {
texts.push('1级')
} else if (value === 2) {
texts.push('2级')
} else if (value === 3) {
texts.push('3级')
} else if (value === 4) {
texts.push('4级')
} else if (value === 5) {
texts.push('5级')
}
return texts
}
},
axisLine: {
show: true,
symbol: ['none', 'arrow']
}
},
series: [
{
name: '综合评估',
type: 'bar',
label: {
show: true,
position: 'top',
distance: 2,
color: '#fff',
fontWeight: 'bolder'
},
barWidth: '45',
data: [
{
value: data
}
],
markLine: {
silent: false,
symbol: 'circle',
data: grade.map((item, index) => {
return {
yAxis: grade.length - index,
name: item.name,
lineStyle: {
color: item.color
},
label: {
color: item.color,
formatter: item.name
}
}
})
},
itemStyle: {
color: (params: any) => {
if (params.value > 5) {
return gradeColor5[0]
} else if (params.value > 4) {
return gradeColor5[1]
} else if (params.value > 3) {
return gradeColor5[2]
} else if (params.value > 2) {
return gradeColor5[3]
} else {
return gradeColor5[4]
}
}
}
}
],
options: {
dataZoom: null
}
}
nextTick(() => {
loading.value = false
})
})
}
onMounted(() => {
init()
})
</script>
<style></style>
<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" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
import { getQualityAssessData } from '@/api/harmonic-boot/asses'
import { gradeColor5 } from '@/components/echarts/color'
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const formData = reactive({
id: '',
searchBeginTime: '',
searchEndTime: '',
periodBeginTime: '',
periodEndTime: ''
})
const options = ref({})
const gradeNames = ['优质', '良好', '一般', '较差', '极差']
const grade = gradeColor5.map((item, index) => {
return {
name: gradeNames[index],
color: item
}
})
const init = () => {
loading.value = true
if (!monitoringPoint.state.lineId) {
return
}
formData.id = monitoringPoint.state.lineId
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
getQualityAssessData(formData).then((res: any) => {
let data = res.data.syn[0]
if (data == 3.14159) {
data = 0.25
} else if (data == 3.1415) {
data = 0.15
}
options.value = {
title: {
text: '稳态综合评估',
x: 'center',
y: '0%'
},
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
borderColor: '#fff',
backgroundColor: 'rgba(0,0,0,0.55)',
formatter: function (params: any) {
if (params.value >= 5) {
return params.name + ' : ' + '优质'
} else if (params.value > 4 && params.value <= 5) {
return params.name + ' : ' + '良好'
} else if (params.value > 3 && params.value <= 4) {
return params.name + ' : ' + '合格'
} else if (params.value > 2 && params.value <= 3) {
return params.name + ' : ' + '较差'
} else if (params.value <= 2 && params.value >= 1) {
return params.name + ' : ' + '极差'
} else if (params.value >= 0.25 && params.value < 1) {
return params.name + ' : ' + '暂无数据'
} else if (params.value <= 0.15 && params.value >= 0) {
return params.name + ' : ' + '/'
}
}
},
legend: {
show: false
},
xAxis: [
{
name: '指标',
type: 'category',
data: ['稳态综合评估'],
axisLabel: {
margin: 10
},
axisTick: {
show: false
},
axisLine: {
symbol: ['none', 'arrow']
}
}
],
yAxis: {
name: '等级',
type: 'value',
min: 0,
max: 5,
axisLabel: {
show: true,
// 这里重新定义就可以
formatter: function (value: number) {
var texts = []
if (value === 1) {
texts.push('1级')
} else if (value === 2) {
texts.push('2级')
} else if (value === 3) {
texts.push('3级')
} else if (value === 4) {
texts.push('4级')
} else if (value === 5) {
texts.push('5级')
}
return texts
}
},
axisLine: {
show: true,
symbol: ['none', 'arrow']
}
},
series: [
{
name: '综合评估',
type: 'bar',
label: {
show: true,
position: 'top',
distance: 2,
color: '#fff',
fontWeight: 'bolder'
},
barWidth: '45',
data: [
{
value: data
}
],
markLine: {
silent: false,
symbol: 'circle',
data: grade.map((item, index) => {
return {
yAxis: grade.length - index,
name: item.name,
lineStyle: {
color: item.color
},
label: {
color: item.color,
formatter: item.name
}
}
})
},
itemStyle: {
color: (params: any) => {
if (params.value > 5) {
return gradeColor5[0]
} else if (params.value > 4) {
return gradeColor5[1]
} else if (params.value > 3) {
return gradeColor5[2]
} else if (params.value > 2) {
return gradeColor5[3]
} else {
return gradeColor5[4]
}
}
}
}
],
options: {
dataZoom: null
}
}
nextTick(() => {
loading.value = false
})
})
}
onMounted(() => {
init()
})
</script>
<style></style>

View File

@@ -1,136 +1,136 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<TableHeader ref="TableHeaderRef" :showSearch="false">
<template v-slot:select>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="指标">
<el-radio-group v-model="formData.harmState">
<el-radio-button :label="0">谐波电压含有率</el-radio-button>
<el-radio-button :label="1">谐波电流幅值</el-radio-button>
</el-radio-group>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</template>
</TableHeader>
<vxe-table :data="analysisData" v-bind="defaultAttribute">
<vxe-column field="name" title="指标" width="140px"></vxe-column>
<vxe-column
:field="index.toString()"
:title="item + 1 + '次'"
v-for="(item, index) in 49"
width="80px"
></vxe-column>
</vxe-table>
<div style="flex: 1" class="mt10" v-loading="loading">
<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 '@/stores/monitoringPoint'
import { getHarmInHarmData } from '@/api/harmonic-boot/inHarm'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const formData = reactive({
id: monitoringPoint.state.lineId,
searchBeginTime: '',
searchEndTime: '',
harmState: 0
})
const analysisData = ref<any>([])
const options = ref({})
const init = () => {
loading.value = true
formData.id = monitoringPoint.state.lineId
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
getHarmInHarmData(formData).then((res: any) => {
let xName = ''
analysisData.value = []
if (formData.harmState === 1) {
xName = 'A'
analysisData.value.push(
{
name: '谐波电流幅值(A)',
originData: res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? 0.14159 : Math.floor(item * 1000) / 1000
),
...res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? '/' : Math.floor(item * 1000) / 1000
)
},
{
name: '国标限值(A)',
originData: res.data.harmInOverLimit,
...res.data.harmInOverLimit
}
)
} else {
xName = '%'
analysisData.value.push(
{
name: '谐波电压含有率(%)',
originData: res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? 0.14159 : Math.floor(item * 1000) / 1000
),
...res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? '/' : Math.floor(item * 1000) / 1000
)
},
{
name: '国标限值(%)',
originData: res.data.harmInOverLimit,
...res.data.harmInOverLimit
}
)
}
options.value = {
xAxis: {
name: '次数',
type: 'category',
data: Array.from({ length: 49 }, (_, i) => `${i + 2}`)
},
yAxis: {
name: xName,
type: 'value'
},
color: ['#2E8B57', '#DAA520'],
series: analysisData.value.map((item: any) => {
return {
name: item.name,
data: item.originData,
type: 'bar'
}
}),
options: {
// dataZoom: null
}
}
nextTick(() => {
loading.value = false
})
})
}
provide('tableStore', tableStore)
onMounted(() => {
init()
})
</script>
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<TableHeader ref="TableHeaderRef" :showSearch="false">
<template v-slot:select>
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="指标">
<el-radio-group v-model="formData.harmState">
<el-radio-button :label="0">谐波电压含有率</el-radio-button>
<el-radio-button :label="1">谐波电流幅值</el-radio-button>
</el-radio-group>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</template>
</TableHeader>
<vxe-table :data="analysisData" v-bind="defaultAttribute">
<vxe-column field="name" title="指标" width="140px"></vxe-column>
<vxe-column
:field="index.toString()"
:title="item + 1 + '次'"
v-for="(item, index) in 49"
width="80px"
></vxe-column>
</vxe-table>
<div style="flex: 1" class="mt10" v-loading="loading">
<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 '@/stores/monitoringPoint'
import { getHarmInHarmData } from '@/api/harmonic-boot/inHarm'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
const formData = reactive({
id: monitoringPoint.state.lineId,
searchBeginTime: '',
searchEndTime: '',
harmState: 0
})
const analysisData = ref<any>([])
const options = ref({})
const init = () => {
loading.value = true
formData.id = monitoringPoint.state.lineId
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
getHarmInHarmData(formData).then((res: any) => {
let xName = ''
analysisData.value = []
if (formData.harmState === 1) {
xName = 'A'
analysisData.value.push(
{
name: '谐波电流幅值(A)',
originData: res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? 0.14159 : Math.floor(item * 1000) / 1000
),
...res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? '/' : Math.floor(item * 1000) / 1000
)
},
{
name: '国标限值(A)',
originData: res.data.harmInOverLimit,
...res.data.harmInOverLimit
}
)
} else {
xName = '%'
analysisData.value.push(
{
name: '谐波电压含有率(%)',
originData: res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? 0.14159 : Math.floor(item * 1000) / 1000
),
...res.data.harmInHarmValue.map((item: number) =>
item == null || item == 3.14159 ? '/' : Math.floor(item * 1000) / 1000
)
},
{
name: '国标限值(%)',
originData: res.data.harmInOverLimit,
...res.data.harmInOverLimit
}
)
}
options.value = {
xAxis: {
name: '次数',
type: 'category',
data: Array.from({ length: 49 }, (_, i) => `${i + 2}`)
},
yAxis: {
name: xName,
type: 'value'
},
color: ['#2E8B57', '#DAA520'],
series: analysisData.value.map((item: any) => {
return {
name: item.name,
data: item.originData,
type: 'bar'
}
}),
options: {
// dataZoom: null
}
}
nextTick(() => {
loading.value = false
})
})
}
provide('tableStore', tableStore)
onMounted(() => {
init()
})
</script>

View File

@@ -2,7 +2,7 @@
<div style="display: flex; flex-direction: column; height: 100%">
<TableHeader ref="TableHeaderRef" :showSearch="false">
<template v-slot:select>
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="对比">

File diff suppressed because it is too large Load Diff

View File

@@ -1,277 +1,277 @@
<template>
<div class="panorama" :style="height">
<div class="mapBox" v-show="lineInfo">
<DatePicker ref="datePickerRef" style="display: none" theCurrentTime />
<el-form :inline="true" :model="form" class="demo-form-inline">
<el-form-item>
<Area ref="areaRef" :show-all-levels="false" v-model="form.orgNo" style="width: 100px"
@changeValue="changeValue" />
</el-form-item>
<el-form-item>
<el-select v-model="form.isUpToGrid" style="width: 100px" @change="info">
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<div class="Icon" @click="reset">
<Icon name="fa fa-refresh" />
</div>
</el-form-item>
</el-form>
</div>
<!-- 地图 -->
<Map v-if="VITE_FLAG" ref="mapRef" @changeValue="changeValue" :lineInfo="lineInfo" @drop="drop"
@show="infoShow" />
<div v-show="lineInfo">
<!-- 省级 -->
<div v-show="control == 1">
<mapL ref="mapLRef" class="mapL" @LookMap="LookMap" @GridDiagram="GridDiagram" />
<mapR ref="mapRRef" class="mapR" />
</div>
<!-- 市级 -->
<!-- <div v-show="control == 4"> -->
<div v-show="control == 2">
<cityMapL ref="cityMapLRef" class="mapL" @LookMap="LookMap" @GridDiagram="GridDiagram" />
<cityMapR ref="cityMapRRef" class="mapR" />
</div>
</div>
<Info v-if="!lineInfo" ref="InfoRef" @back="lineInfo = true" />
</div>
</template>
<script setup lang="ts">
import { onMounted, nextTick, ref, provide } from 'vue'
import Area from '@/components/form/area/index.vue'
import Map from './components/map.vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { Search, Refresh } from '@element-plus/icons-vue'
import mapL from './components/mapL.vue'
import mapR from './components/mapR.vue'
import cityMapL from './components/cityMapL.vue'
import cityMapR from './components/cityMapR.vue'
import Info from './components/line/info.vue'
import DatePicker from '@/components/form/datePicker/index.vue'
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei'
const dictData = useDictData()
defineOptions({
name: 'panorama'
})
const datePickerRef = ref()
const areaRef = ref()
const lineInfo = ref(true)
const mapRef = ref()
const mapLRef = ref()
const InfoRef = ref()
const mapRRef = ref()
const cityMapLRef = ref()
const cityMapRRef = ref()
// const list: any = [dictData.state.area[0], ...dictData.state.area[0].children]
const options: any = ref([
{
name: dictData.state.area[0].name,
id: 0
},
{
name: '上送网公司',
id: 1
}
])
const control = ref(1)
const form: any = ref({
name: '',
orgNo: dictData.state.area[0].id,
areaName: dictData.state.area[0]?.name,
isUpToGrid: 0
})
const height = mainHeight(10)
// 获取区域名称
const changeValue = (e: any) => {
VITE_FLAG ? mapRef.value.locatePositions(e) : ''
form.value.orgNo = e.data.id //list.filter((item: any) => item.code == e.orgId)[0]?.id || dictData.state.area[0].id
form.value.areaName = e.data.name
options.value[0].name = e.data.areaName
control.value = e.data.level
info()
}
//点击监测点详情
const drop = (id: string) => {
lineInfo.value = false
nextTick(() => {
InfoRef.value.open(id)
})
}
// 关闭左右数据展示
const infoShow = (e: boolean) => {
mapLRef.value.show = e
mapRRef.value.show = e
cityMapLRef.value.show = e
cityMapRRef.value.show = e
}
// 地图控制图层
const LookMap = (row: any, key?: any) => {
VITE_FLAG ? mapRef.value.addMarkers({ ...row, type: 1 }, key) : ''
}
const LngLat = [
{
name: '唐山',
LngLat: [118.335849137, 39.7513593355],
zoom: 8
},
{
name: '张家口',
LngLat: [115.032504679, 40.8951549951],
zoom: 7
},
{
name: '秦皇岛',
LngLat: [119.185113833, 40.1179119754],
zoom: 8.3
},
{
name: '承德',
LngLat: [117.548498365, 41.3775890632],
zoom: 7.3
},
{
name: '廊坊',
LngLat: [116.628004129, 39.0589378611],
zoom: 8
},
{
name: '超高压',
LngLat: [116.84428600000001, 40.57707185292256],
zoom: 6.709267680647425
},
{
name: '风光储',
LngLat: [116.84428600000001, 40.57707185292256],
zoom: 6.709267680647425
}
]
//区域统计展示切换
const GridDiagram = (k?: number, num?: number) => {
VITE_FLAG ? mapRef.value.radiusPop(k) : ''
if (num == 3) {
// form.value.areaName
let value = LngLat.filter(item => item.name == form.value.areaName)[0]
if (value) VITE_FLAG ? mapRef.value.flyTo({ coordinate: value.LngLat }, value.zoom) : ''
} else {
VITE_FLAG ? mapRef.value.flyTo({ coordinate: [116.84428600000001, 40.57707185292256] }, 6.709267680647425) : ''
}
}
const info = () => {
form.value.startTime = datePickerRef.value.timeValue[0]
form.value.searchBeginTime = datePickerRef.value.timeValue[0]
form.value.endTime = datePickerRef.value.timeValue[1]
form.value.searchEndTime = datePickerRef.value.timeValue[1]
form.value.type = datePickerRef.value.interval
VITE_FLAG ? mapRef.value.grids(form.value) : ''
if (control.value == 1) {
mapLRef.value.info(form.value)
mapRRef.value.info(form.value)
} else {
cityMapRRef.value.info(form.value)
cityMapLRef.value.info(form.value)
}
}
// 重置
const reset = () => {
form.value = {
name: '',
orgNo: dictData.state.area[0].id,
areaName: dictData.state.area[0]?.name,
isUpToGrid: 0
}
changeValue({ data: dictData.state.area[0] })
}
onMounted(() => {
// info()
changeValue({ data: dictData.state.area[0] })
// aaa()
})
</script>
<style lang="scss" scoped>
:deep(.mapBox) {
position: absolute;
top: 10px;
left: calc(50% + 45px);
z-index: 1;
.el-select {
min-width: 100px;
.el-select__wrapper {
height: 46px !important;
border-radius: 8px;
}
}
.Icon {
height: 46px;
width: 46px;
background-color: #fff;
border-radius: 8px;
text-align: center;
line-height: 50px;
cursor: pointer;
.fa-refresh {
color: var(--el-color-primary) !important;
}
}
.el-input__wrapper {
height: 46px;
border-radius: 8px;
}
.el-form-item {
margin-right: 15px;
}
}
.mapL {
position: absolute;
top: 10px;
// z-index: 1;
left: 10px;
}
.mapR {
position: absolute;
top: 10px;
// z-index: 1;
right: 10px;
}
.panorama {
margin: 10px 0 0 0;
position: relative;
}
.el-button:focus {
color: var(--color);
background-color: #fff;
}
.el-button:hover {
color: var(--el-color-white);
border-color: var(--el-button-hover-bg-color);
background-color: var(--el-button-hover-bg-color);
outline: 0;
}
</style>
<template>
<div class="panorama" :style="height">
<div class="mapBox" v-show="lineInfo">
<DatePicker ref="datePickerRef" style="display: none" theCurrentTime />
<el-form :inline="true" :model="form" class="demo-form-inline">
<el-form-item>
<Area ref="areaRef" :show-all-levels="false" v-model="form.orgNo" style="width: 100px"
@changeValue="changeValue" />
</el-form-item>
<el-form-item>
<el-select v-model="form.isUpToGrid" style="width: 100px" @change="info">
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<div class="Icon" @click="reset">
<Icon name="fa fa-refresh" />
</div>
</el-form-item>
</el-form>
</div>
<!-- 地图 -->
<Map v-if="VITE_FLAG" ref="mapRef" @changeValue="changeValue" :lineInfo="lineInfo" @drop="drop"
@show="infoShow" />
<div v-show="lineInfo">
<!-- 省级 -->
<div v-show="control == 1">
<mapL ref="mapLRef" class="mapL" @LookMap="LookMap" @GridDiagram="GridDiagram" />
<mapR ref="mapRRef" class="mapR" />
</div>
<!-- 市级 -->
<!-- <div v-show="control == 4"> -->
<div v-show="control == 2">
<cityMapL ref="cityMapLRef" class="mapL" @LookMap="LookMap" @GridDiagram="GridDiagram" />
<cityMapR ref="cityMapRRef" class="mapR" />
</div>
</div>
<Info v-if="!lineInfo" ref="InfoRef" @back="lineInfo = true" />
</div>
</template>
<script setup lang="ts">
import { onMounted, nextTick, ref, provide } from 'vue'
import Area from '@/components/form/area/index.vue'
import Map from './components/map.vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { Search, Refresh } from '@element-plus/icons-vue'
import mapL from './components/mapL.vue'
import mapR from './components/mapR.vue'
import cityMapL from './components/cityMapL.vue'
import cityMapR from './components/cityMapR.vue'
import Info from './components/line/info.vue'
import DatePicker from '@/components/form/datePicker/index.vue'
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei'
const dictData = useDictData()
defineOptions({
name: 'panorama'
})
const datePickerRef = ref()
const areaRef = ref()
const lineInfo = ref(true)
const mapRef = ref()
const mapLRef = ref()
const InfoRef = ref()
const mapRRef = ref()
const cityMapLRef = ref()
const cityMapRRef = ref()
// const list: any = [dictData.state.area[0], ...dictData.state.area[0].children]
const options: any = ref([
{
name: dictData.state.area[0].name,
id: 0
},
{
name: '上送网公司',
id: 1
}
])
const control = ref(1)
const form: any = ref({
name: '',
orgNo: dictData.state.area[0].id,
areaName: dictData.state.area[0]?.name,
isUpToGrid: 0
})
const height = mainHeight(10)
// 获取区域名称
const changeValue = (e: any) => {
VITE_FLAG ? mapRef.value.locatePositions(e) : ''
form.value.orgNo = e.data.id //list.filter((item: any) => item.code == e.orgId)[0]?.id || dictData.state.area[0].id
form.value.areaName = e.data.name
options.value[0].name = e.data.areaName
control.value = e.data.level
info()
}
//点击监测点详情
const drop = (id: string) => {
lineInfo.value = false
nextTick(() => {
InfoRef.value.open(id)
})
}
// 关闭左右数据展示
const infoShow = (e: boolean) => {
mapLRef.value.show = e
mapRRef.value.show = e
cityMapLRef.value.show = e
cityMapRRef.value.show = e
}
// 地图控制图层
const LookMap = (row: any, key?: any) => {
VITE_FLAG ? mapRef.value.addMarkers({ ...row, type: 1 }, key) : ''
}
const LngLat = [
{
name: '唐山',
LngLat: [118.335849137, 39.7513593355],
zoom: 8
},
{
name: '张家口',
LngLat: [115.032504679, 40.8951549951],
zoom: 7
},
{
name: '秦皇岛',
LngLat: [119.185113833, 40.1179119754],
zoom: 8.3
},
{
name: '承德',
LngLat: [117.548498365, 41.3775890632],
zoom: 7.3
},
{
name: '廊坊',
LngLat: [116.628004129, 39.0589378611],
zoom: 8
},
{
name: '超高压',
LngLat: [116.84428600000001, 40.57707185292256],
zoom: 6.709267680647425
},
{
name: '风光储',
LngLat: [116.84428600000001, 40.57707185292256],
zoom: 6.709267680647425
}
]
//区域统计展示切换
const GridDiagram = (k?: number, num?: number) => {
VITE_FLAG ? mapRef.value.radiusPop(k) : ''
if (num == 3) {
// form.value.areaName
let value = LngLat.filter(item => item.name == form.value.areaName)[0]
if (value) VITE_FLAG ? mapRef.value.flyTo({ coordinate: value.LngLat }, value.zoom) : ''
} else {
VITE_FLAG ? mapRef.value.flyTo({ coordinate: [116.84428600000001, 40.57707185292256] }, 6.709267680647425) : ''
}
}
const info = () => {
form.value.startTime = datePickerRef.value.timeValue[0]
form.value.searchBeginTime = datePickerRef.value.timeValue[0]
form.value.endTime = datePickerRef.value.timeValue[1]
form.value.searchEndTime = datePickerRef.value.timeValue[1]
form.value.type = datePickerRef.value.interval
VITE_FLAG ? mapRef.value.grids(form.value) : ''
if (control.value == 1) {
mapLRef.value.info(form.value)
mapRRef.value.info(form.value)
} else {
cityMapRRef.value.info(form.value)
cityMapLRef.value.info(form.value)
}
}
// 重置
const reset = () => {
form.value = {
name: '',
orgNo: dictData.state.area[0].id,
areaName: dictData.state.area[0]?.name,
isUpToGrid: 0
}
changeValue({ data: dictData.state.area[0] })
}
onMounted(() => {
// info()
changeValue({ data: dictData.state.area[0] })
// aaa()
})
</script>
<style lang="scss" scoped>
:deep(.mapBox) {
position: absolute;
top: 10px;
left: calc(50% + 45px);
z-index: 1;
.el-select {
min-width: 100px;
.el-select__wrapper {
height: 46px !important;
border-radius: 8px;
}
}
.Icon {
height: 46px;
width: 46px;
background-color: #fff;
border-radius: 8px;
text-align: center;
line-height: 50px;
cursor: pointer;
.fa-refresh {
color: var(--el-color-primary) !important;
}
}
.el-input__wrapper {
height: 46px;
border-radius: 8px;
}
.el-form-item {
margin-right: 15px;
}
}
.mapL {
position: absolute;
top: 10px;
// z-index: 1;
left: 10px;
}
.mapR {
position: absolute;
top: 10px;
// z-index: 1;
right: 10px;
}
.panorama {
margin: 10px 0 0 0;
position: relative;
}
.el-button:focus {
color: var(--color);
background-color: #fff;
}
.el-button:hover {
color: var(--el-color-white);
border-color: var(--el-button-hover-bg-color);
background-color: var(--el-button-hover-bg-color);
outline: 0;
}
</style>

View File

@@ -476,6 +476,7 @@ tableStore.table.params.name = ''
provide('tableStore', tableStore)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.card-list {
display: flex;
.monitoringPoints {

View File

@@ -518,6 +518,7 @@ tableStore.table.params.name = ''
provide('tableStore', tableStore)
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.card-list {
display: flex;
.monitoringPoints {

View File

@@ -1,137 +1,170 @@
<template>
<el-dialog draggable width="1550px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<div style="display: flex">
<div :style="height1" class="mr10 box" style="width: 600px">
<vxe-table
height="auto"
:data="TableData"
v-bind="defaultAttribute"
ref="tableRef"
:row-config="{ isCurrent: true, isHover: true }"
@current-change="currentChangeEvent"
>
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="date" title="日期"></vxe-column>
<vxe-column field="bdName" title="所属电站(场站)" width="120px"></vxe-column>
<vxe-column field="monitorName" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="timeSum" title="异常时间(分钟)" width="80px"></vxe-column>
<vxe-column field="errCount" title="异常次数" width="80px"></vxe-column>
</vxe-table>
</div>
<div :style="height" style="width: 920px" v-loading="loading1">
<vxe-table
height="auto"
:data="TableData1.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
v-bind="defaultAttribute"
>
<vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }">
<span>{{ (pageNum - 1) * pageSize + rowIndex + 1 }}</span>
</template>
</vxe-column>
<vxe-column field="time" title="时间" width="150px"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="80px"></vxe-column>
<vxe-column field="phaseType" title="相别" width="60px">
<template v-slot="{ row }">
{{ row.phaseType=='T'?'/':row.phaseType }}
</template>
</vxe-column>
<vxe-column field="rangeDesc" title="合理范围" min-width="90px"></vxe-column>
<vxe-column field="max" title="最大" width="85px" :formatter="formatter"></vxe-column>
<vxe-column field="min" title="最小" width="85px" :formatter="formatter"></vxe-column>
<vxe-column field="avg" title="平均" width="85px" :formatter="formatter"></vxe-column>
<vxe-column field="cp95" title="CP95" width="85px" :formatter="formatter"></vxe-column>
</vxe-table>
<div class="table-pagination">
<el-pagination
v-model:currentPage="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100, 200]"
background
layout="sizes,total, ->, prev, pager, next, jumper"
:total="TableData1.length"
></el-pagination>
</div>
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ElMessage } from 'element-plus'
import { monitorAbnormalTable, monitorAbnormalTableDetail } from '@/api/device-boot/dataVerify'
import { mainHeight } from '@/utils/layout'
const dialogVisible = ref(false)
const height1 = mainHeight(-110, 2)
const height = mainHeight(10, 2)
const tableRef = ref()
const title = ref('')
const loading1 = ref(false)
const TableData = ref([])
const TableData1 = ref([])
const pageNum = ref(1)
const pageSize = ref(20)
const numKey = ref(0)
const targetKey = ref('')
const open = (data: anyObj, time: string[], num: number) => {
// title.value = (num == 0 ? data.targetName : data.monitorName) + '_异常监测点详情'
title.value ='异常监测点详情'
TableData.value = []
numKey.value = num
targetKey.value = data.key
monitorAbnormalTable({
monitorIds: num == 0 ? data.ids : [data.monitorId],
targetKey: num == 0 ? data.key : '',
searchBeginTime: time[0],
searchEndTime: time[1]
}).then(res => {
TableData.value = res.data
tableRef.value.setCurrentRow(TableData.value[0])
currentChangeEvent()
})
dialogVisible.value = true
}
const currentChangeEvent = () => {
loading1.value = true
let data = tableRef.value.getCurrentRecord()
TableData1.value = []
monitorAbnormalTableDetail({
monitorIds: [data.monitorId],
searchBeginTime: data.date,
targetKey: numKey.value == 0 ? targetKey.value : ''
})
.then(res => {
TableData1.value = res.data
loading1.value = false
pageNum.value = 1
})
.catch(() => {
loading1.value = false
})
}
const formatter = (row: any) => {
return row.cellValue == null ? '/' : (row.cellValue - 0).toFixed(2)
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.table-pagination {
height: 58px;
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
:deep(.box) {
.row--current {
background-color: var(--el-color-primary-light-8) !important;
}
}
</style>
<template>
<el-dialog draggable width="1550px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<div style="display: flex">
<div :style="height1" class="mr10 box" style="width: 600px">
<vxe-table
height="auto"
:data="TableData"
v-bind="defaultAttribute"
ref="tableRef"
:row-config="{ isCurrent: true, isHover: true }"
@current-change="currentChangeEvent"
>
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="date" title="日期"></vxe-column>
<vxe-column field="bdName" title="所属电站(场站)" width="120px"></vxe-column>
<vxe-column field="monitorName" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="timeSum" title="异常时间(分钟)" width="80px"></vxe-column>
<vxe-column field="errCount" title="异常次数" width="80px"></vxe-column>
</vxe-table>
</div>
<div :style="height" style="width: 920px" v-loading="loading1">
<vxe-table
height="auto"
:data="TableData1.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
v-bind="defaultAttribute"
>
<vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }">
<span>{{ (pageNum - 1) * pageSize + rowIndex + 1 }}</span>
</template>
</vxe-column>
<vxe-column field="time" title="时间" width="150px"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="80px"></vxe-column>
<vxe-column field="phaseType" title="相别" width="60px">
<template v-slot="{ row }">
{{ row.phaseType == 'T' ? '/' : row.phaseType }}
</template>
</vxe-column>
<vxe-column field="rangeDesc" title="合理范围" min-width="90px"></vxe-column>
<vxe-column
field="max"
title="最大"
width="85px"
:formatter="formatter"
v-if="showColumn"
></vxe-column>
<vxe-column
field="min"
title="最小"
width="85px"
:formatter="formatter"
v-if="showColumn"
></vxe-column>
<vxe-column
field="avg"
title="平均"
width="85px"
:formatter="formatter"
v-if="showColumn"
></vxe-column>
<vxe-column
field="cp95"
title="CP95"
width="85px"
:formatter="formatter"
v-if="showColumn"
></vxe-column>
<vxe-column
field="featureAmplitude"
title="幅值"
width="85px"
:formatter="formatter"
v-if="!showColumn"
></vxe-column>
</vxe-table>
<div class="table-pagination">
<el-pagination
v-model:currentPage="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100, 200]"
background
layout="sizes,total, ->, prev, pager, next, jumper"
:total="TableData1.length"
></el-pagination>
</div>
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ElMessage } from 'element-plus'
import { monitorAbnormalTable, monitorAbnormalTableDetail } from '@/api/device-boot/dataVerify'
import { mainHeight } from '@/utils/layout'
const dialogVisible = ref(false)
const height1 = mainHeight(-110, 2)
const height = mainHeight(10, 2)
const tableRef = ref()
const title = ref('')
const loading1 = ref(false)
const TableData = ref([])
const TableData1 = ref([])
const pageNum = ref(1)
const pageSize = ref(20)
const numKey = ref(0)
const targetKey = ref('')
const showColumn = ref(true)
const open = (data: anyObj, time: string[], num: number) => {
// title.value = (num == 0 ? data.targetName : data.monitorName) + '_异常监测点详情'
title.value = '异常监测点详情'
TableData.value = []
numKey.value = num
targetKey.value = data.key
monitorAbnormalTable({
monitorIds: num == 0 ? data.ids : [data.monitorId],
targetKey: num == 0 ? data.key : '',
searchBeginTime: time[0],
searchEndTime: time[1]
}).then(res => {
TableData.value = res.data
tableRef.value.setCurrentRow(TableData.value[0])
currentChangeEvent()
})
dialogVisible.value = true
}
const currentChangeEvent = () => {
loading1.value = true
let data = tableRef.value.getCurrentRecord()
TableData1.value = []
monitorAbnormalTableDetail({
monitorIds: [data.monitorId],
searchBeginTime: data.date,
targetKey: numKey.value == 0 ? targetKey.value : ''
})
.then(res => {
TableData1.value = res.data
showColumn.value = res.data[0]?.featureAmplitude == null ? true : false
loading1.value = false
pageNum.value = 1
})
.catch(() => {
loading1.value = false
})
}
const formatter = (row: any) => {
return row.cellValue == null ? '/' : (row.cellValue - 0).toFixed(2)
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.table-pagination {
height: 58px;
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
:deep(.box) {
.row--current {
background-color: var(--el-color-primary-light-8) !important;
}
}
</style>

View File

@@ -0,0 +1,121 @@
<template>
<div style="height: 145px" class="box1">
<!-- <div class="boxDiv hexagon">
<div class="text-style" @click="change('')">{{ props.params.allNum }}</div>
<div class="mt10 divBot">总数</div>
</div>
<div class="boxDiv hexagon hexagon1">
<div class="text-style" @click="change('运行')">{{ props.params.runNum }}</div>
<div class="mt10 divBot">在运</div>
</div>
<div class="boxDiv hexagon hexagon2">
<div class="text-style" @click="change('调试')">{{ props.params.checkNum }}</div>
<div class="mt10 divBot">调试</div>
</div>
<div class="boxDiv hexagon hexagon3">
<div class="text-style" @click="change('停运')">{{ props.params.stopRunNum }}</div>
<div class="mt10 divBot">停运</div>
</div> -->
<div class="statistics">
<div class="divBox div1">
<span class="iconfont icon-qiyezongshu" style="color: #57bc6e"></span>
<span class="divBox_title">终端总数</span>
<span class="divBox_num text-style" style="color: #57bc6e" @click="change('')">
{{ props.params.allNum }}
</span>
</div>
<div class="divBox div2" style="width: 210px">
<span class="iconfont icon-zaiyunshebei" style="color: #67c23a"></span>
<span class="divBox_title">在运终端数</span>
<span class="divBox_num text-style" style="color: #67c23a" @click="change('运行')">
{{ props.params.runNum }}
</span>
</div>
</div>
<div class="statistics">
<div class="divBox div3">
<span class="iconfont icon-yichanglei_14feizhinengbiaozaiyunyichang" style="color: #ffbf00"></span>
<span class="divBox_title">调试终端数</span>
<span class="divBox_num text-style" style="color: #ffbf00" @click="change('调试')">
{{ props.params.checkNum }}
</span>
</div>
<div class="divBox div4" style="width: 210px">
<span class="iconfont icon-tingyunshijianguanli" style="color: #f56c6c"></span>
<span class="divBox_title">停运终端数</span>
<span class="divBox_num text-style" style="color: #f56c6c" @click="change('停运')">
{{ props.params.stopRunNum }}
</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import MyEChart from '@/components/echarts/MyEchart.vue'
import { mainHeight } from '@/utils/layout'
import { color } from '@/components/echarts/color'
const emit = defineEmits(['change'])
const height = mainHeight(330, 3)
const props = defineProps({
params: {
type: Object,
default: () => {}
}
})
const change = (e: string) => {
emit('change', e)
}
const info = () => {}
onMounted(() => {
info()
})
</script>
<style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.statistics {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-bottom: 10px;
.divBox {
width: 210px;
height: 70px;
padding: 10px;
display: flex;
.iconfont {
font-size: 40px;
margin-right: 5px;
}
.divBox_title {
font-weight: 550;
}
.divBox_num {
font-size: 20px;
font-weight: 550;
margin-left: auto;
font-family: AlimamaDongFangDaKai;
}
align-items: center;
// text-align: center;
border-radius: 5px;
}
.div1 {
background-color: #eef8f0;
}
.div2 {
background-color: #67c23a24;
}
.div3 {
background-color: #ffbf0024;
}
.div4 {
background-color: #f56c6c24;
}
}
.text-style {
cursor: pointer;
text-decoration: underline;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader date-picker ref="TableHeaderRef" :dateLabel="`数据统计时间`">
<TableHeader date-picker ref="TableHeaderRef" >
<template v-slot:select>
<el-form-item label="运行状态">
<el-select v-model="tableStore.table.params.lineRunFlag" clearable placeholder="请选择运行状态">
@@ -23,7 +23,7 @@
</TableHeader>
<div class="card-list pt10" v-loading="tableStore.table.loading">
<div class="monitoringPoints">
<el-card style="height: 200px">
<el-card style="height: 215px">
<template #header>
<div class="card-header">
<span>终端统计</span>
@@ -68,7 +68,7 @@
<span style="width: 90px">终端总数</span>
<span style="flex: 1">完整性(%)</span>
<span style="width: 80px">在线率(%)</span>
<span style="width: 80px">合格(%)</span>
<span style="width: 80px">异常(%)</span>
</div>
<div :style="indicatorHeight" style="overflow-y: auto">
<div v-for="o in abnormal" class="abnormal mb10">
@@ -165,7 +165,7 @@
</vxe-column>
<vxe-column field="integrityRate" title="完整性(%)" width="100px"></vxe-column>
<vxe-column field="onLineRate" title="在线率(%)" width="100px"></vxe-column>
<vxe-column field="passRate" title="合格率(%)" width="100px"></vxe-column>
<vxe-column field="passRate" title="异常率(%)" width="100px"></vxe-column>
</vxe-table>
</div>
<div class="table-pagination">
@@ -191,7 +191,7 @@ import { onMounted, provide, ref } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import statistics from './components/statistics.vue'
import statistics from './components/statistics_JB.vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getMonitorVerifyDay } from '@/api/device-boot/dataVerify'
defineOptions({
@@ -201,7 +201,7 @@ defineOptions({
const dictData = useDictData()
//字典获取监督对象类型
const pageHeight = mainHeight(97)
const indicatorHeight = mainHeight(447)
const indicatorHeight = mainHeight(462)
const monitoringPoints = ref({
runNum: 0,
abnormalNum: 0,
@@ -269,7 +269,9 @@ const tableStore = new TableStore({
statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length
statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length
abnormal.value = tableStore.table.data
abnormal.value = tableStore.table.data.filter(
(k: any) => k.name != '上送国网' && k.name != '非上送国网'
)
// 合并子集数据 并去重
totalTable(101, '')
@@ -484,7 +486,7 @@ provide('tableStore', tableStore)
justify-content: space-between;
margin-bottom: 10px;
.divBox {
width: 200px;
width: 215x;
height: 70px;
padding: 10px;
display: flex;

View File

@@ -195,16 +195,16 @@ const tableStore = new TableStore({
render: 'buttons',
fixed: 'right',
buttons: [
// {
// name: 'edit',
// title: '人工维护',
// type: 'primary',
// icon: 'el-icon-Plus',
// render: 'basicButton',
// click: async row => {
// addFormRef.value.open(row)
// }
// },
{
name: 'edit',
title: '人工维护',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: async row => {
addFormRef.value.open(row)
}
},
{
name: 'edit',
title: '波形分析',

View File

@@ -1,332 +1,332 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%" v-loading="loading">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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: ['上限', '下限', '可容忍事件', '不可容忍事件']
},
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.55)',
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: '%'
}
],
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
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>
<template>
<div style="display: flex; flex-direction: column; height: 100%" v-loading="loading">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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: ['上限', '下限', '可容忍事件', '不可容忍事件']
},
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.55)',
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: '%'
}
],
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
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>

View File

@@ -1,320 +1,320 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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: ['上限', '下限', '可容忍事件', '不可容忍事件']
},
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.55)',
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: '%'
}
],
color: ['#DAA520', 'green', 'red'],
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.pointF
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
data: gongData.pointFun
}
]
}
}
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>
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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: ['上限', '下限', '可容忍事件', '不可容忍事件']
},
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.55)',
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: '%'
}
],
color: ['#DAA520', 'green', 'red'],
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.pointF
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
data: gongData.pointFun
}
]
}
}
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>

View File

@@ -1,171 +1,171 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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: {
top: 0,
show: true,
data: ['概率分布', '占比'],
textStyle: {
rich: {
a: {
verticalAlign: 'middle'
}
},
padding: [2, 0, 0, 0] //[上、右、下、左]
}
},
toolbox: {
top: -10
},
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.55)',
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>
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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: {
top: 0,
show: true,
data: ['概率分布', '占比'],
textStyle: {
rich: {
a: {
verticalAlign: 'middle'
}
},
padding: [2, 0, 0, 0] //[上、右、下、左]
}
},
toolbox: {
top: -10
},
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.55)',
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>

View File

@@ -1,304 +1,304 @@
<template>
<div v-loading="loading" class="dianyazanjiangbaojimidu">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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="420px" size="mini" :data="firstData">
<vxe-colgroup title="剩余电压" field="name" width="80px"></vxe-colgroup>
<vxe-colgroup title="持续时间">
<vxe-column field="twentyMs" title="20ms" :formatter="formatter" />
<vxe-column field="oneHundredMs" title="100ms" :formatter="formatter" />
<vxe-column field="fiveHundredMs" title="500ms" :formatter="formatter" />
<vxe-column field="oneS" title="1s" :formatter="formatter" />
<vxe-column field="threeS" title="2s" :formatter="formatter" />
<vxe-column field="twentyS" title="20s" :formatter="formatter" />
<vxe-column field="sixtyS" title="60s" :formatter="formatter" />
<vxe-column field="oneEightyS" title="180s" :formatter="formatter" />
</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="220px" size="mini" :data="secondData">
<vxe-colgroup title="剩余电压" field="name" width="80px"></vxe-colgroup>
<vxe-colgroup title="持续时间">
<vxe-column field="tenTwentyMs" title="10-20ms" :formatter="formatter" />
<vxe-column field="twentyOneHundredMs" title="20-100ms" :formatter="formatter" />
<vxe-column field="zeroPiontOneTwoS" title="0.1-0.2s" :formatter="formatter" />
<vxe-column field="zeroPiontFive1S" title="0.2-0.5s" :formatter="formatter" />
<vxe-column field="zeroPiontTwoFiveS" title="0.5-1s" :formatter="formatter" />
<vxe-column field="greater1S" title=">1s" :formatter="formatter" />
</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" :formatter="formatter" />
<vxe-column field="w" title="0.1-0.25s" align="center" :formatter="formatter" />
<vxe-column field="e" title="0.25-0.5s" align="center" :formatter="formatter" />
<vxe-column field="r" title="0.5-1s" align="center" :formatter="formatter" />
<vxe-column field="t" title="1-3s" align="center" :formatter="formatter" />
<vxe-column field="y" title="3-20s" align="center" :formatter="formatter" />
<vxe-column field="u" title="20-60s" align="center" :formatter="formatter" />
<vxe-column field="i" title="60-180s" align="center" :formatter="formatter" />
</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 '@/stores/monitoringPoint'
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 formatter = (row: any) => {
return row.cellValue == 0 ? '/' : row.cellValue
}
const init = () => {
formData.lineIndex = monitoringPoint.state.lineId
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;
height: 280px;
}
.second {
grid-area: second;
display: flex;
flex-direction: column;
overflow: hidden;
height: 210px;
}
.third {
grid-area: third;
display: flex;
flex-direction: column;
overflow: hidden;
height: 720px;
}
.charts {
grid-area: charts;
overflow: hidden;
}
}
}
</style>
<template>
<div v-loading="loading" class="dianyazanjiangbaojimidu">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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="420px" size="mini" :data="firstData">
<vxe-colgroup title="剩余电压" field="name" width="80px"></vxe-colgroup>
<vxe-colgroup title="持续时间">
<vxe-column field="twentyMs" title="20ms" :formatter="formatter" />
<vxe-column field="oneHundredMs" title="100ms" :formatter="formatter" />
<vxe-column field="fiveHundredMs" title="500ms" :formatter="formatter" />
<vxe-column field="oneS" title="1s" :formatter="formatter" />
<vxe-column field="threeS" title="2s" :formatter="formatter" />
<vxe-column field="twentyS" title="20s" :formatter="formatter" />
<vxe-column field="sixtyS" title="60s" :formatter="formatter" />
<vxe-column field="oneEightyS" title="180s" :formatter="formatter" />
</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="220px" size="mini" :data="secondData">
<vxe-colgroup title="剩余电压" field="name" width="80px"></vxe-colgroup>
<vxe-colgroup title="持续时间">
<vxe-column field="tenTwentyMs" title="10-20ms" :formatter="formatter" />
<vxe-column field="twentyOneHundredMs" title="20-100ms" :formatter="formatter" />
<vxe-column field="zeroPiontOneTwoS" title="0.1-0.2s" :formatter="formatter" />
<vxe-column field="zeroPiontFive1S" title="0.2-0.5s" :formatter="formatter" />
<vxe-column field="zeroPiontTwoFiveS" title="0.5-1s" :formatter="formatter" />
<vxe-column field="greater1S" title=">1s" :formatter="formatter" />
</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" :formatter="formatter" />
<vxe-column field="w" title="0.1-0.25s" align="center" :formatter="formatter" />
<vxe-column field="e" title="0.25-0.5s" align="center" :formatter="formatter" />
<vxe-column field="r" title="0.5-1s" align="center" :formatter="formatter" />
<vxe-column field="t" title="1-3s" align="center" :formatter="formatter" />
<vxe-column field="y" title="3-20s" align="center" :formatter="formatter" />
<vxe-column field="u" title="20-60s" align="center" :formatter="formatter" />
<vxe-column field="i" title="60-180s" align="center" :formatter="formatter" />
</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 '@/stores/monitoringPoint'
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 formatter = (row: any) => {
return row.cellValue == 0 ? '/' : row.cellValue
}
const init = () => {
formData.lineIndex = monitoringPoint.state.lineId
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;
height: 280px;
}
.second {
grid-area: second;
display: flex;
flex-direction: column;
overflow: hidden;
height: 210px;
}
.third {
grid-area: third;
display: flex;
flex-direction: column;
overflow: hidden;
height: 720px;
}
.charts {
grid-area: charts;
overflow: hidden;
}
}
}
</style>

View File

@@ -1,51 +1,59 @@
<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>
<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, onMounted } 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 props = defineProps({
externalHeight: {
type: Number,
default: 0
}
})
const activeName = ref('1')
const height = ref(mainHeight(84 + props.externalHeight))
// onMounted(() => {
// height.value = mainHeight(84 + props.externalHeight)
// console.log("🚀 ~ 84 + props.externalHeight:", 84 + props.externalHeight)
// })
</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>

View File

@@ -1,172 +1,172 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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,
top: 0,
data: ['概率分布', '占比'],
textStyle: {
rich: {
a: {
verticalAlign: 'middle'
}
},
padding: [2, 0, 0, 0] //[上、右、下、左]
}
},
toolbox: {
top: -10
},
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.55)',
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>
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</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 '@/stores/monitoringPoint'
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.lineIndex = monitoringPoint.state.lineId
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,
top: 0,
data: ['概率分布', '占比'],
textStyle: {
rich: {
a: {
verticalAlign: 'middle'
}
},
padding: [2, 0, 0, 0] //[上、右、下、左]
}
},
toolbox: {
top: -10
},
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.55)',
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>

View File

@@ -1,162 +1,171 @@
<template>
<div>
<div v-show="view">
<!-- 表头 -->
<TableHeader date-picker showExport>
<template v-slot:operation>
<el-button :icon='Download' type='primary' @click='download'>下载波形</el-button>
</template>
</TableHeader>
<!-- 表格 -->
<Table ref='tableRef' :checkboxConfig='checkboxConfig' />
</div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
<waveForm ref="waveFormRef" senior @backbxlb="backbxlb" />
</div>
</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 '@/stores/monitoringPoint'
import { useDictData } from '@/stores/dictData'
import { checkUser } from '@/api/user-boot/user'
import waveForm from '@/components/echarts/waveForm.vue'
import { VxeTablePropTypes } from 'vxe-table'
import { downloadWaveFile, getMonitorEventAnalyseWave } from '@/api/event-boot/transient'
const view = ref(true)
const waveFormRef = ref()
const view2 = ref(false)
const pageHeight = mainHeight(20)
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: '序号', width: 80, formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '变电站名称', field: 'subName', minWidth: '140' },
{ title: '监测点名称', field: 'lineName', minWidth: '130' },
{ title: '网络参数', field: 'ip', minWidth: '130' },
{ title: '电压等级(kV)', field: 'voltageScale', width: '120' },
{ title: '暂降发生时刻', field: 'startTime', width: '200' },
// { title: '暂降类型', field: 'advanceType', minWidth: '130' },
{ title: '暂降原因', field: 'advanceReason', minWidth: '130' },
{
title: '触发类型', field: 'eventType', minWidth: '80', formatter: (row: any) => {
return eventTypeOptions.find(item => item.id === row.cellValue)?.name || '/'
}
},
{
title: '暂降(骤升)幅值(%)', field: 'featureAmplitude', minWidth: '140',
formatter: (row: any) => {
return (row.cellValue * 100).toFixed(2)
},
},
{ title: '持续时间(s)', field: 'duration', minWidth: '100' },
// { 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('暂无可下载的波形文件!')
// })
view.value = false
setTimeout(() => {
waveFormRef.value.open(row)
}, 100)
}
},
{
name: 'edit',
title: '暂无波形',
type: '',
disabled: row => {
return row.fileFlag != 0
},
icon: 'el-icon-Plus',
render: 'basicButton'
}
]
}
],
beforeSearchFun: () => {
tableStore.table.params.lineId = monitoringPoint.state.lineId
console.log('beforeSearchFun')
},
loadCallback: () => {
}
})
provide('tableStore', tableStore)
tableStore.table.params.searchState = 0
onMounted(() => {
// 加载数据
tableStore.index()
})
const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({
checkMethod: ({ row }) => {
return row.fileFlag === 1
}
})
const backbxlb = () => {
view.value = true
view2.value = false
}
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.info('下载中......')
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>
<template>
<div>
<div v-show="view">
<!-- 表头 -->
<TableHeader date-picker showExport>
<template v-slot:operation>
<el-button :icon="Download" type="primary" @click="download">下载波形</el-button>
</template>
</TableHeader>
<!-- 表格 -->
<Table ref="tableRef" :checkboxConfig="checkboxConfig" />
</div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
<waveForm ref="waveFormRef" senior @backbxlb="backbxlb" />
</div>
</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 '@/stores/monitoringPoint'
import { useDictData } from '@/stores/dictData'
import { checkUser } from '@/api/user-boot/user'
import waveForm from '@/components/echarts/waveForm.vue'
import { VxeTablePropTypes } from 'vxe-table'
import { downloadWaveFile, getMonitorEventAnalyseWave } from '@/api/event-boot/transient'
const props = defineProps({
externalHeight: {
type: Number,
default: 0
}
})
const view = ref(true)
const waveFormRef = ref()
const view2 = ref(false)
const pageHeight = mainHeight(20)
const dictData = useDictData()
const eventTypeOptions = dictData.getBasicData('Event_Statis')
const monitoringPoint = useMonitoringPoint()
const tableStore = new TableStore({
publicHeight: 60 + props.externalHeight,
url: '/event-boot/monitor/getMonitorEventAnalyseQuery',
method: 'POST',
column: [
{ width: '60', type: 'checkbox' },
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '变电站名称', field: 'subName', minWidth: '140' },
{ title: '监测点名称', field: 'lineName', minWidth: '130' },
{ title: '网络参数', field: 'ip', minWidth: '130' },
{ title: '电压等级(kV)', field: 'voltageScale', width: '120' },
{ title: '暂降发生时刻', field: 'startTime', width: '200' },
// { title: '暂降类型', field: 'advanceType', minWidth: '130' },
{ title: '暂降原因', field: 'advanceReason', minWidth: '130' },
{
title: '触发类型',
field: 'eventType',
minWidth: '80',
formatter: (row: any) => {
return eventTypeOptions.find(item => item.id === row.cellValue)?.name || '/'
}
},
{
title: '暂降(骤升)幅值(%)',
field: 'featureAmplitude',
minWidth: '140',
formatter: (row: any) => {
return (row.cellValue * 100).toFixed(2)
}
},
{ title: '持续时间(s)', field: 'duration', minWidth: '100' },
// { 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('暂无可下载的波形文件!')
// })
view.value = false
setTimeout(() => {
waveFormRef.value.open(row)
}, 100)
}
},
{
name: 'edit',
title: '暂无波形',
type: '',
disabled: row => {
return row.fileFlag != 0
},
icon: 'el-icon-Plus',
render: 'basicButton'
}
]
}
],
beforeSearchFun: () => {
tableStore.table.params.lineId = monitoringPoint.state.lineId
console.log('beforeSearchFun')
},
loadCallback: () => {}
})
provide('tableStore', tableStore)
tableStore.table.params.searchState = 0
onMounted(() => {
// 加载数据
tableStore.index()
})
const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({
checkMethod: ({ row }) => {
return row.fileFlag === 1
}
})
const backbxlb = () => {
view.value = true
view2.value = false
}
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.info('下载中......')
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>

View File

@@ -27,7 +27,6 @@ import EventStatistics from './eventStatistics/index.vue'
import EventStudy from './eventStudy/index.vue'
import RunningCondition from './runningCondition/index.vue'
import TransientReport from './transientReport/index.vue'
import { mainHeight } from '@/utils/layout'
import router from '@/router'
import { useMonitoringPoint } from '@/stores/monitoringPoint'

View File

@@ -0,0 +1,130 @@
<template>
<div class="default-main" style="padding: 10px">
<splitpanes :style="height" class="default-theme" id="navigation-splitpanes">
<pane :size="size">
<PointTree
ref="pointTree"
:default-expand-all="false"
:default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []"
:current-node-key="monitoringPoint.state.lineId"
:show-checkbox="monitoringPoint.state.showCheckBox"
:default-checked-keys="monitoringPoint.state.lineIds"
@check="handleCheckChange"
@node-click="handleNodeClick"
@init="handleNodeClick"
></PointTree>
</pane>
<pane>
<div style="position: relative; height: 100%">
<el-tabs
v-model="activeName"
type="border-card"
class="demo-tabs"
style="height: 100%"
@tab-change="handleTabChange"
>
<el-tab-pane label="事件分析" name="3" lazy v-if="!isReload">
<EventStudy :externalHeight='20'/>
</el-tab-pane>
<el-tab-pane label="事件统计" name="2" lazy v-if="!isReload">
<EventStatistics :externalHeight='20'/>
</el-tab-pane>
<el-tab-pane label="运行情况" name="4" lazy :style="height" v-if="!isReload">
<RunningCondition :externalHeight='20'/>
</el-tab-pane>
<el-tab-pane label="暂态报告" name="5" lazy v-if="!isReload">
<TransientReport />
</el-tab-pane>
</el-tabs>
</div>
</pane>
</splitpanes>
</div>
</template>
<script setup lang="ts">
import { defineOptions, watch, onMounted, ref, nextTick } from 'vue'
import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes'
import PointTree from '@/components/tree/pqs/pointTree.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { mainHeight } from '@/utils/layout'
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 TransientReport from './transientReport/index.vue'
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei'
import router from '@/router'
defineOptions({
name: 'harmonic-boot/monitor/online'
})
const monitoringPoint = useMonitoringPoint()
const pointTree = ref()
const size = ref(0)
const isReload = ref(false)
const height = mainHeight(40)
const activeName = ref('3')
onMounted(() => {
const dom = document.getElementById('navigation-splitpanes')
if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100)
}
})
const handleNodeClick = (data: any, node: any) => {
if (data.level === 6) {
monitoringPoint.setValue('lineId', data.id)
monitoringPoint.setValue('pid', data.pids)
monitoringPoint.setValue('lineName', data.alias)
monitoringPoint.setValue('comFlag', data.comFlag)
}
}
const handleCheckChange = (data: any, node: any) => {
monitoringPoint.setValue(
'lineIds',
node.checkedNodes.filter((item: any) => item.level === 6).map((item: any) => item.id)
)
}
const handleTabChange = () => {
monitoringPoint.setShowCheckBox(false)
}
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 }
)
watch(
() => monitoringPoint.state.lineId,
() => {
// 刷新页面
isReload.value = true
nextTick(() => {
isReload.value = false
})
}
)
const changeTab = (e: string) => {
activeName.value = e
}
</script>
<style lang="scss">
.splitpanes.default-theme .splitpanes__pane {
background: #eaeef1;
}
.monitoring-point {
position: absolute;
top: 12px;
right: 10px;
font-size: 12px;
font-weight: 700;
color: var(--el-color-primary);
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div v-loading="loading" class="running-condition">
<el-form :inline="true" class="fx-jcsb">
<el-form-item label="日期">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item>

View File

@@ -1,15 +1,6 @@
<template>
<div :style="height">
<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 style="background: #fff" :style="height">
<!-- <div :style="height"></div> -->
<TableHeader ref="TableHeaderRef" date-picker :show-search="false">
@@ -29,7 +20,7 @@
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">生成报告</el-button>
</template>
</TableHeader>
<div class="box" :style="`height: calc(${tableStore.table.height} + 45px)`">
<div class="box" :style="`height: calc(${tableStore.table.height} + 65px)`">
<el-row>
<el-col :span="12" class="mTop">
<div class="grid-content">
@@ -140,6 +131,7 @@ import { mainHeight } from '@/utils/layout'
import { getLineExport, getList, selectReleation } from '@/api/event-boot/report'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { ElMessage } from 'element-plus'
defineOptions({
name: 'TransientReport/monitoringpointReport'
})
@@ -174,6 +166,7 @@ const formd: any = ref({
const templatePolicy: any = ref([])
const tableStore = new TableStore({
publicHeight: 80,
url: '',
method: 'post',
column: []
@@ -185,58 +178,7 @@ onMounted(() => {
size.value = Math.round((180 / dom.offsetHeight) * 100)
}
})
// getList({
// pageNum: 1,
// pageSize: 100,
// type: 0
// }).then(res => {
// templatePolicy.value = res.data.records
// // 默认选中第一个
// if (res.data.records && res.data.records.length > 0) {
// value.value = res.data.records[0].id
// // 触发 change 事件,加载对应的配置
// changeFn(res.data.records[0].id)
// }
// })
const handleNodeClick = (data: any, node: any) => {
if (data.level === 6) {
dotList.value = data
monitoringPoint.setValue('lineId', data.id)
}
}
const changeFn = (val: any) => {
formd.value = {
xq: false,
lb: false,
mdbg: false,
mdtx: false,
sjdITIC: false,
sjdF47: false,
glfbfz: false,
glfbsj: false,
tjbg: false,
tjtx: false,
yybg: false,
yytx: false,
lxbg: false,
lxtx: false,
type: 0
}
let data = {
id: val
}
selectReleation(data).then(res => {
res.data.forEach((item: any) => {
for (let k in formd.value) {
if (item.name == k) {
formd.value[k] = true
return
}
}
})
})
}
const exportEvent = () => {
if (dotList.value.level != 6) {
return ElMessage({
@@ -246,8 +188,8 @@ const exportEvent = () => {
}
let a = ''
formd.value.lineId = dotList.value.id
formd.value.lineName = dotList.value.name
formd.value.lineId = monitoringPoint.state.lineId
formd.value.lineName = monitoringPoint.state.lineName.split('>').at(-1)
formd.value.searchBeginTime = TableHeaderRef.value.datePickerRef.timeValue[0]
formd.value.searchEndTime = TableHeaderRef.value.datePickerRef.timeValue[1]
formd.value.flag = TableHeaderRef.value.datePickerRef.interval

View File

@@ -1,134 +1,134 @@
<template>
<div>
<el-form :inline="true" class="formFlex">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item class="mr5">
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
</el-form-item>
</el-form>
<div v-loading="loading" style="display: flex; overflow: hidden" :style="{ height: height }">
<vxe-table style="flex: 1" v-bind="defaultAttribute" height="100%" :data="region">
<vxe-table-colgroup title="暂态统计(按区域统计)">
<vxe-table-column field="name" title="区域"></vxe-table-column>
<vxe-table-colgroup title="监测点数量">
<vxe-table-column field="onLine" title="在线"></vxe-table-column>
<vxe-table-column field="offLine" title="离线"></vxe-table-column>
</vxe-table-colgroup>
<vxe-table-column field="sagsCount" title="暂降次数"></vxe-table-column>
<vxe-table-column field="breakCount" title="中断次数"></vxe-table-column>
<vxe-table-column field="upCount" title="暂升次数"></vxe-table-column>
</vxe-table-colgroup>
</vxe-table>
<vxe-table style="flex: 1" class="ml10" v-bind="defaultAttribute" height="100%" :data="voltage">
<vxe-table-colgroup title="暂态统计(按电压等级统计)">
<vxe-table-column field="name" title="电压等级"></vxe-table-column>
<vxe-table-colgroup title="监测点数量">
<vxe-table-column field="onLine" title="在线"></vxe-table-column>
<vxe-table-column field="offLine" title="离线"></vxe-table-column>
</vxe-table-colgroup>
<vxe-table-column field="sagsCount" title="暂降次数"></vxe-table-column>
<vxe-table-column field="breakCount" title="中断次数"></vxe-table-column>
<vxe-table-column field="upCount" title="暂升次数"></vxe-table-column>
</vxe-table-colgroup>
</vxe-table>
</div>
</div>
</template>
<script setup lang="ts">
import { useDictData } from '@/stores/dictData'
import DatePicker from '@/components/form/datePicker/index.vue'
import { ElMessage } from 'element-plus'
import { ref, reactive, onMounted } from 'vue'
import { getVoltage, getGeneralSituation, getExport } from '@/api/event-boot/report'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
const dictData = useDictData()
const datePickerRef = ref()
const loading = ref(true)
const formData = reactive({
deptIndex: dictData.state.area[0].id,
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: '',
searchEndTime: '',
serverName: 'event-boot'
})
const height = mainHeight(145).height
const region = ref([])
const voltage = ref([])
const init = () => {
loading.value = true
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
Promise.all([
getGeneralSituation({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Manufacturer',
'Voltage_Level',
'Load_Type'
])[0]
}),
getVoltage({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Power_Network',
'Manufacturer',
'Load_Type'
])[0]
})
]).then(res => {
loading.value = false
region.value = res[0].data
voltage.value = res[1].data
})
}
const exportEvent = () => {
ElMessage({
message: '正在导出中'
})
getExport({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Manufacturer',
'Voltage_Level',
'Load_Type'
])[0]
}).then(res => {
const link = document.createElement('a')
let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'
})
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
link.setAttribute('download', '暂态总体概况.xlsx') // 文件名可自定义
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
ElMessage({
message: '导出成功',
type: 'success'
})
})
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
.formFlex {
display: flex;
justify-content: space-between;
}
</style>
<template>
<div>
<el-form :inline="true" class="formFlex">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item class="mr5">
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
</el-form-item>
</el-form>
<div v-loading="loading" style="display: flex; overflow: hidden" :style="{ height: height }">
<vxe-table style="flex: 1" v-bind="defaultAttribute" height="100%" :data="region">
<vxe-table-colgroup title="暂态统计(按区域统计)">
<vxe-table-column field="name" title="区域"></vxe-table-column>
<vxe-table-colgroup title="监测点数量">
<vxe-table-column field="onLine" title="在线"></vxe-table-column>
<vxe-table-column field="offLine" title="离线"></vxe-table-column>
</vxe-table-colgroup>
<vxe-table-column field="sagsCount" title="暂降次数"></vxe-table-column>
<vxe-table-column field="breakCount" title="中断次数"></vxe-table-column>
<vxe-table-column field="upCount" title="暂升次数"></vxe-table-column>
</vxe-table-colgroup>
</vxe-table>
<vxe-table style="flex: 1" class="ml10" v-bind="defaultAttribute" height="100%" :data="voltage">
<vxe-table-colgroup title="暂态统计(按电压等级统计)">
<vxe-table-column field="name" title="电压等级"></vxe-table-column>
<vxe-table-colgroup title="监测点数量">
<vxe-table-column field="onLine" title="在线"></vxe-table-column>
<vxe-table-column field="offLine" title="离线"></vxe-table-column>
</vxe-table-colgroup>
<vxe-table-column field="sagsCount" title="暂降次数"></vxe-table-column>
<vxe-table-column field="breakCount" title="中断次数"></vxe-table-column>
<vxe-table-column field="upCount" title="暂升次数"></vxe-table-column>
</vxe-table-colgroup>
</vxe-table>
</div>
</div>
</template>
<script setup lang="ts">
import { useDictData } from '@/stores/dictData'
import DatePicker from '@/components/form/datePicker/index.vue'
import { ElMessage } from 'element-plus'
import { ref, reactive, onMounted } from 'vue'
import { getVoltage, getGeneralSituation, getExport } from '@/api/event-boot/report'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
const dictData = useDictData()
const datePickerRef = ref()
const loading = ref(true)
const formData = reactive({
deptIndex: dictData.state.area[0].id,
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: '',
searchEndTime: '',
serverName: 'event-boot'
})
const height = mainHeight(145).height
const region = ref([])
const voltage = ref([])
const init = () => {
loading.value = true
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
Promise.all([
getGeneralSituation({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Manufacturer',
'Voltage_Level',
'Load_Type'
])[0]
}),
getVoltage({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Power_Network',
'Manufacturer',
'Load_Type'
])[0]
})
]).then(res => {
loading.value = false
region.value = res[0].data
voltage.value = res[1].data
})
}
const exportEvent = () => {
ElMessage({
message: '正在导出中'
})
getExport({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Manufacturer',
'Voltage_Level',
'Load_Type'
])[0]
}).then(res => {
const link = document.createElement('a')
let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'
})
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
link.setAttribute('download', '暂态总体概况.xlsx') // 文件名可自定义
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
ElMessage({
message: '导出成功',
type: 'success'
})
})
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
.formFlex {
display: flex;
justify-content: space-between;
}
</style>

View File

@@ -1,292 +1,292 @@
<template>
<div>
<el-form :inline="true" class="formFlex">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item class="mr5">
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
<div v-loading="loading" :style="{ height: height }">
<div style="display: flex">
<my-echart class="bars_w" :options="options1" />
<my-echart class="bars_w" :options="options2" />
</div>
<div style="display: flex">
<my-echart class="bars_w" :options="options3" />
<my-echart class="bars_w" :options="options4" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useDictData } from '@/stores/dictData'
import DatePicker from '@/components/form/datePicker/index.vue'
import { ref, reactive, onMounted } from 'vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getVoltage, getGeneralSituation } from '@/api/event-boot/report'
import { mainHeight } from '@/utils/layout'
const dictData = useDictData()
const datePickerRef = ref()
const loading = ref(true)
const formData = reactive({
deptIndex: dictData.state.area[0].id,
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: '',
searchEndTime: '',
serverName: 'event-boot'
})
const height = mainHeight(145).height
const options1 = ref({})
const options2 = ref({})
const options3 = ref({})
const options4 = ref({})
const init = () => {
let label = {
normal: {
show: true,
textStyle: {
//数值样式
color: '#fff',
fontSize: 14
}
}
}
loading.value = true
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
Promise.all([
getGeneralSituation({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Manufacturer',
'Voltage_Level',
'Load_Type'
])[0]
}),
getVoltage({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Power_Network',
'Manufacturer',
'Load_Type'
])[0]
})
]).then(res => {
// region.value = res[0].data
// voltage.value = res[1].data
let area = []
let onlineData = []
let offlineData = []
res[0].data.forEach(item => {
area.push(item.name)
onlineData.push(item.onLine)
offlineData.push(item.offLine)
})
options1.value = {
title: {
text: '终端运行情况',
subtext: '区域统计'
},
legend: {
data: ['在线', '离线']
},
xAxis: {
name: '(区域)',
data: res[0].data.map(item => item.name)
},
yAxis: {
name: '个' // 给X轴加单位
},
color: ['#07CCCA', '#FFBF00'],
options: {
series: [
{
name: '在线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'green',
data: res[0].data.map(item => item.onLine)
},
{
name: '离线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'orange',
data: res[0].data.map(item => item.offLine)
}
]
}
}
options2.value = {
title: {
text: '终端运行情况',
subtext: '电压等级统计'
},
legend: {
data: ['在线', '离线']
},
xAxis: {
name: '电压\n等级',
data: res[1].data.map(item => item.name)
},
yAxis: {
name: '个' // 给X轴加单位
},
color: ['#07CCCA', '#FFBF00'],
options: {
series: [
{
name: '在线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'green',
data: res[1].data.map(item => item.onLine)
},
{
name: '离线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'orange',
data: res[1].data.map(item => item.offLine)
}
]
}
}
options3.value = {
title: {
text: '暂态事件次数',
subtext: '区域统计'
},
legend: {
data: ['暂降次数', '中断次数', '暂升次数']
},
xAxis: {
name: '(区域)',
data: res[0].data.map(item => item.name)
},
yAxis: {
name: '次' // 给X轴加单位
},
color: ['#07CCCA', '#FFBF00', '#77DA63'],
options: {
series: [
{
name: '暂降次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[0].data.map(item => item.sagsCount)
},
{
name: '中断次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[0].data.map(item => item.breakCount)
},
{
name: '暂升次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[0].data.map(item => item.upCount)
}
]
}
}
options4.value = {
title: {
text: '暂态事件次数',
subtext: '电压等级统计'
},
legend: {
data: ['暂降次数', '中断次数', '暂升次数']
},
color: ['#07CCCA', '#FFBF00', '#77DA63'],
xAxis: {
name: '电压\n等级',
data: res[1].data.map(item => item.name)
},
yAxis: {
name: '次'
},
options: {
series: [
{
name: '暂降次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[1].data.map(item => item.sagsCount)
},
{
name: '中断次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[1].data.map(item => item.breakCount)
},
{
name: '暂升次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[1].data.map(item => item.upCount)
}
]
}
}
loading.value = false
})
}
onMounted(() => {
init()
})
const layout = mainHeight(150) as any
</script>
<style lang="scss" scoped>
.bars_w {
width: 100%;
height: calc(v-bind('layout.height') / 2);
}
.formFlex {
display: flex;
justify-content: space-between;
}
</style>
<template>
<div>
<el-form :inline="true" class="formFlex">
<el-form-item label="统计时间">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item class="mr5">
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
<div v-loading="loading" :style="{ height: height }">
<div style="display: flex">
<my-echart class="bars_w" :options="options1" />
<my-echart class="bars_w" :options="options2" />
</div>
<div style="display: flex">
<my-echart class="bars_w" :options="options3" />
<my-echart class="bars_w" :options="options4" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useDictData } from '@/stores/dictData'
import DatePicker from '@/components/form/datePicker/index.vue'
import { ref, reactive, onMounted } from 'vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getVoltage, getGeneralSituation } from '@/api/event-boot/report'
import { mainHeight } from '@/utils/layout'
const dictData = useDictData()
const datePickerRef = ref()
const loading = ref(true)
const formData = reactive({
deptIndex: dictData.state.area[0].id,
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: '',
searchEndTime: '',
serverName: 'event-boot'
})
const height = mainHeight(145).height
const options1 = ref({})
const options2 = ref({})
const options3 = ref({})
const options4 = ref({})
const init = () => {
let label = {
normal: {
show: true,
textStyle: {
//数值样式
color: '#fff',
fontSize: 14
}
}
}
loading.value = true
formData.searchBeginTime = datePickerRef.value.timeValue[0]
formData.searchEndTime = datePickerRef.value.timeValue[1]
Promise.all([
getGeneralSituation({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Manufacturer',
'Voltage_Level',
'Load_Type'
])[0]
}),
getVoltage({
...formData,
statisticalType: dictData.getBasicData('Statistical_Type', [
'Report_Type',
'Power_Network',
'Manufacturer',
'Load_Type'
])[0]
})
]).then(res => {
// region.value = res[0].data
// voltage.value = res[1].data
let area = []
let onlineData = []
let offlineData = []
res[0].data.forEach(item => {
area.push(item.name)
onlineData.push(item.onLine)
offlineData.push(item.offLine)
})
options1.value = {
title: {
text: '终端运行情况',
subtext: '区域统计'
},
legend: {
data: ['在线', '离线']
},
xAxis: {
name: '(区域)',
data: res[0].data.map(item => item.name)
},
yAxis: {
name: '个' // 给X轴加单位
},
color: ['#07CCCA', '#FFBF00'],
options: {
series: [
{
name: '在线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'green',
data: res[0].data.map(item => item.onLine)
},
{
name: '离线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'orange',
data: res[0].data.map(item => item.offLine)
}
]
}
}
options2.value = {
title: {
text: '终端运行情况',
subtext: '电压等级统计'
},
legend: {
data: ['在线', '离线']
},
xAxis: {
name: '电压\n等级',
data: res[1].data.map(item => item.name)
},
yAxis: {
name: '个' // 给X轴加单位
},
color: ['#07CCCA', '#FFBF00'],
options: {
series: [
{
name: '在线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'green',
data: res[1].data.map(item => item.onLine)
},
{
name: '离线',
type: 'bar',
barMaxWidth: 20,
stack: 'account',
// color: 'orange',
data: res[1].data.map(item => item.offLine)
}
]
}
}
options3.value = {
title: {
text: '暂态事件次数',
subtext: '区域统计'
},
legend: {
data: ['暂降次数', '中断次数', '暂升次数']
},
xAxis: {
name: '(区域)',
data: res[0].data.map(item => item.name)
},
yAxis: {
name: '次' // 给X轴加单位
},
color: ['#07CCCA', '#FFBF00', '#77DA63'],
options: {
series: [
{
name: '暂降次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[0].data.map(item => item.sagsCount)
},
{
name: '中断次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[0].data.map(item => item.breakCount)
},
{
name: '暂升次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[0].data.map(item => item.upCount)
}
]
}
}
options4.value = {
title: {
text: '暂态事件次数',
subtext: '电压等级统计'
},
legend: {
data: ['暂降次数', '中断次数', '暂升次数']
},
color: ['#07CCCA', '#FFBF00', '#77DA63'],
xAxis: {
name: '电压\n等级',
data: res[1].data.map(item => item.name)
},
yAxis: {
name: '次'
},
options: {
series: [
{
name: '暂降次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[1].data.map(item => item.sagsCount)
},
{
name: '中断次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[1].data.map(item => item.breakCount)
},
{
name: '暂升次数',
type: 'bar',
stack: 'account',
barWidth: 20,
data: res[1].data.map(item => item.upCount)
}
]
}
}
loading.value = false
})
}
onMounted(() => {
init()
})
const layout = mainHeight(150) as any
</script>
<style lang="scss" scoped>
.bars_w {
width: 100%;
height: calc(v-bind('layout.height') / 2);
}
.formFlex {
display: flex;
justify-content: space-between;
}
</style>