3 Commits

Author SHA1 Message Date
guanj
a7b5762946 告警事件添加设备选取功能 2026-07-14 09:18:32 +08:00
guanj
0e70182c89 修改列设置点击问题 2026-07-10 08:55:28 +08:00
guanj
e6313ca8c3 全局添加列配置功能 2026-07-09 15:42:58 +08:00
92 changed files with 8535 additions and 8563 deletions

6157
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,10 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --mode ypt" ,
"dev:zl": "vite --mode zl",
"dev:ypt": "vite --mode ypt",
"build": "vite build",
"build": "vite build --mode ypt",
"build:zl": "vite build --mode zl",
"build:ypt": "vite build --mode ypt",
"preview": "vite preview"
@@ -51,7 +51,8 @@
"vue-i18n": "9.10.2",
"vue-router": "4",
"vue-types": "^5.1.1",
"vxe-table": "^4.5.17",
"vxe-pc-ui": "~4.15.19",
"vxe-table": "^4.19.22",
"vxe-table-plugin-export-xlsx": "^4.0.7",
"web-storage-cache": "^1.1.1",
"xe-utils": "^3.5.14"
@@ -67,6 +68,7 @@
"typescript": "^5.2.2",
"unplugin-auto-import": "^0.16.7",
"vite": "^5.0.8",
"vite-plugin-lazy-import": "^1.0.7",
"vue-tsc": "^1.8.25"
}
}

7038
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
<template>
<div>
<!--指标越限程度 -->
<TableHeader ref="TableHeaderRef" :showReset="false" @selectChange="selectChange" datePicker
<TableHeader ref="TableHeaderRef" :showReset="false" showCustomColumn @selectChange="selectChange" datePicker
:timeKeyList="prop.timeKey" v-if="fullscreen"></TableHeader>
<my-echart class="tall" :options="echartList"
:style="{ width: prop.width, height: `calc(${prop.height} / 2 )` }" />

View File

@@ -2,7 +2,7 @@
<div>
<!-- 指标越限详情 -->
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
<TableHeader datePicker showExport :showReset="false" showCustomColumn ref="tableHeaderRef">
<template v-slot:select>
<!-- <el-form-item label="监测点">
<el-select
@@ -76,18 +76,18 @@ const tableStore: any = new TableStore({
{
title: '日期',
field: 'time',
width: '120',
minWidth: '120',
sortable: true
},
{
title: '名称',
field: 'lineName',
width: '120'
minWidth: '120'
},
{
title: '长时闪变越限(%)',
field: 'flickerOvertime',
width: '90',
minWidth: '90',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flickerOvertime}</span>`
@@ -96,7 +96,7 @@ const tableStore: any = new TableStore({
{
title: '电压偏差越限(%)',
field: 'voltageDevOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
@@ -105,7 +105,7 @@ const tableStore: any = new TableStore({
{
title: '三相不平衡度越限(%)',
field: 'ubalanceOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`

View File

@@ -1,7 +1,7 @@
<template>
<div>
<!--电网侧指标越限统计 -->
<TableHeader :showReset="false" ref="TableHeaderRef" @selectChange="selectChange" datePicker
<TableHeader :showReset="false" ref="TableHeaderRef" showCustomColumn @selectChange="selectChange" datePicker
:timeKeyList="prop.timeKey" v-if="fullscreen"></TableHeader>
<my-echart class="tall" :options="echartList" :style="{
width: prop.width,

View File

@@ -2,7 +2,7 @@
<div>
<!-- 指标越限详情 -->
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
<TableHeader datePicker showExport showCustomColumn :showReset="false" ref="tableHeaderRef">
<!-- <template v-slot:select>
<el-form-item label="监测点">
<el-select
@@ -77,18 +77,18 @@ const tableStore: any = new TableStore({
{
title: '日期',
field: 'time',
width: '120',
minWidth: '120',
sortable: true
},
{
title: '监测点名称',
field: 'lineName',
width: '150'
minWidth: '150'
},
{
title: '长时闪变越限(分钟)',
field: 'flickerOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flickerOvertime}</span>`
@@ -96,7 +96,7 @@ const tableStore: any = new TableStore({
}, {
title: '电压偏差越限(分钟)',
field: 'uaberranceOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
@@ -105,7 +105,7 @@ const tableStore: any = new TableStore({
{
title: '三相不平衡度越限(分钟)',
field: 'ubalanceOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`

View File

@@ -1,7 +1,7 @@
<template>
<div>
<!--主要监测点列表 -->
<TableHeader :showReset="false" showExport :timeKeyList="prop.timeKey" @selectChange="selectChange"
<TableHeader :showReset="false" showExport showCustomColumn :timeKeyList="prop.timeKey" @selectChange="selectChange"
v-if="fullscreen" ref="TableHeaderRef">
<template v-slot:select>
<el-form-item label="关键字筛选">

View File

@@ -1,7 +1,7 @@
<template>
<!-- 综合评估详情 -->
<el-dialog draggable title="指标合格率统计" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport :showReset="false">
<TableHeader datePicker showExport showCustomColumn :showReset="false">
<template v-slot:select>
<el-form-item label="监测点名称">
<el-select
@@ -38,7 +38,7 @@ const loop50 = (key: string) => {
title: i + '次',
// field: key + i,
field: 'flicker',
width: '80'
minWidth: '80'
})
}
return list
@@ -61,32 +61,32 @@ const tableStore: any = new TableStore({
{
title: '日期',
field: 'time',
width: '150'
minWidth: '150'
},
{
title: '名称',
field: 'name',
width: '150'
minWidth: '150'
},
{
title: '长时闪变越限(分钟)',
field: 'flicker',
width: '80'
minWidth: '80'
},
{
title: '三相不平衡度越限(分钟)',
field: 'flicker',
width: '100'
minWidth: '100'
},
{
title: '电压偏差越限(分钟)',
field: 'flicker',
width: '100'
minWidth: '100'
},
{
title: '频率偏差越限(分钟)',
field: 'flicker',
width: '100'
minWidth: '100'
},
{
title: '谐波电压越限(分钟)',

View File

@@ -2,7 +2,7 @@
<div>
<!-- 综合评估详情 -->
<el-dialog draggable title="指标合格率统计" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport :showReset="false">
<TableHeader datePicker showExport showCustomColumn :showReset="false">
<template v-slot:select>
<el-form-item label="监测点名称">
<el-select
@@ -76,17 +76,17 @@ const tableStore: any = new TableStore({
{
title: '日期',
field: 'time',
width: '150'
minWidth: '150'
},
{
title: '名称',
field: 'name',
width: '150'
minWidth: '150'
},
{
title: '长时闪变越限(分钟)',
field: 'flicker',
width: '80',
minWidth: '80',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flicker}</span>`
@@ -95,17 +95,17 @@ const tableStore: any = new TableStore({
{
title: '三相不平衡度越限(分钟)',
field: 'flicker',
width: '100'
minWidth: '100'
},
{
title: '电压偏差越限(分钟)',
field: 'flicker',
width: '100'
minWidth: '100'
},
{
title: '频率偏差越限(分钟)',
field: 'flicker',
width: '100'
minWidth: '100'
},
{
title: '谐波电压越限(分钟)',

View File

@@ -2,7 +2,7 @@
<div>
<!-- 指标越限详情 -->
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
<TableHeader datePicker showExport showCustomColumn :showReset="false" ref="tableHeaderRef">
<template v-slot:select>
<!-- <el-form-item label="监测点">
<el-select
@@ -49,7 +49,7 @@ const loop50 = (key: string) => {
list.push({
title: i + '次',
field: key + i + 'Overtime',
width: '60',
minWidth: '60',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row[key + i + 'Overtime']}</span>`
@@ -76,18 +76,18 @@ const tableStore: any = new TableStore({
{
title: '日期',
field: 'time',
width: '120',
minWidth: '120',
sortable: true
},
{
title: '名称',
field: 'lineName',
width: '120'
minWidth: '120'
},
{
title: '长时闪变越限(%)',
field: 'flickerOvertime',
width: '90',
minWidth: '90',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flickerOvertime}</span>`
@@ -96,7 +96,7 @@ const tableStore: any = new TableStore({
{
title: '电压偏差越限(%)',
field: 'voltageDevOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
@@ -105,7 +105,7 @@ const tableStore: any = new TableStore({
{
title: '三相不平衡度越限(%)',
field: 'ubalanceOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`

View File

@@ -1,26 +1,56 @@
<template>
<div>
<!-- 监测点列表 -->
<TableHeader ref="TableHeaderRef" :showReset="false" showExport @selectChange="selectChange" v-if="fullscreen"
:timeKeyList="prop.timeKey">
<TableHeader
ref="TableHeaderRef"
:showReset="false"
showExport
@selectChange="selectChange"
v-if="fullscreen"
:timeKeyList="prop.timeKey"
>
<template #select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="请输入监测点名称" />
<el-input
maxlength="32"
show-word-limit
style="width: 240px"
v-model.trim="tableStore.table.params.searchValue"
clearable
placeholder="请输入监测点名称"
/>
</el-form-item>
</template>
</TableHeader>
<Table ref="tableRef" @cell-click="cellClickEvent"
:height="`calc(${prop.height} - ${headerHeight}px + ${fullscreen ? -58 : 56}px )`"></Table>
<Table
ref="tableRef"
@cell-click="cellClickEvent"
:height="`calc(${prop.height} - ${headerHeight}px + ${fullscreen ? -58 : 56}px )`"
></Table>
<!-- 指标越限详情 -->
<OverLimitDetails ref="OverLimitDetailsRef" />
<!-- 上传对话框 -->
<el-dialog v-model="uploadDialogVisible" title="上传报告" append-to-body width="500px" @closed="handleDialogClosed">
<el-upload ref="uploadRef" class="upload-demo" action="" accept=".doc,.docx,.PDF" :on-change="handleChange"
:before-upload="beforeUpload" :limit="1" :auto-upload="false" :on-exceed="handleExceed"
:on-remove="handleRemove" :file-list="fileList">
<el-dialog
v-model="uploadDialogVisible"
title="上传报告"
append-to-body
width="500px"
@closed="handleDialogClosed"
>
<el-upload
ref="uploadRef"
class="upload-demo"
action=""
accept=".doc,.docx,.PDF"
:on-change="handleChange"
:before-upload="beforeUpload"
:limit="1"
:auto-upload="false"
:on-exceed="handleExceed"
:on-remove="handleRemove"
:file-list="fileList"
>
<el-button type="primary">点击上传</el-button>
<template #tip>
<div class="el-upload__tip">请上传Word或PDF文件</div>
@@ -110,7 +140,7 @@ const tableStore: any = new TableStore({
minWidth: 150,
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row?.cellValue || '/'}</span>`
return `<span style='cursor: pointer;text-decoration: underline;'>${row?.lineName || '/'}</span>`
}
},
{ title: '设备名称', field: 'devName', minWidth: 150, align: 'center' },
@@ -166,7 +196,6 @@ const tableStore: any = new TableStore({
}
},
{
title: '治理方案',
field: 'govern',
@@ -395,7 +424,6 @@ const handleUpload = async () => {
uploadDialogVisible.value = false
tableStore.index()
return Promise.resolve(result)
} catch (error: any) {
ElMessage.error('上传失败: ' + (error.message || '未知错误'))
return Promise.reject(error)

View File

@@ -2,7 +2,7 @@
<div>
<!-- 指标越限详情 -->
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="1200">
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
<TableHeader datePicker showExport showCustomColumn :showReset="false" ref="tableHeaderRef">
<template v-slot:select>
<!-- <el-form-item label="监测点">
<el-select
@@ -76,18 +76,18 @@ const tableStore: any = new TableStore({
{
title: '日期',
field: 'time',
width: '120',
minWidth: '120',
sortable: true
},
{
title: '名称',
field: 'lineName',
width: '120'
minWidth: '120'
},
{
title: '长时闪变越限(%)',
field: 'flickerOvertime',
width: '90',
minWidth: '90',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flickerOvertime}</span>`
@@ -96,7 +96,7 @@ const tableStore: any = new TableStore({
{
title: '电压偏差越限(%)',
field: 'voltageDevOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
@@ -105,7 +105,7 @@ const tableStore: any = new TableStore({
{
title: '三相不平衡度越限(%)',
field: 'ubalanceOvertime',
width: '100',
minWidth: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`

View File

@@ -1,7 +1,7 @@
<template>
<div>
<!--敏感负荷列表 -->
<TableHeader ref="TableHeaderRef" :showReset="false" @selectChange="selectChange" v-if="fullscreen"
<TableHeader ref="TableHeaderRef" :showReset="false" showCustomColumn @selectChange="selectChange" v-if="fullscreen"
:timeKeyList="prop.timeKey">
<template #select>
<el-form-item label="关键字筛选">

View File

@@ -1,7 +1,7 @@
<template>
<div>
<el-dialog draggable title="暂态事件" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport ref="tableHeaderRef" @selectChange="selectChange"
<TableHeader datePicker showExport showCustomColumn ref="tableHeaderRef" @selectChange="selectChange"
@onResetForm="onResetForm">
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
<TableHeader datePicker showExport ref="tableHeaderRef" @selectChange="selectChange"
<TableHeader datePicker showExport showCustomColumn ref="tableHeaderRef" @selectChange="selectChange"
@onResetForm="onResetForm">
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<!--暂态事件统计 -->
<TableHeader ref="TableHeaderRef" :showReset="false" @selectChange="selectChange" datePicker v-if="fullscreen"
<TableHeader ref="TableHeaderRef" :showReset="false" showCustomColumn @selectChange="selectChange" datePicker v-if="fullscreen"
:timeKeyList="prop.timeKey"></TableHeader>
<my-echart class="tall" :options="echartList" :style="{
width: prop.width,

View File

@@ -5,7 +5,7 @@
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, defineExpose, watch, nextTick } from 'vue'
import { onBeforeUnmount, onMounted, ref, watch, nextTick } from 'vue'
// import echarts from './echarts'
import * as echarts from 'echarts' // 全引入
import 'echarts-gl'

View File

@@ -14,10 +14,17 @@ import html2canvas from 'html2canvas'
import $ from 'jquery'
import * as echarts from 'echarts'
import { mainHeight } from '@/utils/layout'
import { calcRmsYAxisRange, formatAxisLabel } from '@/utils/chartAxisHelper'
import {
calcRmsYAxisRange,
createWaveLineSeries,
formatAxisLabel,
formatWaveAxisTooltip,
WAVE_AXIS_POINTER,
WAVE_DATA_ZOOM
} from '@/utils/chartAxisHelper'
import url from '@/assets/img/point.png'
import url2 from '@/assets/img/dw.png'
import { buildWaveCacheKey, getWaveCache, setWaveCache } from '@/utils/waveCache'
import { buildWaveCacheKey, getWaveCache, setWaveCache, removeWaveCacheByEvent } from '@/utils/waveCache'
import { getRmsWorker, buildWorkerPayload } from '@/utils/waveWorkerPool'
import { buildExportBaseName, formatExportDateTime } from '@/utils/echartMethod'
let waveRequestId = 0
@@ -186,6 +193,9 @@ onMounted(() => {
})
onBeforeUnmount(() => {
waveRequestId++
pendingCacheKeys.clear()
removeWaveCacheByEvent(props.wp, props.boxoList)
backbxlb()
window.removeEventListener('resize', handleResize)
})
@@ -660,21 +670,9 @@ const initWave = (
tooltip: {
top: '10px',
trigger: 'axis',
axisPointer: WAVE_AXIS_POINTER,
borderColor: 'grey',
formatter: function (params: any) {
let tips = '时刻:' + params[0].data[0] + '</br/>'
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName != '暂降触发点') {
tips +=
params[i].marker +
params[i].seriesName +
':' +
(params[i].value[1] - 0).toFixed(2) +
'<br/>'
}
}
return tips
},
formatter: (params: any) => formatWaveAxisTooltip(params),
textStyle: {
color: '#fff',
fontStyle: 'normal',
@@ -814,52 +812,11 @@ const initWave = (
top: '60px'
// containLabel: true
},
dataZoom: [
{
type: 'inside',
height: 13,
start: 0,
bottom: '10px',
end: 100,
filterMode: 'none'
},
{
start: 0,
height: 13,
bottom: '10px',
end: 100,
filterMode: 'none'
}
],
dataZoom: WAVE_DATA_ZOOM,
series: [
{
name: a,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#DAA520' },
data: radata
},
{
name: b,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#2E8B57' },
data: rbdata
},
{
name: c,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#A52a2a' },
data: rcdata
},
createWaveLineSeries(a, radata, '#DAA520'),
createWaveLineSeries(b, rbdata, '#2E8B57'),
createWaveLineSeries(c, rcdata, '#A52a2a'),
{
name: '暂降触发点',
type: 'scatter',
@@ -1024,21 +981,9 @@ const drawPics = (
tooltip: {
top: '10px',
trigger: 'axis',
axisPointer: WAVE_AXIS_POINTER,
borderColor: 'grey',
formatter: function (params: any) {
let tips = '时刻:' + params[0].data[0] + '</br/>'
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName != '暂降触发点') {
tips +=
params[i].marker +
params[i].seriesName +
':' +
(params[i].value[1] - 0).toFixed(2) +
'<br/>'
}
}
return tips
},
formatter: (params: any) => formatWaveAxisTooltip(params, { showMarker: false }),
textStyle: {
color: '#fff',
fontStyle: 'normal',
@@ -1163,52 +1108,11 @@ const drawPics = (
top: '60px'
// containLabel: true
},
dataZoom: [
{
type: 'inside',
height: 13,
start: 0,
bottom: '10px',
end: 100,
filterMode: 'none'
},
{
start: 0,
height: 13,
bottom: '10px',
end: 100,
filterMode: 'none'
}
],
dataZoom: WAVE_DATA_ZOOM,
series: [
{
name: a,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#DAA520' },
data: radata
},
{
name: b,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#2E8B57' },
data: rbdata
},
{
name: c,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#A52a2a' },
data: rcdata
}
createWaveLineSeries(a, radata, '#DAA520'),
createWaveLineSeries(b, rbdata, '#2E8B57'),
createWaveLineSeries(c, rcdata, '#A52a2a')
]
}

View File

@@ -14,9 +14,17 @@ import html2canvas from 'html2canvas'
import $ from 'jquery'
import * as echarts from 'echarts'
import { mainHeight } from '@/utils/layout'
import { calcShuYAxisRange, formatAxisLabel } from '@/utils/chartAxisHelper'
import {
calcShuYAxisRange,
createWaveLineSeries,
formatAxisLabel,
formatWaveAxisTooltip,
WAVE_AXIS_POINTER,
WAVE_DATA_ZOOM
} from '@/utils/chartAxisHelper'
import url from '@/assets/img/point.png'
import { buildWaveCacheKey, getWaveCache, setWaveCache } from '@/utils/waveCache'
import { buildWaveCacheKey, getWaveCache, setWaveCache, removeWaveCacheByEvent } from '@/utils/waveCache'
import { getShuWorker, buildWorkerPayload } from '@/utils/waveWorkerPool'
import { buildExportBaseName, formatExportDateTime } from '@/utils/echartMethod'
@@ -192,6 +200,9 @@ onMounted(() => {
})
onBeforeUnmount(() => {
waveRequestId++
pendingCacheKeys.clear()
removeWaveCacheByEvent(props.wp, props.boxoList)
backbxlb()
window.removeEventListener('resize', handleResize)
})
@@ -430,26 +441,14 @@ const initWave = (
tooltip: {
top: '10px',
trigger: 'axis',
axisPointer: WAVE_AXIS_POINTER,
borderColor: 'grey',
style: {
color: '#fff',
fontSize: '15px',
padding: 10
},
formatter: function (params: any) {
let tips = '时刻:' + params[0].data[0] + '</br/>'
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName != '暂降触发点') {
tips +=
params[i].marker +
params[i].seriesName +
':' +
(params[i].value[1] - 0).toFixed(2) +
'<br/>'
}
}
return tips
},
formatter: (params: any) => formatWaveAxisTooltip(params),
textStyle: {
color: '#fff',
fontStyle: 'normal',
@@ -577,55 +576,11 @@ const initWave = (
bottom: '45px',
top: '60px'
},
dataZoom: [
{
type: 'inside',
height: 13,
start: 0,
bottom: '10px',
end: 100,
filterMode: 'none'
},
{
start: 0,
height: 13,
bottom: '10px',
end: 100,
filterMode: 'none'
}
],
dataZoom: WAVE_DATA_ZOOM,
series: [
{
name: a,
type: 'line',
large: true,
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#DAA520' },
data: adata
},
{
name: b,
type: 'line',
large: true,
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#2E8B57' },
data: bdata
},
{
name: c,
type: 'line',
large: true,
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#A52a2a' },
data: cdata
},
createWaveLineSeries(a, adata, '#DAA520'),
createWaveLineSeries(b, bdata, '#2E8B57'),
createWaveLineSeries(c, cdata, '#A52a2a'),
{
name: '暂降触发点',
type: 'scatter',
@@ -778,16 +733,9 @@ const drawPics = (
const option = {
tooltip: {
trigger: 'axis',
axisPointer: WAVE_AXIS_POINTER,
borderColor: 'grey',
formatter: function (params: any) {
let tips = '时刻:' + params[0].data[0] + '</br/>'
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName != '暂降触发点') {
tips += params[i].seriesName + ':' + (params[i].value[1] - 0).toFixed(2) + '<br/>'
}
}
return tips
},
formatter: (params: any) => formatWaveAxisTooltip(params, { showMarker: false }),
textStyle: {
color: '#fff',
fontStyle: 'normal',
@@ -905,55 +853,11 @@ const drawPics = (
top: '60px'
// containLabel: true
},
dataZoom: [
{
type: 'inside',
height: 13,
start: 0,
bottom: '10px',
end: 100,
filterMode: 'none'
},
{
start: 0,
height: 13,
bottom: '10px',
end: 100,
filterMode: 'none'
}
],
dataZoom: WAVE_DATA_ZOOM,
series: [
{
name: a,
type: 'line',
large: true,
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#DAA520' },
data: adata
},
{
name: b,
type: 'line',
large: true,
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#2E8B57' },
data: bdata
},
{
name: c,
type: 'line',
large: true,
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: { color: '#A52a2a' },
data: cdata
}
createWaveLineSeries(a, adata, '#DAA520'),
createWaveLineSeries(b, bdata, '#2E8B57'),
createWaveLineSeries(c, cdata, '#A52a2a')
]
}

View File

@@ -16,7 +16,7 @@ export default defineComponent({
required: true
},
size: {
type: String,
type: [String, Number],
default: '18px'
},
color: {
@@ -27,7 +27,7 @@ export default defineComponent({
setup(props) {
const iconStyle = computed((): CSSProperties => {
const { size, color } = props
let s = `${size.replace('px', '')}px`
const s = typeof size === 'number' ? `${size}px` : `${String(size).replace('px', '')}px`
return {
fontSize: s,
color: color

View File

@@ -10,7 +10,7 @@ import { computed, type CSSProperties } from 'vue'
import { isExternal } from '@/utils/common'
interface Props {
name: string
size: string
size: string | number
color: string
}
@@ -20,19 +20,21 @@ const props = withDefaults(defineProps<Props>(), {
color: '#000000',
})
const s = `${props.size.replace('px', '')}px`
const s = computed(() =>
typeof props.size === 'number' ? `${props.size}px` : `${String(props.size).replace('px', '')}px`
)
const iconName = computed(() => `#${props.name}`)
const iconStyle = computed((): CSSProperties => {
return {
color: props.color,
fontSize: s,
fontSize: s.value,
}
})
const isUrl = computed(() => isExternal(props.name))
const urlIconStyle = computed(() => {
return {
width: s,
height: s,
width: s.value,
height: s.value,
mask: `url(${props.name}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.name}) no-repeat 50% 50%`,
}

View File

@@ -9,9 +9,8 @@ export const defaultAttribute: VxeTableProps = {
columnConfig: { resizable: true },
rowConfig: { isCurrent: true, isHover: true },
scrollX: { scrollToLeftOnChange: true },
scrollY: { scrollToTopOnChange: true, enabled: true },
treeConfig: {
reserve: true
},
showOverflow:true
scrollY: { scrollToTopOnChange: true, enabled: true, gt: 100 },
customConfig: { enabled: true, allowFixed: false, showFooter: false, immediate: true ,mode:'default'},
showOverflow: 'tooltip',
showHeaderOverflow: false
}

View File

@@ -1,401 +1,427 @@
<template>
<div ref="tableHeader" class="cn-table-header">
<div class="table-header ba-scroll-style" :key="num">
<el-form
style="flex: 1; height: 34px; margin-right: 0px; display: flex; flex-wrap: wrap"
ref="headerForm"
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
>
<el-form-item label="日期" v-if="datePicker" style="grid-column: span 2; max-width: 570px">
<DatePicker
ref="datePickerRef"
:nextFlag="nextFlag"
:theCurrentTime="theCurrentTime"
@change="handleDatePickerChange"
:timeKeyList="props.timeKeyList"
></DatePicker>
</el-form-item>
<el-form-item label="区域" v-if="area">
<Area ref="areaRef" v-model.trim="tableStore.table.params.deptIndex" />
</el-form-item>
<slot name="select"></slot>
</el-form>
<template v-if="$slots.select || datePicker || showSearch">
<el-button type="primary" @click="showSelectChange" v-if="showUnfoldButton">
<Icon size="14" name="el-icon-ArrowUp" style="color: #fff" v-if="showSelect" />
<Icon size="14" name="el-icon-ArrowDown" style="color: #fff" v-else />
</el-button>
<el-button
@click="onComSearch"
v-if="showSearch &&showQuery"
:loading="tableStore.table.loading"
type="primary"
:icon="Search"
>
查询
</el-button>
<el-button
@click="onResetForm"
v-if="showSearch && showReset"
:loading="tableStore.table.loading"
:icon="RefreshLeft"
>
重置
</el-button>
<el-button
@click="onExport"
v-if="showExport"
:loading="tableStore.table.exportLoading"
type="primary"
icon="el-icon-Download"
>
导出
</el-button>
</template>
<slot name="operation"></slot>
</div>
<el-form
:style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose"
ref="headerFormSecond"
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
></el-form>
</div>
</template>
<script setup lang="ts">
import { inject, ref, onMounted, nextTick, onUnmounted } from 'vue'
import type TableStore from '@/utils/tableStore'
import DatePicker from '@/components/form/datePicker/index.vue'
import Area from '@/components/form/area/index.vue'
import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import { Search, RefreshLeft } from '@element-plus/icons-vue'
import { defineProps } from 'vue'
import { useTimeCacheStore } from '@/stores/timeCache'
import { useRoute } from 'vue-router'
const emit = defineEmits(['selectChange','onResetForm'])
const tableStore = inject('tableStore') as TableStore
const tableHeader = ref()
const datePickerRef = ref()
const dictData = useDictData()
const areaRef = ref()
const headerForm = ref()
const headerFormSecond = ref()
const num = ref(0)
// 获取路由和缓存 store
const route = useRoute()
const timeCacheStore = useTimeCacheStore()
interface Props {
datePicker?: boolean
area?: boolean
showSearch?: boolean
nextFlag?: boolean //控制时间是否可以往后推
theCurrentTime?: boolean //控制时间前3天展示上个月时间
showQuery?: boolean //是否显示查詢
showReset?: boolean //是否显示重置
showExport?: boolean //导出控制
timeCacheFlag?: boolean //是否取缓存时间
timeKeyList?: string[] //日期下拉列表
}
const props = withDefaults(defineProps<Props>(), {
datePicker: false,
area: false,
showSearch: true,
nextFlag: false,
theCurrentTime: true,
showReset: true,
showQuery: true,
showExport: false,
timeCacheFlag: true,
timeKeyList: () => ['1', '2', '3', '4', '5'] // 修改为箭头函数返回空数组
})
// 处理 DatePicker 值变化事件
const handleDatePickerChange = (value: any) => {
// 将值缓存到 timeCache
// if (value) {
// timeCacheStore.setCache(route.path, value.interval, value.timeValue)
// }
// 将 datePicker 的变化传递给父组件
emit('selectChange', true, tableHeader.value.offsetHeight, value)
}
// 动态计算table高度
let resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
handlerHeight()
computedSearchRow()
}
})
const showUnfoldButton = ref(false)
const headerFormSecondStyleOpen = {
opacity: 1,
height: 'auto',
padding: '0 15px 0px 15px'
}
const headerFormSecondStyleClose = {
opacity: 0,
height: '0',
padding: '0'
}
onMounted(() => {
// 设置初始值到 DatePicker
if (props.datePicker && datePickerRef.value) {
// 从缓存中获取值并设置
const cached = timeCacheStore.getCache(route.path)
if (props.timeCacheFlag && cached) {
if (cached.interval !== undefined) {
datePickerRef.value.setInterval(cached.interval)
}
if (cached.timeValue) {
datePickerRef.value.timeValue = cached.timeValue
}
}
// 更新 tableStore 参数
tableStore.table.params.searchBeginTime = datePickerRef.value?.timeValue?.[0]
tableStore.table.params.searchEndTime = datePickerRef.value?.timeValue?.[1]
tableStore.table.params.startTime = datePickerRef.value?.timeValue?.[0]
tableStore.table.params.endTime = datePickerRef.value?.timeValue?.[1]
tableStore.table.params.timeFlag = datePickerRef.value?.timeFlag
}
if (props.area) {
tableStore.table.params.deptIndex = dictData.state.area[0].id
}
nextTick(() => {
resizeObserver.observe(tableHeader.value)
computedSearchRow()
})
})
onUnmounted(() => {
resizeObserver.disconnect()
})
const handlerHeight = () => {
if (tableStore && tableStore.table) {
tableStore.table.height = mainHeight(
tableStore.table.publicHeight + tableHeader.value.offsetHeight + (tableStore.showPage ? 58 : 0) + 20
).height as string
}
}
// 刷新页面handler高度出下拉
const computedSearchRow = () => {
if (!headerForm.value.$el) return
// 清空headerFormSecond.value.$el下的元素
while (headerFormSecond.value.$el.firstChild) {
headerForm.value.$el.appendChild(headerFormSecond.value.$el.firstChild)
}
// 获取第一行放了几个表单
const elFormItem = headerForm.value.$el.querySelectorAll('.el-form-item')
// 把第一行放不下的复制一份放到headerFormSecond.value.$el
let width = 0
for (let i = 0; i < elFormItem.length; i++) {
width += elFormItem[i].offsetWidth + 32
if (width > headerForm.value.$el.offsetWidth) {
headerFormSecond.value.$el.appendChild(elFormItem[i])
}
}
// 判断是否需要折叠
if (headerFormSecond.value.$el.scrollHeight > 0) {
showUnfoldButton.value = true
} else {
showUnfoldButton.value = false
}
}
const showSelect = ref(false)
const showSelectChange = () => {
showSelect.value = !showSelect.value
setTimeout(() => {
emit('selectChange', showSelect.value, tableHeader.value.offsetHeight)
}, 20)
}
const onComSearch = async () => {
if (props.datePicker) {
tableStore.table.params.searchBeginTime = datePickerRef.value.timeValue[0]
tableStore.table.params.searchEndTime = datePickerRef.value.timeValue[1]
tableStore.table.params.startTime = datePickerRef.value.timeValue[0]
tableStore.table.params.endTime = datePickerRef.value.timeValue[1]
tableStore.table.params.timeFlag = datePickerRef.value.timeFlag
}
await tableStore.onTableAction('search', {})
}
const setDatePicker = (list: any) => {
datePickerRef.value.setTimeOptions(list)
}
const onResetForm = () => {
//时间重置成默认值
datePickerRef.value?.setInterval(3)
emit('onResetForm')
tableStore.onTableAction('reset', {})
}
const setInterval = (val: any) => {
datePickerRef.value.setInterval(val)
}
const setTimeInterval = (val: any) => {
datePickerRef.value.timeValue = val
tableStore.table.params.searchBeginTime = val[0]
tableStore.table.params.searchEndTime = val[1]
tableStore.table.params.startTime = val[0]
tableStore.table.params.endTime = val[1]
}
// 导出
const onExport = () => {
tableStore.onTableAction('export', { showAllFlag: true })
}
defineExpose({
onComSearch,
areaRef,
setDatePicker,
setInterval,
setTimeInterval,
datePickerRef,
showSelectChange,
computedSearchRow
})
</script>
<style scoped lang="scss">
.cn-table-header {
border: 1px solid var(--el-border-color);
}
.table-header {
position: relative;
overflow-x: auto;
box-sizing: border-box;
display: flex;
align-items: center;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
border-bottom: none;
padding: 13px 15px 9px;
font-size: 14px;
.table-header-operate-text {
margin-left: 6px;
}
}
.table-com-search {
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
border: 1px solid var(--ba-border-color);
border-bottom: none;
padding: 13px 15px 20px 15px;
font-size: 14px;
}
#header-form-second,
#header-form {
// display: flex;
// flex-wrap: wrap;
transition: all 0.3s;
}
.mlr-12 {
margin-left: 12px;
}
.mlr-12 + .el-button {
margin-left: 12px;
}
.table-search {
display: flex;
margin-left: auto;
.quick-search {
width: auto;
}
}
.table-search-button-group {
display: flex;
margin-left: 12px;
border: 1px solid var(--el-border-color);
border-radius: var(--el-border-radius-base);
overflow: hidden;
button:focus,
button:active {
background-color: var(--ba-bg-color-overlay);
}
button:hover {
background-color: var(--el-color-info-light-7);
}
.table-search-button-item {
height: 30px;
border: none;
border-radius: 0;
}
.el-button + .el-button {
margin: 0;
}
.right-border {
border-right: 1px solid var(--el-border-color);
}
}
html.dark {
.table-search-button-group {
button:focus,
button:active {
background-color: var(--el-color-info-dark-2);
}
button:hover {
background-color: var(--el-color-info-light-7);
}
button {
background-color: var(--ba-bg-color-overlay);
el-icon {
color: white !important;
}
}
}
}
#header-form,
#header-form-second {
:deep(.el-select) {
--el-select-width: 220px;
}
:deep(.el-input) {
--el-input-width: 220px;
}
}
</style>
<template>
<div ref="tableHeader" class="cn-table-header">
<div class="table-header ba-scroll-style" :key="num">
<el-form
style="flex: 1; min-height: 34px; margin-right: 0px; display: flex; flex-wrap: wrap; align-items: center"
ref="headerForm"
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
>
<el-form-item label="日期" v-if="datePicker" style="grid-column: span 2; max-width: 570px">
<DatePicker
ref="datePickerRef"
:nextFlag="nextFlag"
:theCurrentTime="theCurrentTime"
@change="handleDatePickerChange"
:timeKeyList="props.timeKeyList"
></DatePicker>
</el-form-item>
<el-form-item label="区域" v-if="area">
<Area ref="areaRef" v-model.trim="tableStore.table.params.deptIndex" />
</el-form-item>
<slot name="select"></slot>
</el-form>
<template v-if="$slots.select || datePicker || showSearch">
<el-button type="primary" @click="showSelectChange" v-if="showUnfoldButton">
<Icon :size="14" name="el-icon-ArrowUp" style="color: #fff" v-if="showSelect" />
<Icon :size="14" name="el-icon-ArrowDown" style="color: #fff" v-else />
</el-button>
<el-button
@click="onComSearch"
v-if="showSearch &&showQuery"
:loading="tableStore.table.loading"
type="primary"
:icon="Search"
>
查询
</el-button>
<el-button
@click="onResetForm"
v-if="showSearch && showReset"
:loading="tableStore.table.loading"
:icon="RefreshLeft"
>
重置
</el-button>
<el-button
@click="onExport"
v-if="showExport"
:loading="tableStore.table.exportLoading"
type="primary"
icon="el-icon-Download"
>
导出
</el-button>
</template>
<slot name="operation"></slot>
<el-button
class="ml10 vxe-toolbar-custom-target"
v-if="showCustomColumn"
:icon="Setting"
@click="openCustomColumn"
>
列设置
</el-button>
</div>
<el-form
:style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose"
ref="headerFormSecond"
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
></el-form>
</div>
</template>
<script setup lang="ts">
import { inject, ref, onMounted, nextTick, onUnmounted } from 'vue'
import type TableStore from '@/utils/tableStore'
import DatePicker from '@/components/form/datePicker/index.vue'
import Area from '@/components/form/area/index.vue'
import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import { Search, RefreshLeft, Setting } from '@element-plus/icons-vue'
import { useTimeCacheStore } from '@/stores/timeCache'
import { useRoute } from 'vue-router'
const emit = defineEmits(['selectChange','onResetForm'])
const tableStore = inject('tableStore') as TableStore
const tableHeader = ref()
const datePickerRef = ref()
const dictData = useDictData()
const areaRef = ref()
const headerForm = ref()
const headerFormSecond = ref()
const num = ref(0)
// 获取路由和缓存 store
const route = useRoute()
const timeCacheStore = useTimeCacheStore()
interface Props {
datePicker?: boolean
area?: boolean
showSearch?: boolean
nextFlag?: boolean //控制时间是否可以往后推
theCurrentTime?: boolean //控制时间前3天展示上个月时间
showQuery?: boolean //是否显示查詢
showReset?: boolean //是否显示重置
showExport?: boolean //导出控制
showCustomColumn?: boolean // 列设置
timeCacheFlag?: boolean //是否取缓存时间
timeKeyList?: string[] //日期下拉列表
}
const props = withDefaults(defineProps<Props>(), {
datePicker: false,
area: false,
showSearch: true,
nextFlag: false,
theCurrentTime: true,
showReset: true,
showQuery: true,
showExport: false,
showCustomColumn: false,
timeCacheFlag: true,
timeKeyList: () => ['1', '2', '3', '4', '5'] // 修改为箭头函数返回空数组
})
const openCustomColumn = () => {
const tableRef = tableStore?.table?.ref
if (!tableRef) return
if (tableRef.getCustomVisible?.()) {
tableRef.closeCustom?.()
} else {
tableRef.openCustom?.()
}
}
// 处理 DatePicker 值变化事件
const handleDatePickerChange = (value: any) => {
// 将值缓存到 timeCache
// if (value) {
// timeCacheStore.setCache(route.path, value.interval, value.timeValue)
// }
// 将 datePicker 的变化传递给父组件
emit('selectChange', true, tableHeader.value.offsetHeight, value)
}
// 动态计算table高度
let resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
handlerHeight()
computedSearchRow()
}
})
const showUnfoldButton = ref(false)
const headerFormSecondStyleOpen = {
opacity: 1,
height: 'auto',
padding: '0 15px 0px 15px'
}
const headerFormSecondStyleClose = {
opacity: 0,
height: '0',
padding: '0'
}
onMounted(() => {
if (props.showCustomColumn && tableStore?.table) {
tableStore.table.customColumnInHeader = true
}
// 设置初始值到 DatePicker
if (props.datePicker && datePickerRef.value) {
// 从缓存中获取值并设置
const cached = timeCacheStore.getCache(route.path)
if (props.timeCacheFlag && cached) {
if (cached.interval !== undefined) {
datePickerRef.value.setInterval(cached.interval)
}
if (cached.timeValue) {
datePickerRef.value.timeValue = cached.timeValue
}
}
// 更新 tableStore 参数
tableStore.table.params.searchBeginTime = datePickerRef.value?.timeValue?.[0]
tableStore.table.params.searchEndTime = datePickerRef.value?.timeValue?.[1]
tableStore.table.params.startTime = datePickerRef.value?.timeValue?.[0]
tableStore.table.params.endTime = datePickerRef.value?.timeValue?.[1]
tableStore.table.params.timeFlag = datePickerRef.value?.timeFlag
}
if (props.area) {
tableStore.table.params.deptIndex = dictData.state.area[0].id
}
nextTick(() => {
resizeObserver.observe(tableHeader.value)
computedSearchRow()
})
})
onUnmounted(() => {
if (tableStore?.table) {
tableStore.table.customColumnInHeader = false
}
resizeObserver.disconnect()
})
const handlerHeight = () => {
if (tableStore && tableStore.table) {
tableStore.table.height = mainHeight(
tableStore.table.publicHeight + tableHeader.value.offsetHeight + (tableStore.showPage ? 58 : 0) + 20
).height as string
}
}
// 刷新页面handler高度出下拉
const computedSearchRow = () => {
if (!headerForm.value.$el) return
// 清空headerFormSecond.value.$el下的元素
while (headerFormSecond.value.$el.firstChild) {
headerForm.value.$el.appendChild(headerFormSecond.value.$el.firstChild)
}
// 获取第一行放了几个表单
const elFormItem = headerForm.value.$el.querySelectorAll('.el-form-item')
// 把第一行放不下的复制一份放到headerFormSecond.value.$el
let width = 0
for (let i = 0; i < elFormItem.length; i++) {
width += elFormItem[i].offsetWidth + 32
if (width > headerForm.value.$el.offsetWidth) {
headerFormSecond.value.$el.appendChild(elFormItem[i])
}
}
// 判断是否需要折叠
if (headerFormSecond.value.$el.scrollHeight > 0) {
showUnfoldButton.value = true
} else {
showUnfoldButton.value = false
}
}
const showSelect = ref(false)
const showSelectChange = () => {
showSelect.value = !showSelect.value
setTimeout(() => {
emit('selectChange', showSelect.value, tableHeader.value.offsetHeight)
}, 20)
}
const onComSearch = async () => {
if (props.datePicker) {
tableStore.table.params.searchBeginTime = datePickerRef.value.timeValue[0]
tableStore.table.params.searchEndTime = datePickerRef.value.timeValue[1]
tableStore.table.params.startTime = datePickerRef.value.timeValue[0]
tableStore.table.params.endTime = datePickerRef.value.timeValue[1]
tableStore.table.params.timeFlag = datePickerRef.value.timeFlag
}
await tableStore.onTableAction('search', {})
}
const setDatePicker = (list: any) => {
datePickerRef.value.setTimeOptions(list)
}
const onResetForm = () => {
//时间重置成默认值
datePickerRef.value?.setInterval(3)
emit('onResetForm')
tableStore.onTableAction('reset', {})
}
const setInterval = (val: any) => {
datePickerRef.value.setInterval(val)
}
const setTimeInterval = (val: any) => {
datePickerRef.value.timeValue = val
tableStore.table.params.searchBeginTime = val[0]
tableStore.table.params.searchEndTime = val[1]
tableStore.table.params.startTime = val[0]
tableStore.table.params.endTime = val[1]
}
// 导出
const onExport = () => {
tableStore.onTableAction('export', { showAllFlag: true })
}
defineExpose({
onComSearch,
areaRef,
setDatePicker,
setInterval,
setTimeInterval,
datePickerRef,
showSelectChange,
computedSearchRow
})
</script>
<style scoped lang="scss">
.cn-table-header {
border: 1px solid var(--el-border-color);
}
.table-header {
position: relative;
overflow-x: auto;
box-sizing: border-box;
display: flex;
align-items: center;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
border-bottom: none;
padding: 13px 15px 9px;
font-size: 14px;
.table-header-operate-text {
margin-left: 6px;
}
}
.table-com-search {
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
border: 1px solid var(--ba-border-color);
border-bottom: none;
padding: 13px 15px 20px 15px;
font-size: 14px;
}
#header-form-second,
#header-form {
// display: flex;
// flex-wrap: wrap;
transition: all 0.3s;
}
.mlr-12 {
margin-left: 12px;
}
.mlr-12 + .el-button {
margin-left: 12px;
}
.table-search {
display: flex;
margin-left: auto;
.quick-search {
width: auto;
}
}
.table-search-button-group {
display: flex;
margin-left: 12px;
border: 1px solid var(--el-border-color);
border-radius: var(--el-border-radius-base);
overflow: hidden;
button:focus,
button:active {
background-color: var(--ba-bg-color-overlay);
}
button:hover {
background-color: var(--el-color-info-light-7);
}
.table-search-button-item {
height: 30px;
border: none;
border-radius: 0;
}
.el-button + .el-button {
margin: 0;
}
.right-border {
border-right: 1px solid var(--el-border-color);
}
}
html.dark {
.table-search-button-group {
button:focus,
button:active {
background-color: var(--el-color-info-dark-2);
}
button:hover {
background-color: var(--el-color-info-light-7);
}
button {
background-color: var(--ba-bg-color-overlay);
el-icon {
color: white !important;
}
}
}
}
#header-form,
#header-form-second {
:deep(.el-select) {
--el-select-width: 220px;
}
:deep(.el-input) {
--el-input-width: 220px;
}
}
</style>

View File

@@ -1,21 +1,22 @@
<template>
<div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }">
<div v-if="showCustomColumn && !tableStore?.table?.customColumnInHeader" class="table-custom-toolbar">
<el-button class="vxe-toolbar-custom-target" :icon="Setting" @click="openCustomColumn">列设置</el-button>
</div>
<vxe-table
ref="tableRef"
height="auto"
:key="key"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)"
v-bind="tableBindProps"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
>
<!-- :sort-config="{ remote: true }" -->
<!-- @sort-change="handleSortChange" -->
<!-- :sort-config="{ remote: true }" -->
<!-- @sort-change="handleSortChange" -->
<!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" />
</template>
@@ -64,9 +65,9 @@
</template>
<script setup lang="ts">
import { ref, nextTick, inject, computed, onMounted, watch } from 'vue'
import type { ElTable } from 'element-plus'
import { ref, inject, computed, onMounted, watch, useAttrs } from 'vue'
import { VxeTableEvents, VxeTableInstance } from 'vxe-table'
import { Setting } from '@element-plus/icons-vue'
import FieldRender from '@/components/table/fieldRender/index.vue'
import Column from '@/components/table/column/index.vue'
import GroupColumn from '@/components/table/column/groupColumn.vue'
@@ -74,28 +75,49 @@ import { useConfig } from '@/stores/config'
import type TableStoreClass from '@/utils/tableStore'
import { useRouter } from 'vue-router'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { buildExportBaseName,formatExportDateTime } from '@/utils/echartMethod'
import { buildExportBaseName, formatExportDateTime } from '@/utils/echartMethod'
defineOptions({
inheritAttrs: false
})
const config = useConfig()
const tableRef = ref<VxeTableInstance>()
const tableStore = inject('tableStore') as TableStoreClass
const router = useRouter()
const key = ref(0)
interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> {
interface Props extends /* @vue-ignore */ Partial<VxeTableInstance> {
isGroup?: boolean
showOverflow?: boolean
showOverflow?: boolean | 'ellipsis' | 'title' | 'tooltip'
showCustomColumn?: boolean
height?: string | number
}
const props = withDefaults(defineProps<Props>(), {
isGroup: false,
showOverflow: true,
showOverflow: 'tooltip',
showCustomColumn: false,
height: undefined
})
const attrs = useAttrs()
const tableBindProps = computed(() => {
const overflow = props.showOverflow ?? defaultAttribute.showOverflow
return Object.assign({}, defaultAttribute, attrs, {
showOverflow: overflow,
showHeaderOverflow: false
})
})
const openCustomColumn = () => {
if (!tableRef.value) return
if (tableRef.value.getCustomVisible?.()) {
tableRef.value.closeCustom?.()
} else {
tableRef.value.openCustom?.()
}
}
onMounted(() => {
if (!tableStore?.table) return
tableStore.table.ref = tableRef.value as VxeTableInstance
})
// console.log(props)
const onTableSizeChange = (val: number) => {
@@ -119,7 +141,7 @@ const handleSortChange = ({ field, order }: any) => {
// console.log('🚀 ~ handleSortChange ~ prop, order :', field, order)
if (field && order) {
// 根据当前排序条件对所有数据进行排序
const list = tableStore.table.copyData.sort((a, b) => {
const list = tableStore.table.copyData.sort((a: any, b: any) => {
if (order === 'asc') {
return a[field] > b[field] ? 1 : -1
} else {
@@ -151,13 +173,19 @@ const selectChangeEvent: VxeTableEvents.CheckboxChange<any> = ({ checked }) => {
const getRef = () => {
return tableRef.value
}
const exportColumnFilterMethod = ({ column }: { column: any }) => {
return !(column.title === undefined || column.title === '序号' || column.title === '操作')
}
const getTableExportFilename = () => {
const exportName = tableStore.exportName
if (exportName && typeof exportName === 'object') {
return buildExportBaseName(exportName)
}
const feature =
exportName || (document.querySelectorAll('.ba-nav-tab.active')[0] as HTMLElement | undefined)?.textContent || '导出'
exportName ||
(document.querySelectorAll('.ba-nav-tab.active')[0] as HTMLElement | undefined)?.textContent ||
'导出'
return buildExportBaseName({ feature })
}
@@ -172,14 +200,9 @@ watch(
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
isTitle: true,
data: tableStore.table.allData, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
columnFilterMethod: exportColumnFilterMethod
})
tableStore.table.allFlag = false
}
@@ -204,9 +227,14 @@ defineExpose({
.ba-data-table :deep(.table-header-cell) .cell {
color: var(--el-text-color-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
:deep(.vxe-header--column.table-header-cell) .vxe-cell,
:deep(.vxe-header--column.table-header-cell) .vxe-cell .vxe-cell--wrapper,
:deep(.vxe-header--column.table-header-cell) .vxe-cell .vxe-cell--title {
overflow: visible;
text-overflow: unset;
white-space: normal;
}
.table-pagination {
@@ -226,5 +254,14 @@ defineExpose({
min-width: 128px;
}
}
.table-custom-toolbar {
display: flex;
justify-content: flex-end;
padding: 8px 15px 0;
background-color: var(--ba-bg-color-overlay);
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
}
</style>
<!-- @/components/table/column/GroupColumn.vue@/components/table/column/GroupColumn.vue -->

View File

@@ -25,7 +25,7 @@
</template>
</el-input>
<!-- <Icon
@click="onMenuCollapse"
@click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''"
size="18px"
@@ -86,7 +86,7 @@
</template>
</el-tree>
</div>
</el-collapse-item>
</el-collapse-item>
</el-collapse>
<div v-if="treeType == '2'" class="engineering-tree-wrap" v-loading="loading">
<el-tree class="engineering-tree pt10 collapse-tree" ref="treeRef4" :props="defaultProps"

View File

@@ -4,8 +4,10 @@ import router from './router'
import pinia from '@/stores/index'
import { registerIcons } from '@/utils/common'
import mitt from 'mitt'
import VxeUI from 'vxe-pc-ui'
import VXETable from 'vxe-table'
import XEUtils from 'xe-utils'
import 'vxe-pc-ui/lib/style.css'
import 'vxe-table/lib/style.css'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
@@ -30,6 +32,7 @@ app.use(router)
app.use(pinia)
app.use(ElementPlus)
app.component('ElDialog', CnDialog)
app.use(VxeUI)
app.use(VXETable)
registerIcons(app) // icons

View File

@@ -244,3 +244,7 @@
min-width: 100% !important;
// display: inline-block !important;
}
.el-radio-button__inner {
border: 1px solid var(--el-border-color);
}

View File

@@ -31,6 +31,8 @@ $border-color: map.merge(
@include set-component-css-var('border-color', $border-color);
--el-color-danger: #e26257;
--el-color-success: #2ab914;
--vxe-ui-font-primary-color: var(--el-color-primary);
--vxe-ui-font-primary-lighten-color: var(--el-color-primary);
// --vxe-table-row-current-background-color: var(--el-color-primary-light-7);
// --vxe-table-row-hover-background-color: var(--el-color-primary-light-9);
// --vxe-table-row-hover-current-background-color: var(--el-color-primary-light-7);

View File

@@ -20,8 +20,22 @@
// }
.vxe-header--row {
background: var(--vxe-table-header-background-color);
color: var(--vxe-table-header-font-color);
background: var(--vxe-ui-table-header-background-color, var(--vxe-table-header-background-color));
color: var(--vxe-ui-table-header-font-color, var(--vxe-table-header-font-color));
}
.vxe-table--render-default .vxe-body--column.col--ellipsis > .vxe-cell,
.vxe-table--render-default .vxe-body--column.col--ellipsis > .vxe-cell > .vxe-cell--wrapper {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.vxe-table--render-default .vxe-body--column.col--ellipsis .cn-render-buttons,
.vxe-table--render-default .vxe-body--column.col--ellipsis .ba-render-image {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.is--checked.vxe-checkbox,
@@ -61,6 +75,7 @@
color: var(--el-color-primary-light-5);
}
.vxe-table--render-default .vxe-body--row.row--current,
.vxe-table--render-default .vxe-body--row.row--current > .vxe-body--column,
.vxe-table--render-default .vxe-body--row.row--current:hover {
background-color: var(--el-color-primary-light-9);
}
@@ -85,3 +100,8 @@
// .vxe-table--body .vxe-body--row:nth-child(odd) {
// background-color: #ffffff;
// }
.vxe-table-custom--panel-list > li {
max-width: 28em;
min-width: 15em;
padding: 0.3em 1em 0.2em 1em;
}

View File

@@ -89,6 +89,83 @@ export function calcShuYAxisRange(dataMin: number, dataMax: number): YAxisRange
return buildYAxisRange(axisMin, axisMax)
}
/** 波形图 dataZoom默认 filterMode仅缩放 X 轴) */
export const WAVE_DATA_ZOOM = [
{
type: 'inside' as const,
xAxisIndex: 0,
start: 0,
end: 100,
},
{
type: 'slider' as const,
xAxisIndex: 0,
height: 13,
bottom: '10px',
start: 0,
end: 100
}
]
export const WAVE_AXIS_POINTER = {
type: 'line' as const,
snap: true
}
/** 波形折线 series不做 sampling/smooth保证 tooltip 与折线位置一致 */
export function createWaveLineSeries(name: string | null, data: number[][], color: string) {
return {
name,
type: 'line' as const,
large: data.length > 2000,
largeThreshold: 2000,
smooth: false,
symbol: 'none' as const,
itemStyle: { color },
data
}
}
const WAVE_TOOLTIP_SKIP_SERIES = new Set(['暂降触发点', '最小暂降幅值'])
/** 波形图 axis tooltip从 data/value 中安全取 [x, y] */
export function formatWaveAxisTooltip(
params: any[],
options?: { showMarker?: boolean }
): string {
if (!params?.length) return ''
const showMarker = options?.showMarker !== false
let time = ''
const axisValue = params[0]?.axisValue
if (axisValue != null && Number.isFinite(Number(axisValue))) {
time = String(Number(Number(axisValue).toFixed(2)))
} else {
for (const param of params) {
if (!param || WAVE_TOOLTIP_SKIP_SERIES.has(param.seriesName)) continue
const point = param.data ?? param.value
if (Array.isArray(point) && point.length >= 2) {
time = String(point[0])
break
}
}
}
let tips = `时刻:${time}<br/>`
for (const param of params) {
if (!param?.seriesName || WAVE_TOOLTIP_SKIP_SERIES.has(param.seriesName)) continue
const point = param.data ?? param.value
const y = Array.isArray(point) ? Number(point[1]) : Number(point)
if (!Number.isFinite(y)) continue
const prefix = showMarker ? param.marker || '' : ''
tips += `${prefix}${param.seriesName}:${y.toFixed(2)}<br/>`
}
return tips
}
/** RMS 波形 Y 轴范围 */
export function calcRmsYAxisRange(dataMin: number, dataMax: number): YAxisRange {
const min = Number(dataMin)

View File

@@ -131,6 +131,9 @@ export const yMethod = (arr: any) => {
// } else if (max == 0 && minValue > -1 && minValue < 0) {
// min = -1
// }
if (max > 1 && max < 10) {
max = Math.ceil(max)
}
return [min, max]
}

View File

@@ -1,42 +1,47 @@
import { onMounted, watch } from 'vue'
import { useElementPlusTheme } from 'use-element-plus-theme'
import { useConfig } from '@/stores/config'
const useSetTheme = () => {
const configStore = useConfig()
const elementPlusTheme = useElementPlusTheme(configStore.getColorVal('elementUiPrimary'))
const updateTheme = () => {
const root = document.documentElement
root.style.setProperty('--vxe-table-header-background-color', configStore.getColorVal('tableHeaderBackground'))
root.style.setProperty('--vxe-table-header-font-color', configStore.getColorVal('tableHeaderColor'))
root.style.setProperty('--vxe-table-row-current-background-color', configStore.getColorVal('tableCurrent'))
root.style.setProperty('--vxe-table-row-hover-background-color', configStore.getColorVal('tableCurrent'))
root.style.setProperty(
'--vxe-table-row-hover-current-background-color',
configStore.getColorVal('tableCurrent')
)
root.style.setProperty(
'--vxe-table-row-hover-striped-background-color',
configStore.getColorVal('tableCurrent')
)
}
onMounted(updateTheme)
watch(
() => configStore.getColorVal('elementUiPrimary'),
() => {
elementPlusTheme.changeTheme(configStore.getColorVal('elementUiPrimary'))
}
)
watch(
[
() => configStore.getColorVal('tableHeaderBackground'),
() => configStore.getColorVal('tableHeaderColor'),
() => configStore.getColorVal('tableCurrent')
],
() => {
updateTheme()
}
)
}
export default useSetTheme
import { onMounted, watch } from 'vue'
import { useElementPlusTheme } from 'use-element-plus-theme'
import { useConfig } from '@/stores/config'
const useSetTheme = () => {
const configStore = useConfig()
const elementPlusTheme = useElementPlusTheme(configStore.getColorVal('elementUiPrimary'))
const updateTheme = () => {
const root = document.documentElement
const tableHeaderBackground = configStore.getColorVal('tableHeaderBackground')
const tableHeaderColor = configStore.getColorVal('tableHeaderColor')
const tableCurrent = configStore.getColorVal('tableCurrent')
root.style.setProperty('--vxe-table-header-background-color', tableHeaderBackground)
root.style.setProperty('--vxe-table-header-font-color', tableHeaderColor)
root.style.setProperty('--vxe-table-row-current-background-color', tableCurrent)
root.style.setProperty('--vxe-table-row-hover-background-color', tableCurrent)
root.style.setProperty('--vxe-table-row-hover-current-background-color', tableCurrent)
root.style.setProperty('--vxe-table-row-hover-striped-background-color', tableCurrent)
root.style.setProperty('--vxe-ui-table-header-background-color', tableHeaderBackground)
root.style.setProperty('--vxe-ui-table-header-font-color', tableHeaderColor)
root.style.setProperty('--vxe-ui-table-row-current-background-color', tableCurrent)
root.style.setProperty('--vxe-ui-table-row-hover-background-color', tableCurrent)
root.style.setProperty('--vxe-ui-table-row-hover-current-background-color', tableCurrent)
root.style.setProperty('--vxe-ui-table-row-hover-striped-background-color', tableCurrent)
}
onMounted(updateTheme)
watch(
() => configStore.getColorVal('elementUiPrimary'),
() => {
elementPlusTheme.changeTheme(configStore.getColorVal('elementUiPrimary'))
}
)
watch(
[
() => configStore.getColorVal('tableHeaderBackground'),
() => configStore.getColorVal('tableHeaderColor'),
() => configStore.getColorVal('tableCurrent')
],
() => {
updateTheme()
}
)
}
export default useSetTheme

View File

@@ -46,6 +46,7 @@ export default class TableStore {
},
loading: true,
exportLoading: false,
customColumnInHeader: false,
column: [],
loadCallback: null,
resetCallback: null,

View File

@@ -40,3 +40,27 @@ export function setWaveCache(key: string, value: unknown): void {
if (oldest !== undefined) cache.delete(oldest)
}
}
export function removeWaveCache(key: string): void {
if (key) cache.delete(key)
}
/** 关闭波形页时清空全部缓存 */
export function clearWaveCache(): void {
cache.clear()
}
/** 移除当前事件相关的 shu/rms 缓存(一次值、二次值、开环等组合) */
export function removeWaveCacheByEvent(
wp: Record<string, any> | undefined,
boxoList: Record<string, any>
): void {
if (!wp) return
for (const type of ['shu', 'rms'] as const) {
for (const value of [1, 2]) {
for (const isOpen of [true, false]) {
removeWaveCache(buildWaveCacheKey(type, wp, value, isOpen, boxoList))
}
}
}
}

View File

@@ -1,10 +1,15 @@
<template>
<div class="default-main">
<div class="custom-table-header">
<!-- <div class="custom-table-header">
<div class="title">待审核用户</div>
<el-button :icon="Check" type="primary" @click="addRole" class="ml10">审核通过</el-button>
</div>
<Table ref="tableRef" />
</div> -->
<TableHeader :showReset="false" showCustomColumn ref="tableHeaderRef">
<template #operation>
<el-button :icon="Check" type="primary" @click="addRole" class="ml10">审核通过</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
</div>
</template>
<script setup lang="ts">
@@ -14,7 +19,7 @@ import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import { ElMessage } from 'element-plus'
import { checkUser } from '@/api/user-boot/user'
import TableHeader from '@/components/table/header/index.vue'
defineOptions({
name: 'auth/audit'
})
@@ -24,6 +29,14 @@ const tableStore = new TableStore({
url: '/user-boot/user/checkUserList',
column: [
{ width: '60', type: 'checkbox' },
{
field: 'index',
title: '序号',
width: '80',
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '名称', field: 'name' },
{ title: '登录名', field: 'loginName' },
{ title: '角色', field: 'roleName' },
@@ -33,7 +46,8 @@ const tableStore = new TableStore({
{ title: '类型', field: 'casualUserName' },
{ title: '状态', field: 'stateName' },
{
title: '操作', fixed: 'right',
title: '操作',
fixed: 'right',
width: '180',
render: 'buttons',
buttons: [

View File

@@ -1,22 +1,36 @@
<template>
<div class="default-main">
<TableHeader>
<TableHeader showCustomColumn>
<template v-slot:select>
<el-form-item label="用户状态">
<el-select v-model.trim="tableStore.table.params.searchState" placeholder="选择用户状态">
<el-option v-for="(item, index) in userState" :label="item.label" :key="index"
:value="item.value"></el-option>
<el-option
v-for="(item, index) in userState"
:label="item.label"
:key="index"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="用户类型:">
<el-select v-model.trim="tableStore.table.params.casualUser" placeholder="选择用户类型">
<el-option v-for="(item, index) in casualUser" :label="item.label" :key="index"
:value="item.value"></el-option>
<el-option
v-for="(item, index) in casualUser"
:label="item.label"
:key="index"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="关键字筛选:">
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="仅根据用户名/登录名" />
<el-input
maxlength="32"
show-word-limit
style="width: 240px"
v-model.trim="tableStore.table.params.searchValue"
clearable
placeholder="仅根据用户名/登录名"
/>
</el-form-item>
</template>
<template v-slot:operation>
@@ -48,6 +62,14 @@ const tableStore = new TableStore({
url: '/user-boot/user/list',
method: 'POST',
column: [
{
field: 'index',
title: '序号',
width: '80',
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '用户名称', field: 'name', minWidth: '130' },
{ title: '登录名', field: 'loginName', minWidth: '130' },
{ title: '角色', field: 'roleName', minWidth: '130' },
@@ -79,10 +101,11 @@ const tableStore = new TableStore({
}
},
{
title: '操作', fixed: 'right',
title: '操作',
fixed: 'right',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',

View File

@@ -1,26 +1,40 @@
<template>
<TableHeader datePicker ref="refheader" showExport>
<TableHeader datePicker ref="refheader" showCustomColumn showExport>
<template v-slot:select>
<!-- <el-form-item label="数据来源">
<el-cascader
v-model.trim="tableStore.table.params.cascader"
filterable
placeholder="请选择数据来源"
@change="sourceChange"
:options="deviceTreeOptions"
:show-all-levels="false"
:props="{ checkStrictly: true, value: 'id', label: 'name' }"
<el-form-item label="设备选取">
<el-tree-select
v-model="tableStore.table.params.cascader"
:data="deviceTree"
clearable
></el-cascader>
</el-form-item> -->
:props="treeProps"
filterable
:filter-node-method="filterNode"
check-strictly
default-expand-all
placeholder="请选择需要筛选的数据"
@node-click="sourceChange"
@clear="onTreeClear"
style="width: 100%"
></el-tree-select>
</el-form-item>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="请输入设备名称/告警代码" />
<el-input
maxlength="32"
show-word-limit
style="width: 240px"
v-model.trim="tableStore.table.params.searchValue"
clearable
placeholder="请输入告警代码"
/>
</el-form-item>
<el-form-item label="级别">
<el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable>
<el-option v-for="item in rankOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-option
v-for="item in rankOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</template>
@@ -35,25 +49,13 @@ 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 { createTreeFilterNode } from '@/components/tree/govern/treeFilterUtils'
const props = defineProps(['deviceTree'])
const refheader = ref()
const deviceTree = ref([])
const tabsList = ref([
{
label: '设备告警',
name: 3
},
{
label: '稳态越限告警',
name: 1
},
{
label: '暂态事件',
name: 0
}
])
const treeProps = {
value: 'id',
label: 'name',
children: 'children'
}
const rankOptions = ref([
{
value: '1',
@@ -66,7 +68,7 @@ const rankOptions = ref([
{
value: '3',
label: '3级'
},
}
// {
// value: '4',
// label: 'DEBUG'
@@ -100,7 +102,11 @@ const tableStore = new TableStore({
},
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{
title: '监测点名称', field: 'lineName', minWidth: 150, align: 'center', formatter: (row: any) => {
title: '监测点名称',
field: 'lineName',
minWidth: 150,
align: 'center',
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
@@ -109,7 +115,6 @@ const tableStore = new TableStore({
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 150 },
// { title: '监测点名称', field: 'lineName', align: 'center', minWidth: 120 },
{
title: '事件描述',
minWidth: 300,
@@ -169,23 +174,23 @@ const tableStore = new TableStore({
// }
// }
],
beforeSearchFun: () => { },
beforeSearchFun: () => {},
exportProcessingData: () => {
tableStore.table.allData = tableStore.table.allData.filter(item => {
item.level =
item.level == 1
? '1级'
: item.level == 2
? '2级'
: item.level == 3
? '3级'
: item.level == 4
? 'DEBUG'
: item.level == 5
? 'NORMAL'
: item.level == 6
? 'WARN'
: 'ERROR'
? '2级'
: item.level == 3
? '3级'
: item.level == 4
? 'DEBUG'
: item.level == 5
? 'NORMAL'
: item.level == 6
? 'WARN'
: 'ERROR'
return item
})
}
@@ -196,52 +201,41 @@ provide('tableStore', tableStore)
// "type": "",
// "userId": ""
tableStore.table.params.searchValue = ''
// tableStore.table.params.cascader = ''
// tableStore.table.params.level = ''
// tableStore.table.params.engineeringid = ''
// tableStore.table.params.projectId = ''
// tableStore.table.params.deviceId = ''
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
tableStore.table.params.lineId = ''
tableStore.table.params.cascader = ''
tableStore.table.params.type = 3
// tableStore.table.params.eventIds = []
// tableStore.table.params.status = ''
// tableStore.table.params.target = []
// tableStore.table.params.userId = ''
// tableStore.table.params.deviceTypeId = ''
// tableStore.table.params.deviceTypeName = ''
const deviceTreeOptions = ref<any>(props.deviceTree)
deviceTreeOptions.value.map((item: any, index: any) => {
if (item?.children.length == 0) {
deviceTreeOptions.value.splice(index, 1)
}
})
const sourceChange = (e: any) => {
tableStore.table.params.deviceTypeId = ''
tableStore.table.params.level = ''
const filterNode = createTreeFilterNode()
const onTreeClear = () => {
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
if (e) {
let name = deviceTreeOptions.value.filter((item: any) => {
return item.id == e[0]
})[0].name
tableStore.table.params.deviceTypeName = name
if (name == '便携式设备') {
tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.deviceId = e[1] || ''
} else {
tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.engineeringid = e[1] || ''
tableStore.table.params.projectId = e[2] || ''
tableStore.table.params.deviceId = e[3] || ''
}
}
tableStore.table.params.lineId = ''
}
const sourceChange = (e: any) => {
onTreeClear()
if (e.level == 0) {
tableStore.table.params.engineeringid = e.id
} else if (e.level == 1) {
tableStore.table.params.projectId = e.id
} else if (e.level == 2) {
tableStore.table.params.deviceId = e.id
} else if (e.level == 3) {
tableStore.table.params.lineId = e.id
}
}
onMounted(() => {
tableStore.index()
})
setTimeout(() => {
// tableStore.table.height = mainHeight(200).height as any
}, 0)
const addMenu = () => { }
const addMenu = () => {}
</script>
<style></style>

View File

@@ -1,5 +1,5 @@
<template>
<TableHeader datePicker ref="refheader" showExport>
<TableHeader datePicker ref="refheader" showCustomColumn showExport>
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit
@@ -20,7 +20,7 @@
</template>
</TableHeader>
<!-- <div style="height: 300px;"> -->
<Table ref="tableRef" :isGroup="true" />
<Table ref="tableRef" :isGroup="true" />
<!-- </div> -->
</template>
<script setup lang="ts">
@@ -76,10 +76,10 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '发生时刻', field: 'startTime', align: 'center', width: 180, sortable: true },
{ title: '服务器名称', field: 'lineId', align: 'center', width: 150 },
{ title: 'IP', field: 'wavePath', align: 'center', width: 150 },
{ title: '进程号', field: 'clDid', align: 'center', width: 70 },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{ title: '服务器名称', field: 'lineId', align: 'center', minWidth: 150 },
{ title: 'IP', field: 'wavePath', align: 'center', minWidth: 150 },
{ title: '进程号', field: 'clDid', align: 'center', minWidth: 70 },
{
title: '事件描述',

View File

@@ -1,15 +1,32 @@
<template>
<TableHeader datePicker ref="refheader" showExport>
<TableHeader datePicker ref="refheader" showCustomColumn showExport>
<template v-slot:select>
<!-- <el-form-item label="数据来源">
<el-cascader v-model.trim="tableStore.table.params.cascader" filterable placeholder="请选择数据来源"
@change="sourceChange" :options="deviceTreeOptions" :show-all-levels="false"
:props="{ checkStrictly: true, value: 'id', label: 'name' }" clearable></el-cascader>
<el-form-item label="设备选取">
<el-tree-select
v-model="tableStore.table.params.cascader"
:data="deviceTree"
clearable
:props="treeProps"
filterable
:filter-node-method="filterNode"
check-strictly
default-expand-all
placeholder="请选择需要筛选的数据"
@node-click="sourceChange"
@clear="onTreeClear"
style="width: 100%"
></el-tree-select>
</el-form-item>
<!-- <el-form-item label="关键字筛选">
<el-input
maxlength="32"
show-word-limit
style="width: 240px"
v-model.trim="tableStore.table.params.searchValue"
clearable
placeholder="请输入监测点名称"
/>
</el-form-item> -->
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="请输入监测点名称" />
</el-form-item>
<!-- <el-form-item label="级别">
<el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable>
<el-option
@@ -32,39 +49,14 @@ 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 { createTreeFilterNode } from '@/components/tree/govern/treeFilterUtils'
const props = defineProps(['deviceTree'])
const refheader = ref()
const deviceTree = ref([])
const tabsList = ref([
{
label: '设备告警',
name: 3
},
{
label: '稳态越限告警',
name: 1
},
{
label: '暂态事件',
name: 0
}
])
const rankOptions = ref([
{
value: '1',
label: '1级'
},
{
value: '2',
label: '2级'
},
{
value: '3',
label: '3级'
}
])
const treeProps = {
value: 'id',
label: 'name',
children: 'children'
}
const tableStore = new TableStore({
url: '/cs-harmonic-boot/eventUser/queryEventpageWeb',
@@ -79,18 +71,23 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '发生时刻', field: 'startTime', align: 'center', sortable: true, minWidth: 180, },
{ title: '监测点名称', field: 'lineName', align: 'center', minWidth: 150,formatter: (row: any) => {
{ title: '发生时刻', field: 'startTime', align: 'center', sortable: true, minWidth: 180 },
{
title: '监测点名称',
field: 'lineName',
align: 'center',
minWidth: 150,
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
} },
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 150, },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 150, },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 150, },
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 150 },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 150 },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 150 },
{ title: '事件描述', field: 'showName', align: 'center', minWidth: 250, }
{ title: '事件描述', field: 'showName', align: 'center', minWidth: 250 }
],
beforeSearchFun: () => { }
beforeSearchFun: () => {}
})
provide('tableStore', tableStore)
@@ -98,44 +95,32 @@ provide('tableStore', tableStore)
// "type": "",
// "userId": ""
tableStore.table.params.searchValue = ''
// tableStore.table.params.engineeringid = ''
// tableStore.table.params.deviceTypeId = ''
// tableStore.table.params.projectId = ''
// tableStore.table.params.deviceId = ''
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
tableStore.table.params.lineId = ''
tableStore.table.params.cascader = ''
tableStore.table.params.type = 1
// tableStore.table.params.eventIds = []
// tableStore.table.params.status = ''
// tableStore.table.params.target = []
// tableStore.table.params.userId = ''
// tableStore.table.params.cascader = ''
// tableStore.table.params.deviceTypeName = ''
// tableStore.table.params.level=''
const deviceTreeOptions = ref<any>(props.deviceTree)
deviceTreeOptions.value.map((item: any, index: any) => {
if (item?.children.length == 0) {
deviceTreeOptions.value.splice(index, 1)
}
})
const sourceChange = (e: any) => {
tableStore.table.params.deviceTypeId = ''
const filterNode = createTreeFilterNode()
const onTreeClear = () => {
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
if (e) {
let name = deviceTreeOptions.value.filter((item: any) => {
return item.id == e[0]
})[0].name
tableStore.table.params.deviceTypeName = name
if (name == '便携式设备') {
tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.deviceId = e[1] || ''
} else {
tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.engineeringid = e[1] || ''
tableStore.table.params.projectId = e[2] || ''
tableStore.table.params.deviceId = e[3] || ''
}
tableStore.table.params.lineId = ''
}
const sourceChange = (e: any) => {
onTreeClear()
if (e.level == 0) {
tableStore.table.params.engineeringid = e.id
} else if (e.level == 1) {
tableStore.table.params.projectId = e.id
} else if (e.level == 2) {
tableStore.table.params.deviceId = e.id
} else if (e.level == 3) {
tableStore.table.params.lineId = e.id
}
}
onMounted(() => {
@@ -144,6 +129,6 @@ onMounted(() => {
setTimeout(() => {
tableStore.table.height = mainHeight(200).height as any
}, 0)
const addMenu = () => { }
const addMenu = () => {}
</script>
<style></style>

View File

@@ -1,17 +1,33 @@
<template>
<div ref="refheader" v-show="!isWaveCharts" style="width: 100%">
<TableHeader datePicker showExport @onResetForm="onResetForm">
<TableHeader datePicker showExport showCustomColumn @onResetForm="onResetForm">
<template v-slot:select>
<!-- <el-form-item label="数据来源">
<el-cascader placeholder="请选择数据来源" @change="sourceChange" filterable
v-model.trim="tableStore.table.params.cascader" :options="deviceTreeOptions"
:show-all-levels="false" :props="{ checkStrictly: true, value: 'id', label: 'name' }"
clearable></el-cascader>
</el-form-item> -->
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="请输入监测点名称" />
<el-form-item label="设备选取">
<el-tree-select
v-model="tableStore.table.params.cascader"
:data="deviceTree"
clearable
:props="treeProps"
filterable
:filter-node-method="filterNode"
check-strictly
default-expand-all
placeholder="请选择需要筛选的数据"
@node-click="sourceChange"
@clear="onTreeClear"
style="width: 100%"
></el-tree-select>
</el-form-item>
<!-- <el-form-item label="关键字筛选">
<el-input
maxlength="32"
show-word-limit
style="width: 240px"
v-model.trim="tableStore.table.params.searchValue"
clearable
placeholder="请输入监测点名称"
/>
</el-form-item> -->
<!-- <el-form-item>
<el-button type="primary" plain @click="openFilterDialog">事件筛选</el-button>
</el-form-item> -->
@@ -22,16 +38,24 @@
</template>
</TableHeader>
<MultiCondition v-model:visible="filterVisible" :params="tableStore.table.params" ref="multiConditionRef"
@confirm="onFilterConfirm" />
<MultiCondition
v-model:visible="filterVisible"
:params="tableStore.table.params"
ref="multiConditionRef"
@confirm="onFilterConfirm"
/>
<Table></Table>
<!-- 补召日志 -->
<analysisList ref="analysisListRef"></analysisList>
</div>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
<waveFormAnalysis
v-loading="loading"
v-if="isWaveCharts"
ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false"
:wp="wp"
/>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
@@ -48,6 +72,7 @@ import { buildWaveExportFileName, getExportSubjectFromRow } from '@/utils/echart
import { useDictData } from '@/stores/dictData'
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
import analysisList from '@/views/govern/device/control/analysisList/index.vue'
import { createTreeFilterNode } from '@/components/tree/govern/treeFilterUtils'
const props = defineProps(['deviceTree'])
const emit = defineEmits(['statistics'])
@@ -65,7 +90,11 @@ const EventTypeList: any = dictData.getBasicData('Event_Type')
const filterVisible = ref(false)
const multiConditionRef = ref<InstanceType<typeof MultiCondition>>()
const treeProps = {
value: 'id',
label: 'name',
children: 'children'
}
const tableStore = new TableStore({
url: '/cs-harmonic-boot/eventUser/queryEventpageWeb',
method: 'POST',
@@ -81,34 +110,50 @@ const tableStore = new TableStore({
},
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{ title: '暂降幅值(%)', minWidth: 120, field: 'evtParamVVaDepth', align: 'center', sortable: true, },
{ title: '暂降幅值(%)', minWidth: 120, field: 'evtParamVVaDepth', align: 'center', sortable: true },
{ title: '持续时间(s)', field: 'evtParamTm', minWidth: 110, align: 'center', sortable: true },
{
title: '严重度', field: 'severity', minWidth: 80, align: 'center', sortable: true, formatter: (row: any) => {
title: '严重度',
field: 'severity',
minWidth: 80,
align: 'center',
sortable: true,
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{ title: '相别', field: 'evtParamPhase', minWidth: 80, align: 'center' },
{ title: '触发类型', field: 'showName', minWidth: 100, align: 'center' },
{
title: '暂降原因', field: 'advanceReason', minWidth: 100, align: 'center', formatter: (row: any) => {
title: '暂降原因',
field: 'advanceReason',
minWidth: 100,
align: 'center',
formatter: (row: any) => {
return ReasonList.find((item: any) => item.id == row.cellValue)?.name || '其他'
}
},
{
title: '暂降类型', field: 'advanceType', minWidth: 100, align: 'center', formatter: (row: any) => {
title: '暂降类型',
field: 'advanceType',
minWidth: 100,
align: 'center',
formatter: (row: any) => {
return EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '其他'
}
},
{ title: '监测点名称', field: 'lineName', minWidth: 150, align: 'center' },
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true, },
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true },
{ title: '设备名称', field: 'equipmentName', minWidth: 150, align: 'center' },
{ title: '项目名称', field: 'projectName', minWidth: 150, align: 'center' },
{ title: '工程名称', field: 'engineeringName', minWidth: 150, align: 'center' },
{
title: '发生位置', field: 'sagSource', minWidth: 120, align: 'center', formatter: (row: any) => {
title: '发生位置',
field: 'sagSource',
minWidth: 120,
align: 'center',
formatter: (row: any) => {
return row.cellValue == 1 ? '上游' : row.cellValue == 2 ? '下游' : '暂无'
}
},
@@ -145,7 +190,7 @@ const tableStore = new TableStore({
persistTime: row.evtParamTm,
featureAmplitude:
row.evtParamVVaDepth != '-' ? (row.evtParamVVaDepth - 0) / 100 : null,
systemType: 'YPT',
systemType: 'YPT'
}
wp.value = res.data
}
@@ -161,7 +206,6 @@ const tableStore = new TableStore({
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
// waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(200, 190)
})
}
},
{
@@ -177,20 +221,22 @@ const tableStore = new TableStore({
click: row => {
row.loading2 = true
ElMessage.info('下载中......')
getFileZip({ eventId: row.id }).then(res => {
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 = buildWaveExportFileName(getExportSubjectFromRow(row))
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
row.loading2 = false
}).catch(() => {
row.loading2 = false
})
getFileZip({ eventId: row.id })
.then(res => {
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 = buildWaveExportFileName(getExportSubjectFromRow(row))
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
row.loading2 = false
})
.catch(() => {
row.loading2 = false
})
}
},
{
@@ -202,8 +248,7 @@ const tableStore = new TableStore({
disabled: row => {
let code = DeviceType.value.filter((item: any) => item.id == row.devType)[0]?.code
return !((code == 'Direct_Connected_Device' || code == 'Gateway') && row.wavePath == null)
},
}
},
{
name: 'edit',
@@ -227,22 +272,21 @@ const tableStore = new TableStore({
deviceData: row,
deviceId: row.deviceId
})
} else if (code == 'DEV_CLD') {
row.loading2 = true
// 监测设备
getFileByEventId(row.id).then(res => {
ElMessage.success(res.message)
tableStore.index()
row.loading2 = false
}).catch(() => {
row.loading2 = false
})
getFileByEventId(row.id)
.then(res => {
ElMessage.success(res.message)
tableStore.index()
row.loading2 = false
})
.catch(() => {
row.loading2 = false
})
}
}
},
}
]
}
],
@@ -267,17 +311,14 @@ provide('tableStore', tableStore)
// "type": "",
// "userId": ""
tableStore.table.params.searchValue = ''
// tableStore.table.params.engineeringid = ''
// tableStore.table.params.projectId = ''
// tableStore.table.params.deviceTypeId = ''
// tableStore.table.params.deviceId = ''
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
tableStore.table.params.lineId = ''
tableStore.table.params.cascader = ''
tableStore.table.params.type = 0
// tableStore.table.params.eventIds = []
// tableStore.table.params.status = ''
// tableStore.table.params.target = []
// tableStore.table.params.userId = ''
// tableStore.table.params.cascader = ''
// tableStore.table.params.deviceTypeName = ''
Object.assign(tableStore.table.params, {
featureAmplitudeMin: undefined,
featureAmplitudeMax: undefined,
@@ -292,55 +333,27 @@ Object.assign(tableStore.table.params, {
const openFilterDialog = () => {
filterVisible.value = true
}
const deviceTreeOptions: any = ref<any>(props.deviceTree)
deviceTreeOptions.value.map((item: any, index: any) => {
if (item?.children.length == 0) {
deviceTreeOptions.value.splice(index, 1)
}
})
const sourceChange = (e: any) => {
tableStore.table.params.deviceTypeId = ''
const onTreeClear = () => {
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
if (e) {
let name = deviceTreeOptions.value.filter((item: any) => {
return item.id == e[0]
})[0].name
tableStore.table.params.deviceTypeName = name
if (name == '便携式设备') {
tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.deviceId = e[1] || ''
} else {
tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.engineeringid = e[1] || ''
tableStore.table.params.projectId = e[2] || ''
tableStore.table.params.deviceId = e[3] || ''
}
}
// tableStore.table.params.engineeringid = e[1] || ''
// tableStore.table.params.projectId = e[2] || ''
// const zlIndex = deviceTreeOptions.value.findIndex((item: any) => {
// return item.name == '治理设备'
// })
// const bxsIndex = deviceTreeOptions.value.findIndex((item: any) => {
// return item.name == '便携式设备'
// })
// console.log("🚀 ~ zlIndex ~ zlIndex:", zlIndex,bxsIndex)
// //便携式设备特殊处理
// if (bxsIndex != -1 && deviceTreeOptions.value[bxsIndex].id == e[0] && e.length == 2) {
// tableStore.table.params.deviceId = e[1]
// }
// //治理设备
// if (zlIndex != -1 && deviceTreeOptions.value[zlIndex].id == e[0]) {
// tableStore.table.params.deviceId = e[2] || ''
// }
tableStore.table.params.lineId = ''
}
const sourceChange = (e: any) => {
onTreeClear()
if (e.level == 0) {
tableStore.table.params.engineeringid = e.id
} else if (e.level == 1) {
tableStore.table.params.projectId = e.id
} else if (e.level == 2) {
tableStore.table.params.deviceId = e.id
} else if (e.level == 3) {
tableStore.table.params.lineId = e.id
}
}
const filterNode = createTreeFilterNode()
const onFilterConfirm = () => {
tableStore.onTableAction('search', {})
}
@@ -374,6 +387,6 @@ setTimeout(() => {
tableStore.table.height = mainHeight(200).height as any
}, 0)
const addMenu = () => { }
const addMenu = () => {}
</script>
<style scoped lang="scss"></style>

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader select :showReset="false" ref="TableHeaderRef">
<TableHeader select :showReset="false" showCustomColumn ref="TableHeaderRef">
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template>

View File

@@ -38,6 +38,7 @@ import TableHeader from '@/components/table/header/index.vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getTime } from '@/utils/formatTime'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { color1 } from '@/components/echarts/color'
const dictData = useDictData()

View File

@@ -5,7 +5,6 @@
<Transient
v-if="!showEventStatistics"
:deviceTree="deviceTree"
:key="key"
@statistics="showEventStatistics = true"
/>
<eventStatistics v-else @back="showEventStatistics = false" />
@@ -14,17 +13,14 @@
</el-tab-pane> -->
<el-tab-pane label="稳态越限告警" name="3">
<Steady v-if="activeName == '3'" :deviceTree="deviceTree" :key="key" />
<Steady :deviceTree="deviceTree" />
</el-tab-pane>
<el-tab-pane label="设备告警" name="1">
<Device v-if="activeName == '1'" :deviceTree="deviceTree" :key="key" />
<Device :deviceTree="deviceTree" />
</el-tab-pane>
<el-tab-pane label="前置告警" name="2">
<Front v-if="activeName == '2'" :deviceTree="deviceTree" :key="key" />
<Front />
</el-tab-pane>
</el-tabs>
</div>
</template>
@@ -35,7 +31,7 @@ import Transient from './Transient.vue'
import Device from './Device.vue'
import Front from './Front.vue'
import eventStatistics from './eventStatistics.vue'
import { getDeviceTree } from '@/api/cs-device-boot/csLedger'
import { getLineTree } from '@/api/cs-device-boot/csLedger'
defineOptions({
name: 'govern/alarm/index'
})
@@ -50,26 +46,13 @@ watch(activeName, val => {
showEventStatistics.value = false
}
})
// getDeviceTree().then(res => {
// res.data.forEach((item: any) => {
// item.value = item.id
// item.label = item.name
// item.children.forEach((child: any) => {
// child.value = child.id
// child.label = child.name
// child.children.forEach((grand: any) => {
// grand.value = grand.id
// grand.label = grand.name
// delete grand.children
// })
// })
// })
// deviceTree.value = res.data
// key.value += 1
// activeName.value = '4'
// })
onMounted(() => { })
getLineTree({ type: 'engineering' }).then(res => {
deviceTree.value = res.data
const addMenu = () => { }
activeName.value = '4'
})
onMounted(() => {})
const addMenu = () => {}
</script>
<style></style>

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader ref="TableHeaderRef">
<TableHeader showCustomColumn ref="TableHeaderRef">
<template #select>
<el-form-item label="数据来源">
<el-select v-model="tableStore.table.params.dataSource" clearable placeholder="请选择数据来源">
@@ -69,41 +69,41 @@ const tableStore: any = new TableStore({
{ field: 'influxdbTableName', title: '表名', minWidth: 150 },
{ field: 'influxdbColumnName', title: '列属性', minWidth: 150 },
{
field: 'harmStart', title: '谐波次数', width: 90,
field: 'harmStart', title: '谐波次数', minWidth: 90,
formatter: (row: any) => {
return row.cellValue == null ? '/' : row.cellValue + '-' + row.row.harmEnd
}
},
{
field: 'phaseType', title: '相别', width: 100, formatter: (row: any) => {
field: 'phaseType', title: '相别', minWidth: 100, formatter: (row: any) => {
return row.cellValue == 'T' ? '/' : row.cellValue
}
},
{
field: 'unit', title: '单位', width: 80,
field: 'unit', title: '单位', minWidth: 80,
formatter: (row: any) => {
return row.cellValue || '/'
}
},
{ field: 'minValue', title: '指标下限', width: 100 },
{ field: 'maxValue', title: '指标上限', width: 100 },
{ field: 'minValue', title: '指标下限', minWidth: 100 },
{ field: 'maxValue', title: '指标上限', minWidth: 100 },
{
field: 'isVoltage',
title: '电压等级参与',
width: 110,
minWidth: 110,
formatter: (row: any) => yesNo(row.cellValue)
},
{
field: 'ctAttendFlag',
title: 'CT变比参与',
width: 100,
minWidth: 100,
formatter: (row: any) => yesNo(row.cellValue)
},
{ field: 'dataSource', title: '数据来源', width: 100 },
{ field: 'belongingSystem', title: '所属系统', width: 100 },
{ field: 'dataSource', title: '数据来源', minWidth: 100 },
{ field: 'belongingSystem', title: '所属系统', minWidth: 100 },
@@ -119,7 +119,7 @@ const tableStore: any = new TableStore({
formatter: (row: any) => {
return row.cellValue || '/'
}
}, { field: 'sort', title: '排序', width: 70 },
}, { field: 'sort', title: '排序', minWidth: 70 },
{
title: '操作',

View File

@@ -5,7 +5,7 @@
<APFTree @node-click="nodeClick" :height="60" :type="'dvr'" @init="nodeClick"
@deviceTypeChange="deviceTypeChange"></APFTree>
<div class="analyze-dvr-right" v-if="tableStore.table.params.deviceId">
<TableHeader datePicker showExport @onResetForm="onResetForm">
<TableHeader datePicker showExport showCustomColumn @onResetForm="onResetForm">
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"

View File

@@ -2,7 +2,7 @@
<template>
<el-dialog modal-class="analysisList" v-model.trim="dialogVisible" title="补召日志" width="70%" draggable
@closed="close">
<TableHeader date-picker :showReset="false">
<TableHeader date-picker showCustomColumn :showReset="false">
<template #operation>
<el-button type="primary" icon="el-icon-Connection" @click="handleImport">
离线补召
@@ -63,7 +63,7 @@ const tableStore: any = new TableStore({
{
title: '解析状态',
field: 'status',
width: 100,
minWidth: 100,
render: 'tag',
custom: {
0: 'warning',

View File

@@ -99,7 +99,6 @@ const echartList: any = ref({})
const dataType = ref([0])
const key = ref(0)
import * as echarts from 'echarts' // 全引入
import { max } from 'lodash'
const echartsData: any = ref({
title: {
show: false
@@ -161,7 +160,7 @@ const echartsData: any = ref({
},
grid: {
top: '80px',
right: '50px',
right: '50px'
},
yAxis: [{}],
@@ -190,7 +189,7 @@ const setData = (data: any) => {
fontSize: 16
}
},
formatter: function (params) {
formatter: function (params: any) {
// console.log("🚀 ~ data.forEach ~ params:", params)
let tip = ''
for (let i = 0; i < params.length; i++) {
@@ -372,15 +371,19 @@ const changeDataType = () => {
echartsData.value.yAxis = [{}]
echartsData.value.options.series = []
const currentTab = list.value[activeTab.value] || {}
const loadList = currentTab.loadList || []
const modOutList = currentTab.modOutList || []
const temperatureList = currentTab.temperatureList || []
let flag = dataType.value.includes(0) || dataType.value.includes(1)
if (flag) {
let data1 = dataType.value.includes(0)
? list.value[activeTab.value]?.loadList.map(k => (k.data == 3.14159 ? 0 : k.data))
: [0]
? loadList.map((k: any) => (k.data == 3.14159 ? null : k.data))
: []
let data2 = dataType.value.includes(1)
? list.value[activeTab.value]?.modOutList.map(k => (k.data == 3.14159 ? 0 : k.data))
: [0]
let [modOuMin, modOuMax] = yMethod([...data1||[0], ...data2||[0]])
? modOutList.map((k: any) => (k.data == 3.14159 ? null : k.data))
: []
let [modOuMin, modOuMax] = yMethod([...data1, ...data2])
echartsData.value.yAxis[0] = {
name: 'A',
@@ -395,7 +398,7 @@ const changeDataType = () => {
{
name: 'A相负载电流',
type: 'line',
data: list.value[activeTab.value]?.loadList
data: loadList
.filter((k: any) => k.phasicType == 'A')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[0].type]),
smooth: true, //让线变得平滑
@@ -407,7 +410,7 @@ const changeDataType = () => {
{
name: 'B相负载电流',
type: 'line',
data: list.value[activeTab.value]?.loadList
data: loadList
.filter((k: any) => k.phasicType == 'B')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[0].type]),
smooth: true, //让线变得平滑
@@ -419,7 +422,7 @@ const changeDataType = () => {
{
name: 'C相负载电流',
type: 'line',
data: list.value[activeTab.value]?.loadList
data: loadList
.filter((k: any) => k.phasicType == 'C')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[0].type]),
smooth: true, //让线变得平滑
@@ -435,7 +438,7 @@ const changeDataType = () => {
{
name: 'A相输入电流',
type: 'line',
data: list.value[activeTab.value].modOutList
data: modOutList
.filter((k: any) => k.phasicType == 'A')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[1].type]),
smooth: true, //让线变得平滑
@@ -447,7 +450,7 @@ const changeDataType = () => {
{
name: 'B相输入电流',
type: 'line',
data: list.value[activeTab.value].modOutList
data: modOutList
.filter((k: any) => k.phasicType == 'B')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[1].type]),
smooth: true, //让线变得平滑
@@ -459,7 +462,7 @@ const changeDataType = () => {
{
name: 'C相输入电流',
type: 'line',
data: list.value[activeTab.value].modOutList
data: modOutList
.filter((k: any) => k.phasicType == 'C')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[1].type]),
smooth: true, //让线变得平滑
@@ -473,7 +476,7 @@ const changeDataType = () => {
}
if (dataType.value.includes(2)) {
let [temperatureMin, temperatureMax] = yMethod(
list.value[activeTab.value].temperatureList.map(k => (k.data == 3.14159 ? 0 : k.data))
temperatureList.map((k: any) => (k.data == 3.14159 ? 0 : k.data))
)
echartsData.value.yAxis[flag ? 1 : 0] = {
name: '℃',
@@ -481,12 +484,16 @@ const changeDataType = () => {
splitNumber: 5,
max: temperatureMax,
min: temperatureMin,
minInterval: 1
minInterval: 1,
splitLine: {
show: false
}
}
echartsData.value.options.series.push({
name: '温度',
type: 'line',
data: list.value[activeTab.value].temperatureList.map((k: any) => [
data: temperatureList.map((k: any) => [
k.time,
k.data == 3.14159 ? null : k.data,
'℃',
@@ -501,7 +508,7 @@ const changeDataType = () => {
}
key.value += 1
}
function renderItem(params, api) {
function renderItem(params: any, api: any) {
var categoryIndex = api.value(0)
var start = api.coord([api.value(1), categoryIndex])
var end = api.coord([api.value(2), categoryIndex])
@@ -531,7 +538,7 @@ function renderItem(params, api) {
)
}
// 三角形标记渲染函数
function renderMarker(params, api) {
function renderMarker(params: any, api: any) {
var point = api.coord([api.value(0), 0])
var symbolSize = 8
var offsetY = 40

View File

@@ -1,32 +1,78 @@
<template>
<div class="near-realtime-data">
<div class="view_bot">
<template v-for="(section, sectionIndex) in tableSections" :key="sectionIndex">
<vxe-table class="near-realtime-table" border height="" width="100%" :data="[section.row]"
:column-config="tableColumnConfig" :tooltip-config="tableTooltipConfig">
<vxe-table
class="near-realtime-table"
border
height=""
width="100%"
:data="[section.row]"
v-bind="defaultAttribute"
:column-config="tableColumnConfig"
:tooltip-config="tableTooltipConfig"
>
<template v-for="(item, colIndex) in section.columns" :key="colIndex">
<vxe-colgroup v-if="item.type === 'abc'" align="center" :title="getPrimaryTitle(item.data)"
:width="getMetricWidth(section)">
<vxe-column align="center" :field="`v${colIndex}A`" :title="item.data.phaseLabels![0]"
:width="getPhaseWidth(section)" :formatter="cellFormatter"></vxe-column>
<vxe-column align="center" :field="`v${colIndex}B`" :title="item.data.phaseLabels![1]"
:width="getPhaseWidth(section)" :formatter="cellFormatter"></vxe-column>
<vxe-column align="center" :field="`v${colIndex}C`" :title="item.data.phaseLabels![2]"
:width="getPhaseWidth(section)" :formatter="cellFormatter"></vxe-column>
<vxe-colgroup
v-if="item.type === 'abc'"
align="center"
:title="getPrimaryTitle(item.data)"
:width="getMetricWidth(section)"
>
<vxe-column
align="center"
:field="`v${colIndex}A`"
:title="item.data.phaseLabels![0]"
:width="getPhaseWidth(section)"
:formatter="cellFormatter"
></vxe-column>
<vxe-column
align="center"
:field="`v${colIndex}B`"
:title="item.data.phaseLabels![1]"
:width="getPhaseWidth(section)"
:formatter="cellFormatter"
></vxe-column>
<vxe-column
align="center"
:field="`v${colIndex}C`"
:title="item.data.phaseLabels![2]"
:width="getPhaseWidth(section)"
:formatter="cellFormatter"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup v-else-if="item.type === 't-multi'" align="center"
:title="getPrimaryTitle(item.data)" :width="getMetricWidth(section)">
<vxe-column v-for="(sub, subIndex) in item.data.subItems" :key="subIndex" align="center"
:field="`t${colIndex}_${subIndex}`" :title="sub.subTitle"
<vxe-colgroup
v-else-if="item.type === 't-multi'"
align="center"
:title="getPrimaryTitle(item.data)"
:width="getMetricWidth(section)"
>
<vxe-column
v-for="(sub, subIndex) in item.data.subItems"
:key="subIndex"
align="center"
:field="`t${colIndex}_${subIndex}`"
:title="sub.subTitle"
:width="getSubColWidth(section, item.data.subItems!.length)"
:formatter="cellFormatter"></vxe-column>
:formatter="cellFormatter"
></vxe-column>
</vxe-colgroup>
<vxe-column v-else align="center" :field="`s${colIndex}`" :title="getScalarTitle(item.data)"
:width="getMetricWidth(section)" show-overflow :formatter="cellFormatter"></vxe-column>
<vxe-column
v-else
align="center"
:field="`s${colIndex}`"
:title="getScalarTitle(item.data)"
:width="getMetricWidth(section)"
show-overflow
:formatter="cellFormatter"
></vxe-column>
</template>
<vxe-column v-for="emptyIndex in section.emptySlotCount" :key="`empty-${emptyIndex}`" align="center"
:width="getMetricWidth(section)"></vxe-column>
<vxe-column
v-for="emptyIndex in section.emptySlotCount"
:key="`empty-${emptyIndex}`"
align="center"
:width="getMetricWidth(section)"
></vxe-column>
</vxe-table>
<div v-if="sectionIndex < tableSections.length - 1" class="table-gap"></div>
</template>
@@ -38,6 +84,7 @@
<script setup lang="ts">
import { mainHeight } from '@/utils/layout'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ref } from 'vue'
const ROW_WITH_GROUP = 4
@@ -97,7 +144,7 @@ interface NameGroup {
const PHASE_GROUPS = [
{ keys: ['A', 'B', 'C'], labels: ['A相', 'B相', 'C相'] as [string, string, string] },
{ keys: ['AB', 'BC', 'CA'], labels: ['AB相', 'BC相', 'CA相'] as [string, string, string] },
{ keys: ['AB', 'BC', 'CA'], labels: ['AB相', 'BC相', 'CA相'] as [string, string, string] }
]
const height = mainHeight(345)
@@ -110,8 +157,7 @@ const getMetricWidth = (section: TableSection) => `${100 / section.slotsPerRow}%
const getPhaseWidth = (section: TableSection) => `${100 / section.slotsPerRow / 3}%`
const getSubColWidth = (section: TableSection, subCount: number) =>
`${100 / section.slotsPerRow / subCount}%`
const getSubColWidth = (section: TableSection, subCount: number) => `${100 / section.slotsPerRow / subCount}%`
const formatCellValue = (value: unknown): string | number => {
if (value == null || value === 3.14159) return '/'
@@ -174,7 +220,7 @@ const buildAbcMetric = (name: string, items: RawMetricItem[]): DisplayMetric =>
valueA: phaseMap[keys[0]],
valueB: phaseMap[keys[1]],
valueC: phaseMap[keys[2]],
phaseLabels: labels,
phaseLabels: labels
}
}
}
@@ -187,7 +233,7 @@ const buildAbcMetric = (name: string, items: RawMetricItem[]): DisplayMetric =>
valueA: phaseMap.A ?? phaseMap.AB,
valueB: phaseMap.B ?? phaseMap.BC,
valueC: phaseMap.C ?? phaseMap.CA,
phaseLabels: phaseMap.AB != null ? ['AB相', 'BC相', 'CA相'] : ['A相', 'B相', 'C相'],
phaseLabels: phaseMap.AB != null ? ['AB相', 'BC相', 'CA相'] : ['A相', 'B相', 'C相']
}
}
@@ -200,7 +246,7 @@ const buildTMetric = (name: string, items: RawMetricItem[]): DisplayMetric => {
otherName: items[0].otherName || name,
unit: items[0].unit ?? null,
type: 'scalar',
valueM: items[0].data,
valueM: items[0].data
}
}
@@ -212,12 +258,9 @@ const buildTMetric = (name: string, items: RawMetricItem[]): DisplayMetric => {
unit: sharedUnit,
type: 't-multi',
subItems: items.map(item => ({
subTitle: buildTitle(
extractSubTitle(item.otherName || item.name || ''),
item.unit
),
value: item.data,
})),
subTitle: buildTitle(extractSubTitle(item.otherName || item.name || ''), item.unit),
value: item.data
}))
}
}
@@ -245,7 +288,7 @@ const normalizeOldItem = (item: RawMetricItem): DisplayMetric => {
valueA: item.valueA,
valueB: item.valueB,
valueC: item.valueC,
phaseLabels: ['A相', 'B相', 'C相'],
phaseLabels: ['A相', 'B相', 'C相']
}
}
@@ -254,7 +297,7 @@ const normalizeOldItem = (item: RawMetricItem): DisplayMetric => {
otherName,
unit: item.unit ?? null,
type: 'scalar',
valueM: item.valueM,
valueM: item.valueM
}
}
@@ -268,7 +311,7 @@ const normalizeMetrics = (data: RawMetricItem[]): DisplayMetric[] => {
const toMetricItem = (data: DisplayMetric): MetricItem => ({
type: data.type,
data,
data
})
const buildRow = (columns: MetricItem[]) => {
@@ -312,7 +355,7 @@ const buildTableSections = (metrics: DisplayMetric[]) => {
columns,
row: buildRow(columns),
slotsPerRow,
emptySlotCount: Math.max(0, slotsPerRow - columns.length),
emptySlotCount: Math.max(0, slotsPerRow - columns.length)
})
}
@@ -346,52 +389,5 @@ defineExpose({ setData })
height: 20px;
}
:deep(.view_bot) {
.near-realtime-table {
width: 100%;
}
.near-realtime-table .vxe-table--render-wrapper,
.near-realtime-table .vxe-table--main-wrapper,
.near-realtime-table .vxe-table--header-wrapper,
.near-realtime-table .vxe-table--body-wrapper,
.near-realtime-table .vxe-table--layout-wrapper {
width: 100% !important;
}
.near-realtime-table table {
width: 100% !important;
table-layout: fixed;
}
.near-realtime-table .vxe-header--column .vxe-cell,
.near-realtime-table .vxe-body--column .vxe-cell {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 22px !important;
}
.vxe-table--render-default .vxe-body--column:not(.col--ellipsis),
.vxe-table--render-default .vxe-footer--column:not(.col--ellipsis),
.vxe-table--render-default .vxe-header--column:not(.col--ellipsis) {
padding: 5px !important;
}
.vxe-table--body-wrapper {
min-height: 32px !important;
}
.vxe-body--row {
height: 32px !important;
}
.vxe-table--render-default {
font-size: 13px !important;
}
}
:deep(.vxe-table--render-default .vxe-body--column.col--ellipsis, .vxe-table--render-default .vxe-footer--column.col--ellipsis, .vxe-table--render-default .vxe-header--column.col--ellipsis, .vxe-table--render-default.vxe-editable .vxe-body--column) {
height: 32px !important;
}
</style>

View File

@@ -1,7 +1,7 @@
<!-- 历史数据补召 -->
<template>
<div class="default-main">
<TableHeader>
<TableHeader showCustomColumn>
<template v-slot:select>
<el-form-item label="设备类型">
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->

View File

@@ -42,6 +42,7 @@ import rmsboxi from '@/components/echarts/rmsboxi.vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { Platform, TrendCharts, DataLine, Back } from '@element-plus/icons-vue'
import { mainHeight } from '@/utils/layout'
import { clearWaveCache } from '@/utils/waveCache'
const props = defineProps(['wp'])
const searchForm = ref({
type: 0
@@ -126,6 +127,7 @@ const handleClick = (tab: any, event: any) => {
}, 1000)
}
const handleBack = () => {
clearWaveCache()
emit('handleHideCharts')
}
const setHeight = (h: any, vh: any, num = 1) => {

View File

@@ -1,7 +1,7 @@
<template>
<div class="view">
<div v-show="!isWaveCharts">
<TableHeader datePicker showExport ref="headerRef" @onResetForm="onResetForm">
<TableHeader datePicker showExport showCustomColumn ref="headerRef" @onResetForm="onResetForm">
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
</template>

View File

@@ -1,12 +1,13 @@
<template>
<div class="view" v-loading="loading">
<div class="charts-panel">
<el-collapse v-model="activeNames" class="charts-collapse">
<el-collapse-item name="1">
<template #title>
<div class="charts-collapse-header">
<div style="font-weight: 700; font-size: 13px; text-align: center">数据时间{{ dataTime || '-' }}</div>
<div style="font-weight: 700; font-size: 13px; text-align: center">
数据时间{{ dataTime || '-' }}
</div>
</div>
</template>
<template #icon>
@@ -54,79 +55,253 @@
</div>
<div class="view_bot">
<vxe-table border height="" :data="realList" :column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }">
<vxe-colgroup align="center" :title="`电压有效值(${voltageUnit})`" >
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vRmsA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vRmsB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vRmsC" title="C相"></vxe-column>
<vxe-table
border
height=""
:data="realList"
v-bind="defaultAttribute"
:column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }"
>
<vxe-colgroup align="center" :title="`电压有效值(${voltageUnit})`">
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vRmsA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vRmsB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vRmsC"
title="C相"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="电流有效值(A)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="iRmsA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="iRmsB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="iRmsC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="iRmsA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="iRmsB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="iRmsC"
title="C相"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="基波电压相位(°)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1AngA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1AngB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1AngC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="v1AngA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="v1AngB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="v1AngC"
title="C相"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="基波电流相位(°)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1AngA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1AngB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1AngC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="i1AngA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="i1AngB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="i1AngC"
title="C相"
></vxe-column>
</vxe-colgroup>
</vxe-table>
<br />
<vxe-table border height="" :data="realList" :column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }">
<vxe-column align="center" field="freq"how-overflow-tooltip min-width="160" title="频率(Hz)"></vxe-column>
<vxe-column align="center" field="freqDev"how-overflow-tooltip min-width="160" title="频率偏差(Hz)"></vxe-column>
<vxe-column align="center"how-overflow-tooltip min-width="160" field="vUnbalance" title="电压不平衡度(%)"></vxe-column>
<vxe-column align="center"how-overflow-tooltip min-width="160" field="iUnbalance" title="电流不平衡度(%)"></vxe-column>
<vxe-table
border
height=""
:data="realList"
v-bind="defaultAttribute"
:column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }"
>
<vxe-column
align="center"
field="freq"
how-overflow-tooltip
min-width="160"
title="频率(Hz)"
></vxe-column>
<vxe-column
align="center"
field="freqDev"
how-overflow-tooltip
min-width="160"
title="频率偏差(Hz)"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="160"
field="vUnbalance"
title="电压不平衡度(%)"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="160"
field="iUnbalance"
title="电流不平衡度(%)"
></vxe-column>
<vxe-colgroup align="center" :title="`基波电压幅值(${voltageUnit})`">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1A" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1B" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1C" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1A" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1B" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="v1C" title="C相"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="基波电流幅值(A)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1A" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1B" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1C" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1A" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1B" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="i1C" title="C相"></vxe-column>
</vxe-colgroup>
</vxe-table>
<br />
<vxe-table border height="" :data="realList" :column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }">
<vxe-table
border
height=""
:data="realList"
v-bind="defaultAttribute"
:column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }"
>
<vxe-colgroup align="center" title="电压偏差(%)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vDevA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vDevB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vDevC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vDevA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vDevB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vDevC"
title="C相"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="电压总谐波畸变率(%)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vThdA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vThdB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="vThdC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vThdA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vThdB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="vThdC"
title="C相"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="电流总谐波畸变率(%)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="iThdA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="iThdB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="iThdC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="iThdA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="iThdB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="iThdC"
title="C相"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" :title="`有功功率(${powerUnit})`">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pC" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pTot" title="总"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pC" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pTot" title="总"></vxe-column>
</vxe-colgroup>
</vxe-table>
<br />
<vxe-table border height="" :data="realList" :column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }">
<vxe-table
border
height=""
:data="realList"
v-bind="defaultAttribute"
:column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }"
>
<vxe-colgroup align="center" :title="`无功功率(${reactivePowerUnit})`">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="qA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="qB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="qC" title="C相">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="qA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="qB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="qC" title="C相">
<template #default="{ row }">
{{ row.qC }}
</template>
@@ -134,22 +309,52 @@
<vxe-column align="center" field="qTot" title="总"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" :title="`视在功率(${apparentPowerUnit})`">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sC" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sTot" title="总"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sC" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="sTot" title="总"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="视在功率因数(P/S)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfC" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfTot" title="总"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="pfC" title="C相"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="pfTot"
title="总"
></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="位移功率因数(P/S1)">
<vxe-column align="center" how-overflow-tooltip min-width="80" field="dpfA" title="A相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="dpfB" title="B相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="dpfC" title="C相"></vxe-column>
<vxe-column align="center" how-overflow-tooltip min-width="80" field="dpfTot" title="总"></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="dpfA"
title="A相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="dpfB"
title="B相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="dpfC"
title="C相"
></vxe-column>
<vxe-column
align="center"
how-overflow-tooltip
min-width="80"
field="dpfTot"
title="总"
></vxe-column>
</vxe-colgroup>
</vxe-table>
</div>
@@ -160,7 +365,7 @@ import { ref, onMounted, computed } from 'vue'
import { ArrowDown } from '@element-plus/icons-vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getRealTimeTableList } from '@/api/cs-device-boot/EquipmentDelivery'
import { defaultAttribute } from '@/components/table/defaultAttribute'
const props = defineProps({
dataTime: String
@@ -189,7 +394,7 @@ const previousDataLevel = ref('')
const PHASE_COLORS = {
A: '#DAA520',
B: '#2E8B57',
C: '#A52a2a',
C: '#A52a2a'
}
const PHASE_RING_COLOR = '#9D322D'
@@ -199,7 +404,7 @@ type GaugeAlign = 'left' | 'right'
const createPhaseGaugeData = (name: string, value: number, color: string) => ({
name,
value,
itemStyle: { color, shadowBlur: 0, shadowColor: 'transparent' },
itemStyle: { color, shadowBlur: 0, shadowColor: 'transparent' }
})
const createRmsGaugeOptions = (name: string, color: string, align: GaugeAlign) => {
@@ -223,8 +428,8 @@ const createRmsGaugeOptions = (name: string, color: string, align: GaugeAlign) =
lineStyle: {
width: 5,
shadowBlur: 0,
color: [[1, color]],
},
color: [[1, color]]
}
},
axisTick: {
show: true,
@@ -233,14 +438,14 @@ const createRmsGaugeOptions = (name: string, color: string, align: GaugeAlign) =
lineStyle: {
color,
width: 2,
type: 'solid',
},
type: 'solid'
}
},
axisLabel: {
show: true,
distance: 12,
color,
fontSize: 12,
fontSize: 12
},
splitLine: {
show: true,
@@ -249,22 +454,22 @@ const createRmsGaugeOptions = (name: string, color: string, align: GaugeAlign) =
lineStyle: {
color,
width: 3,
type: 'solid',
},
type: 'solid'
}
},
title: {
show: true,
fontWeight: 'bolder',
fontSize: 12,
color,
offsetCenter: isLeft ? ['-130%', '-20%'] : ['130%', '-20%'],
offsetCenter: isLeft ? ['-130%', '-20%'] : ['130%', '-20%']
},
detail: {
fontSize: 14,
color,
valueAnimation: true,
formatter: '{value}',
offsetCenter: isLeft ? ['50%', '-35%'] : ['-45%', '-35%'],
offsetCenter: isLeft ? ['50%', '-35%'] : ['-45%', '-35%']
},
pointer: {
length: '80%',
@@ -274,18 +479,18 @@ const createRmsGaugeOptions = (name: string, color: string, align: GaugeAlign) =
itemStyle: {
color,
shadowBlur: 0,
shadowColor: 'transparent',
},
shadowColor: 'transparent'
}
},
itemStyle: {
color,
shadowBlur: 0,
shadowColor: 'transparent',
shadowColor: 'transparent'
},
data: [createPhaseGaugeData(name, 0, color)],
},
],
},
data: [createPhaseGaugeData(name, 0, color)]
}
]
}
}
}
@@ -297,7 +502,7 @@ const applyGaugePhaseColor = (options: any, color: string) => {
...series.pointer,
itemStyle: { color, shadowBlur: 0, shadowColor: 'transparent' },
shadowBlur: 0,
shadowColor: 'transparent',
shadowColor: 'transparent'
}
series.axisTick.lineStyle.color = color
series.splitLine.lineStyle.color = color
@@ -313,38 +518,22 @@ const buildPhaseLegendGraphic = () => {
const phases = [
{ key: 'A', label: 'A相', color: PHASE_COLORS.A },
{ key: 'B', label: 'B相', color: PHASE_COLORS.B },
{ key: 'C', label: 'C相', color: PHASE_COLORS.C },
{ key: 'C', label: 'C相', color: PHASE_COLORS.C }
]
const voltageValues = [
realData.value.v1AngA ?? 0,
realData.value.v1AngB ?? 0,
realData.value.v1AngC ?? 0,
]
const currentValues = [
realData.value.i1AngA ?? 0,
realData.value.i1AngB ?? 0,
realData.value.i1AngC ?? 0,
]
const voltageValues = [realData.value.v1AngA ?? 0, realData.value.v1AngB ?? 0, realData.value.v1AngC ?? 0]
const currentValues = [realData.value.i1AngA ?? 0, realData.value.i1AngB ?? 0, realData.value.i1AngC ?? 0]
return [
{
type: 'group',
right: 20,
bottom: 20,
bottom: 20
// children,
},
}
]
}
const updateRmsGaugeChart = (
chartRef: any,
chartData: any,
name: string,
value: number,
color: string
) => {
const updateRmsGaugeChart = (chartRef: any, chartData: any, name: string, value: number, color: string) => {
chartData.value.options.series[0].max = value == 0 ? 1 : Math.ceil(value * 1.2)
chartData.value.options.series[0].data = [createPhaseGaugeData(name, value || 0, color)]
applyGaugePhaseColor(chartData.value.options, color)
@@ -399,10 +588,10 @@ const initRadioCharts = () => {
[0.25, PHASE_RING_COLOR],
[0.5, PHASE_RING_COLOR],
[0.75, PHASE_RING_COLOR],
[1, PHASE_RING_COLOR],
[1, PHASE_RING_COLOR]
],
width: 2,
},
width: 2
}
},
axisTick: {
show: true,
@@ -412,8 +601,8 @@ const initRadioCharts = () => {
lineStyle: {
color: PHASE_RING_COLOR,
width: 1,
type: 'solid',
},
type: 'solid'
}
},
splitLine: {
show: true,
@@ -422,8 +611,8 @@ const initRadioCharts = () => {
lineStyle: {
color: PHASE_RING_COLOR,
width: 2,
type: 'solid',
},
type: 'solid'
}
},
// 分割线标识
axisLabel: {
@@ -451,7 +640,7 @@ const initRadioCharts = () => {
width: 15,
opacity: 1,
shadowBlur: 0,
shadowColor: 'transparent',
shadowColor: 'transparent'
},
detail: {
show: false
@@ -508,10 +697,10 @@ const initRadioCharts = () => {
[0.25, PHASE_RING_COLOR],
[0.5, PHASE_RING_COLOR],
[0.75, PHASE_RING_COLOR],
[1, PHASE_RING_COLOR],
[1, PHASE_RING_COLOR]
],
width: 1.5,
},
width: 1.5
}
},
axisTick: {
show: true,
@@ -521,8 +710,8 @@ const initRadioCharts = () => {
lineStyle: {
color: PHASE_RING_COLOR,
width: 1,
type: 'solid',
},
type: 'solid'
}
},
splitLine: {
show: true,
@@ -531,8 +720,8 @@ const initRadioCharts = () => {
lineStyle: {
color: PHASE_RING_COLOR,
width: 2,
type: 'solid',
},
type: 'solid'
}
},
// 分割线标识
axisLabel: {
@@ -560,7 +749,7 @@ const initRadioCharts = () => {
width: 15,
opacity: 1,
shadowBlur: 0,
shadowColor: 'transparent',
shadowColor: 'transparent'
},
detail: {
show: false
@@ -761,8 +950,6 @@ onMounted(() => {
border: none;
}
:deep(.el-collapse-item__arrow) {
display: none;
}
@@ -777,8 +964,6 @@ onMounted(() => {
pointer-events: none;
}
.charts-collapse-action {
display: inline-flex;
align-items: center;
@@ -895,102 +1080,5 @@ onMounted(() => {
display: none;
}
.table_container {
width: 100%;
height: auto;
display: flex;
align-items: center;
justify-content: center;
.table {
flex: 1;
.table_info {
width: 100%;
height: 120px;
// border: 1px solid #eee;
border-bottom: 2px solid #eee;
margin-bottom: 20px;
display: flex;
flex-direction: column;
}
.thead {
width: 100%;
height: auto;
background: #f4f6f9;
text-align: center;
display: flex;
flex-direction: column;
.thead_top {
width: 100%;
height: 40px;
line-height: 40px;
border: 1px solid #eee;
color: #111;
font-size: 14px;
font-weight: 800;
}
.thead_bot {
width: 100%;
height: 40px;
line-height: 40px;
display: flex;
color: #111;
font-size: 14px;
font-weight: 800;
.thead_bot_cell {
flex: 1;
border: 1px solid #eee;
}
}
}
.tbody {
flex: 1;
display: flex;
text-align: center;
.tbody_cell {
flex: 1;
text-align: center;
line-height: 40px;
border: 1px solid #eee;
border-bottom: 0;
}
}
.tbody:hover {
background: #f4f6f9;
}
}
}
.table_container:hover {
.table {
.tbody {
background: #f4f6f9;
}
}
}
:deep(.view_bot) {
.vxe-table--render-default .vxe-body--column:not(.col--ellipsis),
.vxe-table--render-default .vxe-footer--column:not(.col--ellipsis),
.vxe-table--render-default .vxe-header--column:not(.col--ellipsis) {
padding: 5px !important;
}
.vxe-table--body-wrapper {
min-height: 32px !important;
}
}
:deep(.vxe-table--render-default) {
font-size: 13px !important;
}
</style>

View File

@@ -31,7 +31,7 @@
</el-descriptions-item>
<el-descriptions-item label="接入方式">
{{ deviceData.devAccessMethod =='CLD'?'1056协议':deviceData.devAccessMethod || '/' }}
{{ deviceData.devAccessMethod == 'CLD' ? '1056协议' : deviceData.devAccessMethod || '/' }}
</el-descriptions-item>
<el-descriptions-item label="网络设备ID">
{{ deviceData.ndid || '/' }}
@@ -309,7 +309,7 @@ const exportData = () => {
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.device-manage {
display: flex;
@@ -343,4 +343,7 @@ const exportData = () => {
right: 10px;
z-index: 10;
}
:deep(.el-tabs__header) {
width: calc(100% - 100px);
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<div v-show="!isWaveCharts">
<TableHeader showExport ref="headerRef" :showQuery="false" @onResetForm="onResetForm">
<TableHeader showExport showCustomColumn ref="headerRef" :showQuery="false" @onResetForm="onResetForm">
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
</template>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<TableHeader datePicker showExport>
<TableHeader datePicker showExport showCustomColumn>
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"
@@ -76,10 +76,10 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '调试时间', field: 'startTime', align: 'center', sortable: true, width: 180 },
{ title: '设备名称', field: 'deviceName', align: 'center', width: 180 },
{ title: '调试时间', field: 'startTime', align: 'center', sortable: true, minWidth: 180 },
{ title: '设备名称', field: 'deviceName', align: 'center', minWidth: 180 },
{
title: '监测点名称', field: 'lineName', align: 'center', width: 180, formatter: (row: any) => {
title: '监测点名称', field: 'lineName', align: 'center', minWidth: 180, formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},

View File

@@ -1,6 +1,6 @@
<template>
<!-- 异常事件 -->
<TableHeader datePicker ref="refheader" showExport>
<TableHeader datePicker ref="refheader" showExport >
<!-- <template v-slot:select>
<el-form-item label="数据来源">
<el-cascader

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader datePicker showExport></TableHeader>
<TableHeader datePicker showExport showCustomColumn></TableHeader>
<Table ref="tableRef" :isGroup="true" />
</div>
</template>
@@ -26,15 +26,15 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '操作日期', field: 'createTime', align: 'center', sortable: true, width: '180' },
{ title: '用户名称', field: 'userName', align: 'center', width: '180' },
{ title: '操作日期', field: 'createTime', align: 'center', sortable: true, minWidth: '180' },
{ title: '用户名称', field: 'userName', align: 'center', minWidth: '180' },
{ title: '操作描述', field: 'operate', align: 'center', minWidth: '300' },
{
title: '状态',
field: 'result',
align: 'center',
width: '100',
minWidth: '100',
render: 'tag',
custom: {
0: 'danger',

View File

@@ -1,33 +1,33 @@
<template>
<div class="default-main">
<TableHeader datePicker> </TableHeader>
<Table ref="tableRef" />
</div>
</template>
<script setup lang="ts">
import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
defineOptions({
name: 'govern/log/push'
})
const tableStore = new TableStore({
url: '/cs-device-boot/csEventSendMsg/queryLog',
method: 'POST',
column: [
{ title: '推送用户', field: 'userName', align: 'center' },
{ title: '推送内容', field: 'showName', align: 'center' },
{ title: '推送时间', field: 'sendTime', align: 'center', sortable: true },
]
})
provide('tableStore', tableStore)
tableStore.table.params.searchState = 0
onMounted(() => {
tableStore.index()
})
const addMenu = () => {}
<template>
<div class="default-main">
<TableHeader datePicker > </TableHeader>
<Table ref="tableRef" />
</div>
</template>
<script setup lang="ts">
import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
defineOptions({
name: 'govern/log/push'
})
const tableStore = new TableStore({
url: '/cs-device-boot/csEventSendMsg/queryLog',
method: 'POST',
column: [
{ title: '推送用户', field: 'userName', align: 'center' },
{ title: '推送内容', field: 'showName', align: 'center' },
{ title: '推送时间', field: 'sendTime', align: 'center', sortable: true },
]
})
provide('tableStore', tableStore)
tableStore.table.params.searchState = 0
onMounted(() => {
tableStore.index()
})
const addMenu = () => {}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader>
<TableHeader showCustomColumn>
<template #select>
<el-form-item label="数据分类">
<el-select v-model.trim="tableStore.table.params.dataType" multiple filterable collapse-tags

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main" v-loading="loading">
<TableHeader ref="tableHeaderRef">
<TableHeader ref="tableHeaderRef" showCustomColumn>
<template #select>
<el-form-item label="模版名称">
<el-input maxlength="32" show-word-limit

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader ref="tableHeaderRef" :showReset="false" showExport>
<TableHeader ref="tableHeaderRef" :showReset="false" showExport showCustomColumn>
<template #select>
<el-form-item label="设备型号:">
<el-select v-model.trim="tableStore.table.params.devType" filterable placeholder="请选择设备型号"

View File

@@ -1,6 +1,6 @@
<template>
<div v-loading="loading">
<TableHeader>
<TableHeader showCustomColumn>
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader datePicker>
<TableHeader datePicker >
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader>
<TableHeader >
<template v-slot:operation>
<el-upload
action=""

View File

@@ -1,168 +1,270 @@
<template>
<div class="default-main">
<TableHeader datePicker ref="refheader">
<TableHeader datePicker showCustomColumn ref="refheader">
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit
<el-input
maxlength="32"
show-word-limit
v-model.trim="tableStore.table.params.name"
placeholder="请输入关键字"
clearable
></el-input>
</el-form-item>
<!-- <el-form-item label="流程阶段">
<el-select v-model.trim="tableStore.table.params.process" clearable placeholder="请选择">
<el-option label="功能调试" :value="2"></el-option>
<el-option label="出厂调试" :value="3"></el-option>
<el-option label="正式投运" :value="4"></el-option>
</el-select>
</el-form-item> -->
</template>
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Download" @click="exportTab">导出</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
<Table ref="tableRef" id="monthly-report-table" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import { ref, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
import { buildExportBaseName } from '@/utils/echartMethod'
defineOptions({
name: 'manage/monthly'
})
const refheader = ref()
const devModelOptions: any = ref([])
queryByCode('Device_Type').then(res => {
queryByid(res.data.id).then(res => {
devModelOptions.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
})
tableStore.index()
})
const tableStore = new TableStore({
url: '/cs-harmonic-boot/statisticsData/halfMonthReport',
method: 'POST',
isWebPaging: true,
exportName: '半月报功能',
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '工程名称', field: 'engineeringName', minWidth: 150 },
{ title: '项目名称', field: 'projectName', minWidth: 150 },
{ title: '设备名称', field: 'devName', minWidth: 150 },
{ title: '监测点名称', field: 'lineName', minWidth: 150 },
{
title: '投运时间',
field: 'operationalTime',
width: 180,
minWidth: 180,
sortable: true
},
{
title: '数据更新时间',
field: 'latestTime',
width: 180,
minWidth: 180,
sortable: true
// formatter: (row: any) => {
// return row.cellValue || '/'
// }
},
// {
// title: '设备型号',
// field: 'devType',
// width: 130,
// formatter: row => {
// return devModelOptions.value.filter((item: any) => item.value == row.cellValue)[0]?.label
// }
// },
// { title: 'Mac地址', field: 'mac', width: 140 },
// {
// title: '流程阶段',
// field: 'process',
// width: 100,
// fixed: 'right',
// render: 'tag',
// custom: {
// 2: 'warning',
// 3: 'warning',
// 4: 'success'
// },
// replaceValue: {
// 2: '功能调试',
// 3: '出厂调试',
// 4: '正式投运'
// },
// minWidth: 80
// },
{
title: '运行状态',
field: 'operationalStatus',
render: 'tag',
fixed: 'right',
width: 100,
custom: {
停运: 'danger',
在运: 'success'
},
replaceValue: {
在运: '在运',
停运: '停运'
}
},
{
title: '通讯状态',
field: 'communicationStatus',
width: 100,
fixed: 'right',
render: 'tag',
custom: {
离线: 'danger',
在线: 'success'
},
replaceValue: {
离线: '离线',
在线: '在线'
}
},
{ title: '在线率(%)', fixed: 'right', width: 100, field: 'onlineRate', sortable: true },
{ title: '完整性(%)', fixed: 'right', width: 100, field: 'integrity', sortable: true }
],
beforeSearchFun: () => {},
exportProcessingData: () => {
tableStore.table.allData = tableStore.table.allData.filter(item => {
item.process = item.process == 2 ? '功能调试' : item.process == 3 ? '出厂调试' : '正式投运'
return item
})
},
loadCallback: () => {
let name = tableStore.table.params.name
let data = tableStore.table.copyData.filter(item => {
// 处理latestTime默认值
item.latestTime = item.latestTime || '/'
// 需要检查的字段列表
const fieldsToCheck = ['projectName', 'engineeringName', 'mac', 'devName', 'lineName']
// 检查任何一个字段包含搜索名称
return fieldsToCheck.some(field => item[field]?.includes(name))
})
tableStore.table.copyData = JSON.parse(JSON.stringify(data))
tableStore.table.total = tableStore.table.copyData.length
if (data.length == 0) {
tableStore.table.data = []
} else {
@@ -176,33 +278,44 @@ const tableStore = new TableStore({
})
provide('tableStore', tableStore)
// tableStore.table.params.process = 4
tableStore.table.params.name = ''
const tableRef = ref()
const exportColumnFilterMethod = ({ column }: { column: any }) => {
return !(column.title === undefined || column.title === '序号' || column.title === '操作')
}
const exportTab = () => {
tableRef.value.getRef()?.exportData({
filename: buildExportBaseName({ feature: '半月报功能' }), // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
isTitle: true,
data: tableStore.table.copyData.filter(item => {
item.process = item.process == 2 ? '功能调试' : item.process == 3 ? '出厂调试' : '正式投运'
return item
}), // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
columnFilterMethod: exportColumnFilterMethod
})
}
onMounted(() => {})
setTimeout(() => {
// tableStore.table.height = mainHeight(200).height as any
}, 0)
const addMenu = () => {}
</script>
<style></style>

View File

@@ -4,7 +4,6 @@
<div class="manage-process-right">
<div class="process-flow-section">
<el-descriptions title="数据链路">
</el-descriptions>
<div class="process-flow-wrap">
<div class="process-flow">
@@ -44,18 +43,18 @@
<div class="process-list-section">
<el-descriptions title="数据列表" />
<div class="process-list-body">
<el-table :data="processTableData" border stripe height="100%">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="name" label="节点" min-width="100" align="center" />
<el-table-column prop="link" label="上游链路" min-width="140" align="center" />
<el-table-column prop="status" label="连接状态" min-width="100" align="center">
<vxe-table :data="processTableData" v-bind="defaultAttribute" height="100%" auto-resize>
<vxe-column type="seq" title="序号" width="60" />
<vxe-column field="name" title="节点" min-width="100" />
<vxe-column field="link" title="上游链路" min-width="140" />
<vxe-column field="status" title="连接状态" min-width="100">
<template #default="{ row }">
<span :class="`process-table-status process-table-status--${row.state}`">
{{ row.status }}
</span>
</template>
</el-table-column>
</el-table>
</vxe-column>
</vxe-table>
</div>
</div>
</div>
@@ -66,6 +65,7 @@ import { h, watch, onUnmounted, ref, computed, defineComponent } from 'vue'
import { Monitor, Coin } from '@element-plus/icons-vue'
import { mainHeight } from '@/utils/layout'
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
defineOptions({
name: 'process'
@@ -74,7 +74,7 @@ defineOptions({
const pageHeight = mainHeight(20)
/** 连接状态null-初始0-终端绿/终端↔前置1-前置绿/前置↔MQTT2-MQTT绿/MQTT↔数据库3-数据库绿/数据库↔Web4-全部完成 */
const linkStatus = ref<number | null>(2)
const linkStatus = ref<number | null>(0)
const COLOR = {
pending: '#94a3b8',

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader ref="tableHeaderRef" showExport>
<TableHeader ref="tableHeaderRef" showExport showCustomColumn>
<template #select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit v-model="tableStore.table.params.searchValue" clearable placeholder="请输入设备名称"
@@ -84,7 +84,7 @@ const tableStore: any = new TableStore({
{ title: '协议版本', field: 'protocolVersion', minWidth: '100', formatter: (row: any) => { return row.cellValue || '/' } },
{ title: '版本日期', field: 'versionDate', minWidth: '150', formatter: (row: any) => { return row.cellValue || '/' } },
{ title: '设备型号', field: 'devModelName', minWidth: '120', formatter: (row: any) => { return row.cellValue || '/' } },
{ title: 'icd模型', field: 'icd', minWidth: '120', formatter: (row: any) => { return icdList.value.filter((item: any) => item.id == row.cellValue)[0]?.name || '/' } },
{ title: 'icd模型', field: 'icd', minWidth: '120', formatter: (row: any) => { return icdList.value?.filter((item: any) => item.id == row.cellValue)[0]?.name || '/' } },
{ title: '所属工程', field: 'associatedEngineering', minWidth: '120', formatter: (row: any) => { return row.cellValue || '/' } },
{ title: '所属项目', field: 'associatedProject', minWidth: '120', formatter: (row: any) => { return row.cellValue || '/' } },
{

View File

@@ -1,6 +1,6 @@
<template>
<div class="view">
<TableHeader datePicker ref="TableHeaderRef" :showReset="false" showExport>
<TableHeader datePicker ref="TableHeaderRef" :showReset="false" showExport >
<template #operation>
<el-button type="primary" :icon="Setting" @click="recall1">事件补召</el-button>
<el-button type="primary" :icon="Setting" @click="recall2">波形补召</el-button>

View File

@@ -1,7 +1,7 @@
<!-- 补召日志 -->
<template>
<TableHeader date-picker :showReset="false">
<TableHeader date-picker :showReset="false" showCustomColumn>
<template #operation>
<el-button type="primary" icon="el-icon-Connection" @click="handleImport">
离线补召
@@ -160,7 +160,7 @@ const handleaddDevice = () => {
query: {
activeName: '0',
id: lineId.value,
ndid: deviceData.value?.ndid,
ndid: (deviceData.value as any)?.ndid || '',
}
})

View File

@@ -1,14 +1,24 @@
<template>
<div class="default-main report-zl-page" :style="height">
<div class="report-zl-sidebar">
<pointTree ref="terminalRef" template @Policy="stencil" @node-click="handleNodeClick"
@init="handleNodeClick" @pointTypeChange="pointTypeChange" />
<pointTree
ref="terminalRef"
template
@Policy="stencil"
@node-click="handleNodeClick"
@init="handleNodeClick"
@pointTypeChange="pointTypeChange"
/>
</div>
<el-tabs v-model="activeTab" type="border-card" class="report-zl-tabs">
<el-tab-pane label="报表" name="sheet">
<Sheet :dot-list="dotList" :line-flag="lineFlag" :template-policy="templatePolicy"
:active="activeTab === 'sheet'" />
<Sheet
:dot-list="dotList"
:line-flag="lineFlag"
:template-policy="templatePolicy"
:active="activeTab === 'sheet'"
/>
</el-tab-pane>
<el-tab-pane label="报告" name="report">
<Report :dot-list="dotList" :line-flag="lineFlag" />
@@ -26,7 +36,7 @@ import Sheet from './components/sheet.vue'
import Report from './components/report.vue'
defineOptions({
name: 'govern/reportCore/statisticsWx/index',
name: 'govern/reportCore/statisticsWx/index'
})
const props = withDefaults(
@@ -34,7 +44,7 @@ const props = withDefaults(
defaultTab?: 'sheet' | 'report'
}>(),
{
defaultTab: 'sheet',
defaultTab: 'sheet'
}
)
@@ -54,7 +64,7 @@ const pointTypeChange = (_val: any, obj: any) => {
}
const handleNodeClick = (data: any) => {
if (data.name.includes('治理监测点')) {
if (data.name.includes('治理监测点') ) {
lineFlag.value = false
return
}
@@ -78,16 +88,10 @@ const handleNodeClick = (data: any) => {
overflow: hidden;
}
.report-zl-tabs {
flex: 1;
min-height: 0;
.el-tab-pane {
height: 100%;
display: flex;

View File

@@ -1,6 +1,6 @@
<template>
<div class="dictiontary-list-detail child-router">
<TableHeader>
<TableHeader showCustomColumn>
<template #select>
<el-form-item label="">
<span class="text-large font-600 mr-3" style="font-weight: 600;">{{ props.bingRow.name
@@ -37,16 +37,23 @@ const tableStore = new TableStore({
url: '/cs-harmonic-boot/pqGovernPlan/getListByPid',
method: 'GET',
column: [
{ title: '治理点名称', field: 'governName', width: 200 },
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '治理点名称', field: 'governName', minWidth: 200 },
{
title: '治理类型',
field: 'governType',
width: 120,
minWidth: 120,
formatter: row => {
return row.cellValue == 'harmonic' ? '稳态治理' : '暂态治理'
}
},
{ title: '治理方法', field: 'governMethod', width: 120 },
{ title: '治理方法', field: 'governMethod', minWidth: 120 },
{ title: '治理前-监测点', field: 'ledgerBefore', minWidth: 200, formatter: row => row.cellValue || row.row?.governBefore || '/' },
{ title: '治理后-监测点', field: 'ledgerAfter', minWidth: 200, formatter: row => row.cellValue || row.row?.governAfter || '/' },

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main" style="position: relative">
<TableHeader :showReset="false" showExport>
<TableHeader :showReset="false" showExport showCustomColumn>
<template #select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"

View File

@@ -2,7 +2,7 @@
<div class="default-main">
<div class="default">
<div style="width: calc(100% - 300px);">
<TableHeader>
<TableHeader showCustomColumn>
<template v-slot:select>
<el-form-item label="前置等级">
<el-select v-model="tableStore.table.params.nodeGrade" clearable placeholder="请选择前置等级">

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader>
<TableHeader showCustomColumn>
<template #select>
<el-form-item label="设备类型">
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
@@ -181,6 +181,13 @@ const tableStore = new TableStore({
url: '/cs-device-boot/EquipmentDelivery/list',
method: 'POST',
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'name' },
{
title: '设备类型',

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader>
<TableHeader showCustomColumn>
<template #select>
<el-form-item label="设备类型">
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
@@ -183,6 +183,13 @@ const tableStore = new TableStore({
url: '/cs-device-boot/EquipmentDelivery/list',
method: 'POST',
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'name' },
{
title: '设备类型',

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader date-picker>
<TableHeader date-picker showCustomColumn>
<template v-slot:select>
<!-- <el-form-item label="用户名">
<el-select v-model.trim="value" class="m-2" placeholder="Select" size="large">
@@ -29,18 +29,25 @@ import { saveLogParam } from '@/api/common'
defineOptions({
name: 'comptroller/list'
})
const tableStore = new TableStore({
const tableStore: any = new TableStore({
url: '/system-boot/audit/getAuditLog',
method: 'POST',
column: [
{ title: '操作时间', field: 'time', align: 'center', width: 200 , sortable: true},
{ title: '操作人员', field: 'userName', align: 'center', width: 120 },
{ title: '操作类型', field: 'operate', align: 'center', width: 220 },
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '操作时间', field: 'time', align: 'center', minWidth: 200 , sortable: true},
{ title: '操作人员', field: 'userName', align: 'center', minWidth: 120 },
{ title: '操作类型', field: 'operate', align: 'center', minWidth: 220 },
{ title: '事件描述', field: 'describe', align: 'center', showOverflow: true, minWidth: 200 },
{ title: '事件类型', field: 'type', align: 'center', width: 160 },
{ title: '操作结果', field: 'type', align: 'center', width: 100 },
{ title: '操作IP', field: 'ip', align: 'center', width: 160 },
{ title: '事件等级', field: 'level', align: 'center', width: 100 }
{ title: '事件类型', field: 'type', align: 'center', minWidth: 160 },
{ title: '操作结果', field: 'type', align: 'center', minWidth: 100 },
{ title: '操作IP', field: 'ip', align: 'center', minWidth: 160 },
{ title: '事件等级', field: 'level', align: 'center', minWidth: 100 }
]
})
tableStore.table.params.loginName = ''

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader date-picker area>
<TableHeader date-picker area showCustomColumn>
<template v-slot:select>
<el-form-item label="终端状态">
@@ -47,7 +47,7 @@ defineOptions({
const dictData = useDictData()
const manufacturer = dictData.getBasicData('Dev_Manufacturers')
const manufacturerForm = ref<string[]>([])
const tableStore = new TableStore({
const tableStore: any = new TableStore({
isWebPaging: true,
url: '/device-boot/runManage/getRuntimeData',
method: 'POST',
@@ -57,23 +57,23 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '区域', field: 'areaName', align: 'center', width: 120 },
{ title: '供电公司', field: 'gdName', align: 'center', width: 120 },
{ title: '区域', field: 'areaName', align: 'center', minWidth: 120 },
{ title: '供电公司', field: 'gdName', align: 'center', minWidth: 120 },
{ title: '变电站', field: 'bdName', align: 'center', showOverflow: true, minWidth: 100 },
{ title: '终端编号', field: 'devName', align: 'center', width: 160 },
{ title: '投运时间', field: 'loginTime', align: 'center', width: 200 , sortable: true},
{ title: '厂家', field: 'manufacturer', align: 'center', width: 160 },
{ title: '型号', field: 'devType', align: 'center', width: 200 },
{ title: '网络参数', field: 'ip', align: 'center', width: 200 },
{ title: '端口', field: 'port', align: 'center', width: 100 },
{ title: '终端状态', field: 'runFlag', align: 'center', width: 100 },
{ title: '通讯状态', field: 'comFlag', align: 'center', width: 100 },
{ title: '最新数据', field: 'updateTime', align: 'center', width: 200, sortable: true },
{ title: '终端编号', field: 'devName', align: 'center', minWidth: 160 },
{ title: '投运时间', field: 'loginTime', align: 'center', minWidth: 200 , sortable: true},
{ title: '厂家', field: 'manufacturer', align: 'center', minWidth: 160 },
{ title: '型号', field: 'devType', align: 'center', minWidth: 200 },
{ title: '网络参数', field: 'ip', align: 'center', minWidth: 200 },
{ title: '端口', field: 'port', align: 'center', minWidth: 100 },
{ title: '终端状态', field: 'runFlag', align: 'center', minWidth: 100 },
{ title: '通讯状态', field: 'comFlag', align: 'center', minWidth: 100 },
{ title: '最新数据', field: 'updateTime', align: 'center', minWidth: 200, sortable: true },
{
title: '评价',
field: 'onlineEvaluate',
align: 'center',
width: 100,
minWidth: 100,
render: 'customRender',
customRender: props => {
if (props.renderValue == null) {

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader date-picker area>
<TableHeader date-picker area showCustomColumn>
<template v-slot:select>
<el-form-item label="干扰源类型">
<el-select multiple clearable collapse-tags v-model.trim="interferenceSourceForm" placeholder="请选择"
@@ -47,70 +47,77 @@ const interferenceSource = dictData.getBasicData('Interference_Source')
const level = dictData.getBasicData('Dev_Voltage_Stand')
const interferenceSourceForm = ref<string[]>([])
const scaleForm = ref<string[]>([])
const tableStore = new TableStore({
const tableStore: any = new TableStore({
isWebPaging: true,
url: '/device-boot/runManage/getLineLedger',
method: 'POST',
column: [
{ field: 'areaName', title: '省公司', width: 150 },
{ field: 'gdName', title: '市公司', width: 150 },
{ field: 'scale', title: '监测点电压等级', width: 150 },
{ field: 'lineName', title: '监测点名称', width: 150 },
{ field: 'bdName', title: '所属变电站', width: 150 },
{ field: 'loadType', title: '干扰源类型', width: 120 },
{ field: 'objName', title: '监测对象名称', width: 180 },
{ field: 'shortCapacity', title: '最小短路容量(MVA)', width: 190 },
{ field: 'devCapacity', title: '供电设备容量(MVA )', width: 190 },
{ field: 'dealCapacity', title: '用户协议容量(MVA)', width: 190 },
{ field: 'comFlag', title: '通讯状态 ', width: 120 },
{ field: 'id', title: '监测点序号', width: 120 },
{ field: 'devName', title: '监测终端编号 ', width: 140 },
{ field: 'ptType', title: '监测终端接线方式', width: 160 },
{ field: 'voltageDev', title: '电压偏差上限(%)', width: 160 },
{ field: 'uvoltageDev', title: '电压偏差下限(%)', width: 160 },
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'areaName', title: '省公司', minWidth: 150 },
{ field: 'gdName', title: '市公司', minWidth: 150 },
{ field: 'scale', title: '监测点电压等级', minWidth: 150 },
{ field: 'lineName', title: '监测点名称', minWidth: 150 },
{ field: 'bdName', title: '所属变电站', minWidth: 150 },
{ field: 'loadType', title: '干扰源类型', minWidth: 120 },
{ field: 'objName', title: '监测对象名称', minWidth: 180 },
{ field: 'shortCapacity', title: '最小短路容量(MVA)', minWidth: 190 },
{ field: 'devCapacity', title: '供电设备容量(MVA )', minWidth: 190 },
{ field: 'dealCapacity', title: '用户协议容量(MVA)', minWidth: 190 },
{ field: 'comFlag', title: '通讯状态 ', minWidth: 120 },
{ field: 'id', title: '监测点序号', minWidth: 120 },
{ field: 'devName', title: '监测终端编号 ', minWidth: 140 },
{ field: 'ptType', title: '监测终端接线方式', minWidth: 160 },
{ field: 'voltageDev', title: '电压偏差上限(%)', minWidth: 160 },
{ field: 'uvoltageDev', title: '电压偏差下限(%)', minWidth: 160 },
{
field: 'limitValue',
title: '限值',
children: [
{ field: 'freqDev', title: '频率(Hz)', width: 120 },
{ field: 'ubalance', title: '三相电压不平衡度(%)', width: 190 },
{ field: 'ineg', title: '负序电流(A)', width: 120 },
{ field: 'flicker', title: '长时闪变', width: 120 },
{ field: 'uaberrance', title: '电压总谐波畸变率(%)', width: 190 },
{ field: 'oddHarm', title: '奇数次谐波电压(%)', width: 180 },
{ field: 'evenHarm', title: '偶数次谐波电压(%)', width: 180 }
{ field: 'freqDev', title: '频率(Hz)', minWidth: 120 },
{ field: 'ubalance', title: '三相电压不平衡度(%)', minWidth: 190 },
{ field: 'ineg', title: '负序电流(A)', minWidth: 120 },
{ field: 'flicker', title: '长时闪变', minWidth: 120 },
{ field: 'uaberrance', title: '电压总谐波畸变率(%)', minWidth: 190 },
{ field: 'oddHarm', title: '奇数次谐波电压(%)', minWidth: 180 },
{ field: 'evenHarm', title: '偶数次谐波电压(%)', minWidth: 180 }
]
},
{
field: 'evaluate',
title: '电流限值',
children: [
{ field: 'iharm2', title: '2次谐波(A)', width: 120 },
{ field: 'iharm3', title: '3次谐波(A)', width: 120 },
{ field: 'iharm4', title: '4次谐波(A)', width: 120 },
{ field: 'iharm5', title: '5次谐波(A)', width: 120 },
{ field: 'iharm6', title: '6次谐波(A)', width: 120 },
{ field: 'iharm7', title: '7次谐波(A)', width: 120 },
{ field: 'iharm8', title: '8次谐波(A)', width: 120 },
{ field: 'iharm9', title: '9次谐波(A)', width: 120 },
{ field: 'iharm10', title: '10次谐波(A)', width: 140 },
{ field: 'iharm11', title: '11次谐波(A)', width: 140 },
{ field: 'iharm12', title: '12次谐波(A)', width: 140 },
{ field: 'iharm13', title: '13次谐波(A)', width: 140 },
{ field: 'iharm14', title: '14次谐波(A)', width: 140 },
{ field: 'iharm15', title: '15次谐波(A)', width: 140 },
{ field: 'iharm16', title: '16次谐波(A)', width: 140 },
{ field: 'iharm17', title: '17次谐波(A)', width: 140 },
{ field: 'iharm18', title: '18次谐波(A)', width: 140 },
{ field: 'iharm19', title: '19次谐波(A)', width: 140 },
{ field: 'iharm10', title: '20次谐波(A)', width: 140 },
{ field: 'iharm21', title: '21次谐波(A)', width: 140 },
{ field: 'iharm22', title: '22次谐波(A)', width: 140 },
{ field: 'iharm23', title: '23次谐波(A)', width: 140 },
{ field: 'iharm24', title: '24次谐波(A)', width: 140 },
{ field: 'iharm25', title: '25次谐波(A)', width: 140 },
{ field: 'inUharm', title: '0.5-1.5次间谐波(A)', width: 180 },
{ field: 'inUharm16', title: '2.5-15.5次间谐波(A)', width: 190 }
{ field: 'iharm2', title: '2次谐波(A)', minWidth: 120 },
{ field: 'iharm3', title: '3次谐波(A)', minWidth: 120 },
{ field: 'iharm4', title: '4次谐波(A)', minWidth: 120 },
{ field: 'iharm5', title: '5次谐波(A)', minWidth: 120 },
{ field: 'iharm6', title: '6次谐波(A)', minWidth: 120 },
{ field: 'iharm7', title: '7次谐波(A)', minWidth: 120 },
{ field: 'iharm8', title: '8次谐波(A)', minWidth: 120 },
{ field: 'iharm9', title: '9次谐波(A)', minWidth: 120 },
{ field: 'iharm10', title: '10次谐波(A)', minWidth: 140 },
{ field: 'iharm11', title: '11次谐波(A)', minWidth: 140 },
{ field: 'iharm12', title: '12次谐波(A)', minWidth: 140 },
{ field: 'iharm13', title: '13次谐波(A)', minWidth: 140 },
{ field: 'iharm14', title: '14次谐波(A)', minWidth: 140 },
{ field: 'iharm15', title: '15次谐波(A)', minWidth: 140 },
{ field: 'iharm16', title: '16次谐波(A)', minWidth: 140 },
{ field: 'iharm17', title: '17次谐波(A)', minWidth: 140 },
{ field: 'iharm18', title: '18次谐波(A)', minWidth: 140 },
{ field: 'iharm19', title: '19次谐波(A)', minWidth: 140 },
{ field: 'iharm10', title: '20次谐波(A)', minWidth: 140 },
{ field: 'iharm21', title: '21次谐波(A)', minWidth: 140 },
{ field: 'iharm22', title: '22次谐波(A)', minWidth: 140 },
{ field: 'iharm23', title: '23次谐波(A)', minWidth: 140 },
{ field: 'iharm24', title: '24次谐波(A)', minWidth: 140 },
{ field: 'iharm25', title: '25次谐波(A)', minWidth: 140 },
{ field: 'inUharm', title: '0.5-1.5次间谐波(A)', minWidth: 180 },
{ field: 'inUharm16', title: '2.5-15.5次间谐波(A)', minWidth: 190 }
]
}
],

View File

@@ -4,23 +4,40 @@
<!-- 实时数据 走驾驶舱-->
<!-- 添加加载事件监听 -->
<div class="dataBox" :style="{ height: prop.height ? prop.height : pageHeight.height }">
<div class="iframe-container" :style="{
boxShadow: `var(--el-box-shadow-light)`
}" style="position: relative">
<iframe v-if="bindId" :key="bindId" :src="iframeSrc" width="100%" height="100%" frameborder="0"
scrolling="no" id="iframeLeft" @load="onIframeLoad"></iframe>
<div
class="iframe-container"
:style="{
boxShadow: `var(--el-box-shadow-light)`
}"
style="position: relative"
>
<iframe
v-if="bindId"
:key="bindId"
:src="iframeSrc"
width="100%"
height="100%"
frameborder="0"
scrolling="no"
id="iframeLeft"
@load="onIframeLoad"
></iframe>
<el-empty v-else description="暂无绑定页面" style="height: 100%" />
</div>
</div>
<div class="bottom-container">
<el-button type="primary" :icon="show ? 'el-icon-ArrowDownBold' : 'el-icon-ArrowUpBold'"
@click="show = !show" style="width: 100%" >
<el-button
type="primary"
:icon="show ? 'el-icon-ArrowDownBold' : 'el-icon-ArrowUpBold'"
@click="show = !show"
style="width: 100%"
>
事件列表
</el-button>
<!-- <el-button class="bindBut" type="primary" icon="el-icon-Sort" @click="bindClick">绑定</el-button> -->
<el-icon class="bindBut">
<Sort style="width: 30px;height: 30px;" color="#fff" @click="bindClick" />
<Sort style="width: 30px; height: 30px" color="#fff" @click="bindClick" />
</el-icon>
<!-- <div class="buttonBox">
<el-button type="primary" icon="el-icon-Aim" @click="reset">复位</el-button>
@@ -28,7 +45,14 @@
<transition name="table-fade">
<div class="tableBox" v-if="show">
<vxe-table border auto-resize height="230px" :data="tableData" ref="tableRef">
<vxe-table
border
auto-resize
height="230px"
:data="tableData"
ref="tableRef"
v-bind="defaultAttribute"
>
<vxe-column type="seq" title="序号" align="center" width="80px"></vxe-column>
<vxe-column field="date" align="center" sortable title="发生时间" width="200px"></vxe-column>
<vxe-column field="name" align="center" title="监测点名称" width="200px"></vxe-column>
@@ -46,6 +70,7 @@ import { ref, watch, onMounted, onUnmounted, provide } from 'vue'
import Table from '@/components/table/index.vue'
import TableStore from '@/utils/tableStore'
import { mainHeight } from '@/utils/layout'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { Sort } from '@element-plus/icons-vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { audit, add, coFqueryPage, getByUserId } from '@/api/cs-harmonic-boot/mxgraph'
@@ -159,7 +184,6 @@ const info = async () => {
pageSize: 1000
}).then(res => {
bindId.value = res.data.records.filter(item => item.scope == 1)[0]?.id || null
})
})
await setTimeout(() => {

View File

@@ -15,7 +15,7 @@
<el-button type="primary" @click="onSubmitadd" icon="el-icon-Plus">新增</el-button>
</template>
</TableHeader>
<!-- <Table ref="tableRef" /> -->
<div
style="overflow-x: hidden; overflow-y: scroll; padding: 0 10px"
v-loading="tableStore.table.loading"

View File

@@ -1,6 +1,6 @@
<template>
<div class="dictiontary-list-detail child-router">
<TableHeader>
<TableHeader showCustomColumn>
<template #select>
<el-form-item label="">
<!-- <el-page-header @back="$emit('close')">

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main" style="position: relative">
<TableHeader>
<TableHeader showCustomColumn>
<template #select>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"
@@ -32,7 +32,7 @@ defineOptions({
})
const popupEditRef = ref()
const detail = ref<anyObj | null>(null)
const tableStore = new TableStore({
const tableStore: any = new TableStore({
url: '/system-boot/dictType/list',
method: 'POST',
column: [

View File

@@ -1,10 +1,11 @@
<template>
<div class="default-main">
<TableHeader :showReset="false">
<TableHeader :showReset="false" showCustomColumn>
<template #select>
<el-radio-group v-model.trim="tableStore.table.params.versionType" @change="tableStore.index()">
<el-radio-button label="web" value="WEB" />
<el-radio-button label="app" value="APP" />
</el-radio-group>
</template>
<template #operation>
@@ -13,20 +14,38 @@
</TableHeader>
<Table ref="tableRef">
<template v-slot:columns>
<vxe-column field="androidPath" title="Android路径" minWidth="250px"
v-if="tableStore.table.params.versionType == 'APP'"></vxe-column>
<vxe-column field="iosPath" title="IOS路径" minWidth="250px"
v-if="tableStore.table.params.versionType == 'APP'"></vxe-column>
<vxe-column
field="androidPath"
title="Android路径"
minWidth="250px"
v-if="tableStore.table.params.versionType == 'APP'"
></vxe-column>
<vxe-column
field="iosPath"
title="IOS路径"
minWidth="250px"
v-if="tableStore.table.params.versionType == 'APP'"
></vxe-column>
</template>
</Table>
<el-dialog width="500px" v-model.trim="dialogVisible" :title="dialogTitle">
<el-form :inline="false" :model="form" ref="formRef" label-width="auto" class="form-one" :rules="rules">
<el-form-item label="版本号" prop="appVersion">
<el-input maxlength="32" show-word-limit v-model.trim="form.appVersion" placeholder="请输入版本号" />
<el-input
maxlength="32"
show-word-limit
v-model.trim="form.appVersion"
placeholder="请输入版本号"
/>
</el-form-item>
<el-form-item label="整改内容">
<el-input show-word-limit maxlength="300" type="textarea" v-model.trim="form.content"
placeholder="请输入整改内容" />
<el-input
show-word-limit
maxlength="300"
type="textarea"
v-model.trim="form.content"
placeholder="请输入整改内容"
/>
</el-form-item>
<el-form-item label="发布类型">
<el-select v-model.trim="form.sev" placeholder="请选择发布类型">
@@ -83,7 +102,7 @@ const rules = {
iosPath: [{ required: true, message: '请输入IOS路径', trigger: 'blur' }]
}
const formRef = ref()
const tableStore = new TableStore({
const tableStore: any = new TableStore({
url: '/cs-system-boot/appVersion/getAllData',
method: 'POST',
showPage: false,
@@ -123,7 +142,7 @@ const tableStore = new TableStore({
click: row => {
editMenu(row)
}
},
}
// {
// name: 'del',
// title: '删除',
@@ -201,3 +220,7 @@ const editMenu = (row: any) => {
form.value.iosPath = row.iosPath || ''
}
</script>
<style scoped lang="scss">
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div class="default-main">
<div v-show="show && lookShow">
<TableHeader ref="TableHeaderRef">
<TableHeader ref="TableHeaderRef" showCustomColumn>
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template>
@@ -39,6 +39,13 @@ const tableStore: any = new TableStore({
method: 'POST',
isWebPaging: true,
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'name', title: '模板名称' },
{ field: 'createBy', title: '创建用户' },
{ field: 'updateBy', title: '更新用户' },

View File

@@ -105,12 +105,12 @@ const tableStore: any = new TableStore({
onChangeField: (row: any, value: any) => {
if (row.jobStatus == 1) {
stop({ id: row.id }).then(res => {
ElMessage.success(res.message)
ElMessage.success((res as any).message)
tableStore.index()
})
} else {
start({ id: row.id }).then(res => {
ElMessage.success(res.message)
ElMessage.success((res as any).message)
tableStore.index()
})
}

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader select ref="TableHeaderRef">
<TableHeader select ref="TableHeaderRef" showCustomColumn>
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template>

View File

@@ -2,7 +2,7 @@
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"suppressImplicitAnyIndexErrors": true,
// "suppressImplicitAnyIndexErrors": true,
"module": "esnext",
"moduleResolution": "node",
"removeComments": false,

1
types/table.d.ts vendored
View File

@@ -7,6 +7,7 @@ import { Mutable } from 'element-plus/es/utils'
declare global {
interface CnTable {
ref: VxeTableInstance | null
customColumnInHeader: boolean
data: TableRow[] | any
allData: TableRow[] | any
copyData: TableRow[] | any

View File

@@ -26,8 +26,8 @@ export default defineConfig({
// target: 'http://192.168.1.24:10215', //
// target: 'http://192.168.1.122:10215', //gfh
// target: 'http://192.168.1.127:10215', //cdf
// target: 'http://192.168.1.125:10215',
target: 'http://192.168.1.103:10215',
// target: 'http://pqmcn.com:27707/api',
// target: 'https://pqmcn.com:8092/api', //治理
// target:'http://www.zhilitest.com:8089/api',
changeOrigin: true,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long