修改测试问题
This commit is contained in:
@@ -25,7 +25,6 @@ export function objTree() {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//云设备录入树
|
||||
export function getCldTree() {
|
||||
return createAxios({
|
||||
@@ -40,4 +39,11 @@ export function lineTree() {
|
||||
method: 'POST'
|
||||
})
|
||||
}
|
||||
|
||||
//APF报表树
|
||||
export function getUserDevTree(data) {
|
||||
return createAxios({
|
||||
url: '/cs-harmonic-boot/pqSensitiveUser/getUserDevTree',
|
||||
method: 'POST',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export const editEquipmentDelivery = (data: any) => {
|
||||
return createAxios({
|
||||
url: '/cs-device-boot/EquipmentDelivery/updateEquipmentDelivery',
|
||||
method: 'POST',
|
||||
data: data
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -106,9 +106,9 @@ const tableStore: any = new TableStore({
|
||||
text: `F47曲线`
|
||||
},
|
||||
legend: {
|
||||
data: ['可容忍事件', '不可容忍事件'],
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
data: ['分割线', '可容忍事件', '不可容忍事件'],
|
||||
// itemWidth: 10,
|
||||
// itemHeight: 10,
|
||||
itemGap: 15
|
||||
},
|
||||
tooltip: {
|
||||
@@ -132,9 +132,14 @@ const tableStore: any = new TableStore({
|
||||
formatter: function (a: any) {
|
||||
var relVal = `<strong>${a.seriesName}</strong><br/>`
|
||||
|
||||
relVal += "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>持续时间:" + a.value[0] + 's</font><br/>'
|
||||
relVal += "<font style='color:" + "'>特征幅值:" + Math.floor(a.value[1] * 100) / 100 + '%</font>'
|
||||
relVal += "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>特征幅值:" + Math.floor(a.value[1] * 100) / 100 + '%</font><br/>'
|
||||
relVal += "<font style='color:" + "'>持续时间:" + a.value[0] + 's</font><br/>'
|
||||
relVal += "<font style='color:" + "'>监测点名称:" + (a.value[4] || '/') + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>设备名称:" + (a.value[5] || '/') + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>项目名称:" + (a.value[6] || '/') + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>工程名称:" + (a.value[7] || '/') + '</font>'
|
||||
|
||||
return relVal
|
||||
}
|
||||
},
|
||||
@@ -171,7 +176,7 @@ const tableStore: any = new TableStore({
|
||||
dataZoom: null,
|
||||
series: [
|
||||
{
|
||||
name: '边界线',
|
||||
name: '分割线',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.05, 0],
|
||||
@@ -184,6 +189,7 @@ const tableStore: any = new TableStore({
|
||||
[1000, 80]
|
||||
],
|
||||
showSymbol: false,
|
||||
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
@@ -268,8 +274,11 @@ function gongfunction(arr: any) {
|
||||
let time = arr[i].time
|
||||
let eventId = arr[i].eventId
|
||||
let lineName = arr[i].lineName
|
||||
let equipmentName = arr[i].equipmentName
|
||||
let projectName = arr[i].projectName
|
||||
let engineeringName = arr[i].engineeringName
|
||||
// let index =arr[i].eventDetailIndex;
|
||||
point = [xx, yy, time, eventId, lineName]
|
||||
point = [xx, yy, time, eventId, lineName, equipmentName, projectName, engineeringName]
|
||||
|
||||
if (xx <= 0.003) {
|
||||
let line = 0
|
||||
|
||||
439
src/components/cockpit/ITICurve/index.vue
Normal file
439
src/components/cockpit/ITICurve/index.vue
Normal file
@@ -0,0 +1,439 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--ITIC曲线 -->
|
||||
<TableHeader ref="TableHeaderRef" :showReset="false" :timeKeyList="prop.timeKey" @selectChange="selectChange"
|
||||
datePicker v-if="fullscreen"></TableHeader>
|
||||
<el-descriptions class="mt2" direction="vertical" :column="4" border>
|
||||
<el-descriptions-item align="center" label="名称">{{ data.name }}</el-descriptions-item>
|
||||
<el-descriptions-item align="center" label="事件总数">{{ data.gs }}</el-descriptions-item>
|
||||
<el-descriptions-item align="center" label="可容忍">{{ data.krr }}</el-descriptions-item>
|
||||
<el-descriptions-item align="center" label="不可容忍">{{ data.bkrr }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<my-echart v-loading="tableStore.table.loading" ref="chartRef" class="tall" :options="echartList" :style="{
|
||||
width: prop.width,
|
||||
height: `calc(${prop.height} - 80px - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}" @chart-click="handleChartClick" />
|
||||
<el-dialog v-model="isWaveCharts" v-if="isWaveCharts" draggable :title="dialogTitle" append-to-body width="70%">
|
||||
<waveFormAnalysis v-loading="loading" ref="waveFormAnalysisRef" @handleHideCharts="isWaveCharts = false"
|
||||
:wp="wp" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, reactive, watch, computed, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { analyseWave } from '@/api/common'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getTime } from '@/utils/formatTime'
|
||||
|
||||
const prop = defineProps({
|
||||
w: { type: [String, Number] },
|
||||
h: { type: [String, Number] },
|
||||
width: { type: [String, Number] },
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
})
|
||||
|
||||
const TableHeaderRef = ref()
|
||||
|
||||
const headerHeight = ref(57)
|
||||
|
||||
const dialogTitle = ref('波形分析')
|
||||
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
|
||||
headerHeight.value = height
|
||||
|
||||
if (datePickerValue && datePickerValue.timeValue) {
|
||||
// 更新时间参数
|
||||
tableStore.table.params.searchBeginTime = datePickerValue.timeValue[0]
|
||||
tableStore.table.params.searchEndTime = datePickerValue.timeValue[1]
|
||||
}
|
||||
}
|
||||
|
||||
// 计算是否全屏展示
|
||||
const fullscreen = computed(() => {
|
||||
const w = Number(prop.w)
|
||||
const h = Number(prop.h)
|
||||
if (!isNaN(w) && !isNaN(h) && w === 12 && h === 6) {
|
||||
// 执行相应逻辑
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
const echartList = ref()
|
||||
|
||||
const chartRef = ref()
|
||||
// 波形
|
||||
const isWaveCharts = ref(false)
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const wp = ref({})
|
||||
|
||||
const boxoList: any = ref({})
|
||||
|
||||
const waveFormAnalysisRef: any = ref(null)
|
||||
|
||||
const data = reactive({
|
||||
name: '事件个数',
|
||||
gs: 0,
|
||||
krr: 0,
|
||||
bkrr: 0
|
||||
})
|
||||
const tableStore: any = new TableStore({
|
||||
url: '/cs-harmonic-boot/csevent/f47Curve',
|
||||
method: 'POST',
|
||||
|
||||
showPage: false,
|
||||
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
setTime()
|
||||
},
|
||||
loadCallback: () => {
|
||||
const gongData = gongfunction(tableStore.table.data)
|
||||
data.gs = tableStore.table.data.length
|
||||
data.krr = gongData.pointI.length
|
||||
data.bkrr = gongData.pointIun.length
|
||||
echartList.value = {
|
||||
title: {
|
||||
text: `ITIC曲线`
|
||||
},
|
||||
legend: {
|
||||
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
|
||||
// itemWidth: 10,
|
||||
// itemHeight: 10,
|
||||
itemGap: 15
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
show: true,
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
label: {
|
||||
color: '#fff',
|
||||
fontSize: 16
|
||||
}
|
||||
},
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontStyle: 'normal',
|
||||
opacity: 0.35,
|
||||
fontSize: 14
|
||||
},
|
||||
backgroundColor: 'rgba(0,0,0,0.55)',
|
||||
borderWidth: 0,
|
||||
formatter: function (a: any) {
|
||||
var relVal = `<strong>${a.seriesName}</strong><br/>`
|
||||
|
||||
relVal += "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>特征幅值:" + Math.floor(a.value[1] * 100) / 100 + '%</font><br/>'
|
||||
relVal += "<font style='color:" + "'>持续时间:" + a.value[0] + 's</font><br/>'
|
||||
relVal += "<font style='color:" + "'>监测点名称:" + (a.value[4] || '/') + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>设备名称:" + (a.value[5] || '/') + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>项目名称:" + (a.value[6] || '/') + '</font><br/>'
|
||||
relVal += "<font style='color:" + "'>工程名称:" + (a.value[7] || '/') + '</font>'
|
||||
|
||||
return relVal
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: [
|
||||
{
|
||||
type: 'log',
|
||||
min: 0.001,
|
||||
max: 1000,
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
name: 's'
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
splitNumber: 10,
|
||||
minInterval: 3,
|
||||
name: '%'
|
||||
}
|
||||
],
|
||||
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
|
||||
options: {
|
||||
dataZoom: null,
|
||||
series: [
|
||||
{
|
||||
name: '上限',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.001, 200],
|
||||
[0.003, 140],
|
||||
[0.003, 120],
|
||||
[0.5, 120],
|
||||
[0.5, 110],
|
||||
[10, 110],
|
||||
[1000, 110]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '下限',
|
||||
type: 'line',
|
||||
data: [
|
||||
[0.02, 0],
|
||||
[0.02, 70],
|
||||
[0.5, 70],
|
||||
[0.5, 80],
|
||||
[10, 80],
|
||||
[10, 90],
|
||||
[1000, 90]
|
||||
],
|
||||
showSymbol: false,
|
||||
tooltips: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
symbolSize: 8,
|
||||
data: gongData.pointI,
|
||||
legendSymbol: 'circle'
|
||||
},
|
||||
{
|
||||
name: '不可容忍事件',
|
||||
type: 'scatter',
|
||||
symbol: 'circle',
|
||||
symbolSize: 8,
|
||||
data: gongData.pointIun,
|
||||
legendSymbol: 'rect'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const tableRef = ref()
|
||||
provide('tableRef', tableRef)
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
const setTime = () => {
|
||||
const time = getTime(
|
||||
(TableHeaderRef.value?.datePickerRef.interval || prop.interval) ?? 0,
|
||||
prop.timeKey,
|
||||
fullscreen.value
|
||||
? [tableStore.table.params.searchBeginTime, tableStore.table.params.searchEndTime]
|
||||
: prop.timeValue
|
||||
)
|
||||
|
||||
if (Array.isArray(time)) {
|
||||
tableStore.table.params.searchBeginTime = time[0]
|
||||
tableStore.table.params.searchEndTime = time[1]
|
||||
TableHeaderRef.value?.setInterval(time[2] - 0)
|
||||
TableHeaderRef.value?.setTimeInterval([time[0], time[1]])
|
||||
} else {
|
||||
console.warn('获取时间失败,time 不是一个有效数组')
|
||||
}
|
||||
}
|
||||
|
||||
function gongfunction(arr: any) {
|
||||
let standI = 0
|
||||
let unstandI = 0
|
||||
let pointIun: any[] = []
|
||||
let pointI: any[] = []
|
||||
const total = arr.length
|
||||
|
||||
if (total > 0) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const xx = arr[i].persistTime
|
||||
const yy = arr[i].eventValue
|
||||
const time = arr[i].time
|
||||
const eventId = arr[i].eventId
|
||||
const lineName = arr[i].lineName
|
||||
let equipmentName = arr[i].equipmentName
|
||||
let projectName = arr[i].projectName
|
||||
let engineeringName = arr[i].engineeringName
|
||||
// let index =arr[i].eventDetailIndex;
|
||||
const point = [xx, yy, time, eventId, lineName, equipmentName, projectName, engineeringName]
|
||||
|
||||
if (xx <= 0.003) {
|
||||
const line = 230 - 30000 * xx
|
||||
if (yy > line) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.02) {
|
||||
if (yy > 120) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 0.5) {
|
||||
if (yy > 120 || yy < 70) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else if (xx <= 10) {
|
||||
if (yy > 110 || yy < 80) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (yy > 110 || yy < 90) {
|
||||
unstandI++
|
||||
pointIun.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'red' } }
|
||||
})
|
||||
} else {
|
||||
standI++
|
||||
pointI.push({
|
||||
value: point,
|
||||
itemStyle: { normal: { color: 'green' } }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
standI,
|
||||
unstandI,
|
||||
pointI,
|
||||
pointIun
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 100)
|
||||
})
|
||||
|
||||
// 点击事件处理函数
|
||||
const handleChartClick = (params: any) => {
|
||||
if (params.seriesName === '可容忍事件') {
|
||||
// 处理可容忍事件点击
|
||||
dialogTitle.value = '可容忍事件波形分析'
|
||||
handleTolerableEventClick(params)
|
||||
} else if (params.seriesName === '不可容忍事件') {
|
||||
dialogTitle.value = '不可容忍事件波形分析'
|
||||
// 处理不可容忍事件点击
|
||||
// ElMessage.info(`点击了不可容忍事件: 持续时间${params.value[0]}s, 幅值${params.value[1].toFixed(2)}%`)
|
||||
handleTolerableEventClick(params)
|
||||
}
|
||||
}
|
||||
|
||||
// 可容忍事件点击处理函数
|
||||
const handleTolerableEventClick = async (row: any) => {
|
||||
loading.value = true
|
||||
nextTick(() => {
|
||||
if (waveFormAnalysisRef.value) {
|
||||
//waveFormAnalysisRef.value.setHeight(false, 360)
|
||||
// waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
|
||||
}
|
||||
})
|
||||
const messageInstance = ElMessage.info(`正在加载,请稍等...`)
|
||||
await analyseWave(row.value[3]) //eventId
|
||||
.then(res => {
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
boxoList.value = {
|
||||
persistTime: row.value[0], //持续时间
|
||||
featureAmplitude: (row.value[1] / 100), //残余电压
|
||||
startTime: row.value[2], //时间
|
||||
lineName: row.value[4] //监测点名称
|
||||
}
|
||||
boxoList.value.systemType = 'YPT'
|
||||
wp.value = res.data
|
||||
}
|
||||
|
||||
isWaveCharts.value = true
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
messageInstance.close()
|
||||
row.loading1 = false
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
nextTick(() => {
|
||||
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
|
||||
waveFormAnalysisRef.value && waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
|
||||
})
|
||||
}
|
||||
|
||||
// 不可容忍事件点击处理函数
|
||||
const handleIntolerableEventClick = (params: any) => {
|
||||
console.log('不可容忍事件详情:', params)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => prop.timeKey,
|
||||
val => {
|
||||
tableStore.index()
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.timeValue,
|
||||
(newVal, oldVal) => {
|
||||
// 当外部时间值变化时,更新表格的时间参数
|
||||
if (newVal && (!oldVal || newVal[0] !== oldVal[0] || newVal[1] !== oldVal[1])) {
|
||||
tableStore.table.params.searchBeginTime = newVal[0]
|
||||
tableStore.table.params.searchEndTime = newVal[1]
|
||||
tableStore.index()
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -1,20 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--暂降方向统计 -->
|
||||
<TableHeader
|
||||
ref="TableHeaderRef"
|
||||
:showReset="false"
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
:timeKeyList="prop.timeKey"
|
||||
v-if="fullscreen"
|
||||
></TableHeader>
|
||||
<my-echart
|
||||
v-loading="tableStore.table.loading"
|
||||
class="tall"
|
||||
:options="echartList"
|
||||
:style="{ width: prop.width, height: `calc(${prop.height} )` }"
|
||||
/>
|
||||
<TableHeader ref="TableHeaderRef" :showReset="false" @selectChange="selectChange" datePicker
|
||||
:timeKeyList="prop.timeKey" v-if="fullscreen"></TableHeader>
|
||||
<my-echart v-loading="tableStore.table.loading" class="tall" :options="echartList"
|
||||
:style="{ width: prop.width, height: `calc(${prop.height} )` }" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -126,7 +116,11 @@ const tableStore: any = new TableStore({
|
||||
title: [
|
||||
{
|
||||
text: '暂降方向统计',
|
||||
left: 'center'
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
fontSize: '15'
|
||||
},
|
||||
},
|
||||
{
|
||||
text: total + '次',
|
||||
@@ -205,6 +199,6 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -81,51 +81,68 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '指标名称',
|
||||
field: 'name',
|
||||
minWidth: '90'
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: '越限最高监测点',
|
||||
field: 'lineName',
|
||||
minWidth: 120,
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '设备名称', field: 'devName', minWidth: 130, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '项目名称', field: 'projectName', minWidth: 130, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: '越限最大值',
|
||||
field: 'maxValue',
|
||||
minWidth: '70',
|
||||
minWidth: 100,
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
const extentValue =
|
||||
row.maxValue !== null && row.maxValue !== undefined && row.maxValue !== ''
|
||||
? Math.floor(row.maxValue * 100) / 100
|
||||
: '/'
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${extentValue}</span>`
|
||||
return extentValue=='/' ? '/' : `<span style='cursor: pointer;text-decoration: underline;'>${extentValue}</span>`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '国标限值',
|
||||
field: 'internationalValue',
|
||||
minWidth: '60'
|
||||
minWidth: 100, formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '越限程度(%)',
|
||||
field: 'extent',
|
||||
minWidth: '70',
|
||||
minWidth: 100,
|
||||
formatter: (row: any) => {
|
||||
return Math.floor(row.cellValue * 100) / 100
|
||||
return row.cellValue? Math.floor(row.cellValue * 100) / 100 : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '越限时间',
|
||||
field: 'time',
|
||||
minWidth: '60',
|
||||
minWidth: 100,
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '越限最高监测点',
|
||||
field: 'lineName',
|
||||
minWidth: '90',
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
setTime()
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="device-control">
|
||||
<!--治理效果报表 -->
|
||||
<div v-show="fullscreen">
|
||||
<!-- <PointTree :height="flag ? 106 : 50" @node-click="nodeClick" @pointTypeChange="pointTypeChange"></PointTree> -->
|
||||
<APFTree :height="flag ? 126 : 70" @node-click="handleNodeClick" template @init="handleNodeClick"></APFTree>
|
||||
</div>
|
||||
<div>
|
||||
<TableHeader :showReset="false" :timeKeyList="prop.timeKey" ref="TableHeaderRef" datePicker
|
||||
@selectChange="selectChange" v-if="fullscreen">
|
||||
<template v-slot:select>
|
||||
@@ -10,25 +15,31 @@
|
||||
:value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="监测对象">
|
||||
<!-- <el-form-item label="监测对象">
|
||||
<el-select filterable v-model="tableStore.table.params.sensitiveUserId" placeholder="请选择监测对象"
|
||||
clearable>
|
||||
<el-option v-for="item in idList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
|
||||
<div style="display: flex" >
|
||||
<div style="display: flex">
|
||||
<div id="luckysheet" :style="{
|
||||
width: `calc(${prop.width} )`,
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - 57px + ${fullscreen ? 0 : 56}px)`
|
||||
}"></div>
|
||||
}" v-if="tableStore.table.data.length"></div>
|
||||
<el-empty description="暂无报表" v-else style="flex: 1" :style="{
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - 57px + ${fullscreen ? 0 : 56}px)`
|
||||
}"></el-empty>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, provide, reactive, watch, h, computed, nextTick } from 'vue'
|
||||
@@ -40,6 +51,7 @@ import { querySysExcel } from '@/api/harmonic-boot/luckyexcel'
|
||||
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { getTime } from '@/utils/formatTime'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import APFTree from '@/components/tree/govern/APFTree.vue'
|
||||
const prop = defineProps({
|
||||
w: { type: [String, Number] },
|
||||
h: { type: [String, Number] },
|
||||
@@ -47,39 +59,38 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
|
||||
const TableHeaderRef = ref()
|
||||
|
||||
// 报表模板列表
|
||||
const templateList = ref()
|
||||
const templateList = ref([])
|
||||
|
||||
// 监测对象
|
||||
const idList = ref()
|
||||
|
||||
// 监测对象
|
||||
const initListByIds = () => {
|
||||
getListByIds({}).then((res: any) => {
|
||||
if (res.data?.length > 0) {
|
||||
idList.value = res.data
|
||||
|
||||
if (!tableStore.table.params.sensitiveUserId && idList.value?.length > 0) {
|
||||
tableStore.table.params.sensitiveUserId = idList.value[0].id
|
||||
}
|
||||
templateListData()
|
||||
} else {
|
||||
querySysExcel({}).then(res => {
|
||||
const handleNodeClick = async (data: any) => {
|
||||
if (templateList.value.length == 0) {
|
||||
await querySysExcel({}).then(res => {
|
||||
templateList.value = res.data.filter(item => item.excelType == 4)
|
||||
if (!tableStore.table.params.tempId && templateList.value?.length > 0) {
|
||||
tableStore.table.params.tempId = templateList.value[0].id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (data?.level == 3 || data?.level == 2) {
|
||||
tableStore.table.params.sensitiveUserId = data.id
|
||||
await tableStore.index()
|
||||
} else {
|
||||
tableStore.table.loading = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const templateListData = () => {
|
||||
querySysExcel({}).then(res => {
|
||||
templateList.value = res.data.filter(item => item.excelType == 4)
|
||||
@@ -98,7 +109,7 @@ const downloadExcel = () => {
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
initListByIds()
|
||||
// initListByIds()
|
||||
})
|
||||
onUnmounted(() => {
|
||||
destroyLuckysheet()
|
||||
@@ -199,4 +210,11 @@ watch(
|
||||
// :deep(.el-select) {
|
||||
// min-width: 80px;
|
||||
// }
|
||||
.device-control {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:deep(.cn-tree) {
|
||||
padding: 0 10px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog draggable title="趋势图" v-model="dialogVisible" append-to-body width="70%">
|
||||
<el-dialog draggable :title="dialogTitle" v-model="dialogVisible" append-to-body width="70%">
|
||||
<!-- 总体指标占比详情谐波含有率 -->
|
||||
<div>
|
||||
<TableHeader ref="tableHeaderRef" :showSearch="false" @selectChange="selectChange">
|
||||
@@ -8,22 +8,10 @@
|
||||
<DatePicker ref="datePickerRef"></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计指标" label-width="80px">
|
||||
<el-select
|
||||
multiple
|
||||
:multiple-limit="2"
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
v-model="searchForm.index"
|
||||
placeholder="请选择统计指标"
|
||||
@change="onIndexChange($event)"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in indexOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
<el-select multiple :multiple-limit="2" collapse-tags collapse-tags-tooltip
|
||||
v-model="searchForm.index" placeholder="请选择统计指标" @change="onIndexChange($event)" filterable>
|
||||
<el-option v-for="item in indexOptions" :key="item.id" :label="item.name"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -33,12 +21,8 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
style="min-width: 90px !important"
|
||||
placeholder="请选择"
|
||||
v-model="searchForm.valueType"
|
||||
filterable
|
||||
>
|
||||
<el-select style="min-width: 90px !important" placeholder="请选择" v-model="searchForm.valueType"
|
||||
filterable>
|
||||
<el-option value="max" label="最大值"></el-option>
|
||||
<el-option value="min" label="最小值"></el-option>
|
||||
<el-option value="avg" label="平均值"></el-option>
|
||||
@@ -46,29 +30,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div
|
||||
class="history_count"
|
||||
v-for="(item, index) in countData"
|
||||
:key="index"
|
||||
v-show="item.countOptions.length != 0"
|
||||
>
|
||||
<div class="history_count" v-for="(item, index) in countData" :key="index"
|
||||
v-show="item.countOptions.length != 0">
|
||||
<span class="mr12">
|
||||
{{ item.name.includes('次数') ? item.name : item.name + '谐波次数' }}
|
||||
</span>
|
||||
<el-select
|
||||
v-model="item.count"
|
||||
@change="onCountChange($event, index)"
|
||||
placeholder="请选择谐波次数"
|
||||
style="width: 100px"
|
||||
class="mr20"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="vv in item.countOptions"
|
||||
:key="vv"
|
||||
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
|
||||
:value="vv"
|
||||
></el-option>
|
||||
<el-select v-model="item.count" @change="onCountChange($event, index)" placeholder="请选择谐波次数"
|
||||
style="width: 100px" class="mr20" filterable>
|
||||
<el-option v-for="vv in item.countOptions" :key="vv"
|
||||
:label="item.name.includes('间谐波') ? vv - 0.5 : vv" :value="vv"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -109,6 +79,7 @@ const props = defineProps({
|
||||
type: Array
|
||||
}
|
||||
})
|
||||
const dialogTitle = ref('趋势图')
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
// console.log("🚀 ~ props:", props.TrendList)
|
||||
@@ -644,7 +615,7 @@ const onIndexChange = (val: any) => {
|
||||
}
|
||||
watch(
|
||||
() => searchForm.value.index,
|
||||
(val: any, oldval: any) => {},
|
||||
(val: any, oldval: any) => { },
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
@@ -652,6 +623,7 @@ watch(
|
||||
)
|
||||
|
||||
const openDialog = async (row: any, field: any, title: any) => {
|
||||
dialogTitle.value = row?.lineName + '_趋势图'
|
||||
dialogVisible.value = true
|
||||
trendRequestData.value = row
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 指标越限详情 -->
|
||||
<el-dialog draggable title="指标越限详情" v-model="dialogVisible" append-to-body width="70%">
|
||||
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<!-- <el-form-item label="监测点">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.lineId"
|
||||
placeholder="请选择监测点"
|
||||
@@ -18,7 +18,7 @@
|
||||
:value="item.lineId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent" isGroup :height="height"></Table>
|
||||
@@ -38,7 +38,7 @@ import { cslineList } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
const harmonicRatioRef: any = ref(null)
|
||||
|
||||
const title = ref('指标越限详情')
|
||||
const options = ref()
|
||||
const height = mainHeight(0, 2).height as any
|
||||
const tableHeaderRef = ref()
|
||||
@@ -76,13 +76,13 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '日期',
|
||||
field: 'time',
|
||||
width: '150',
|
||||
width: '120',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
field: 'lineName',
|
||||
width: '150'
|
||||
width: '120'
|
||||
},
|
||||
{
|
||||
title: '长时闪变越限(%)',
|
||||
@@ -143,6 +143,7 @@ tableStore.table.params.sortBy = ''
|
||||
tableStore.table.params.orderBy = ''
|
||||
const open = async (row: any,searchBeginTime:any,searchEndTime:any,interval:any,list:any) => {
|
||||
dialogVisible.value = true
|
||||
title.value = row.lineName + '_指标越限详情'
|
||||
options.value = list
|
||||
// initCSlineList()
|
||||
tableStore.table.params.lineId = row.lineId
|
||||
@@ -161,7 +162,7 @@ const open = async (row: any,searchBeginTime:any,searchEndTime:any,interval:any,
|
||||
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field != 'name' && column.field != 'time') {
|
||||
if (column.field != 'lineName' &&column.field != 'name' && column.field != 'time') {
|
||||
dialogFlag.value = true
|
||||
dialogVisible.value = false
|
||||
nextTick(() => {
|
||||
|
||||
@@ -1,28 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--电网侧指标越限统计 -->
|
||||
<TableHeader
|
||||
:showReset="false"
|
||||
ref="TableHeaderRef"
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
:timeKeyList="prop.timeKey"
|
||||
v-if="fullscreen"
|
||||
></TableHeader>
|
||||
<my-echart
|
||||
class="tall"
|
||||
:options="echartList"
|
||||
:style="{
|
||||
<TableHeader :showReset="false" ref="TableHeaderRef" @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 )`
|
||||
}"
|
||||
/>
|
||||
<Table
|
||||
ref="tableRef"
|
||||
@cell-click="cellClickEvent"
|
||||
:height="`calc(${prop.height} / 2 - ${headerHeight}px + ${fullscreen ? 0 : 56}px )`"
|
||||
isGroup
|
||||
></Table>
|
||||
}" />
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent"
|
||||
:height="`calc(${prop.height} / 2 - ${headerHeight}px + ${fullscreen ? 0 : 56}px )`" isGroup></Table>
|
||||
<!-- 指标越限详情 -->
|
||||
<OverLimitDetails ref="OverLimitDetailsRef" />
|
||||
</div>
|
||||
@@ -141,17 +127,20 @@ const tableStore: any = new TableStore({
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
minWidth: '90'
|
||||
minWidth: 120
|
||||
},
|
||||
{ title: '设备名称', field: 'devName', minWidth: 130, align: 'center', },
|
||||
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
|
||||
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
|
||||
{
|
||||
title: '越限占比(%)',
|
||||
children: [
|
||||
{
|
||||
title: '长时闪变',
|
||||
field: 'flicker',
|
||||
minWidth: '70',
|
||||
minWidth: '80',
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flicker}</span>`
|
||||
@@ -261,6 +250,6 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,46 +1,31 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="device-control">
|
||||
<!--指标越限时间分布
|
||||
-->
|
||||
<TableHeader
|
||||
:showReset="false"
|
||||
:timeKeyList="prop.timeKey"
|
||||
ref="TableHeaderRef"
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
v-if="fullscreen"
|
||||
>
|
||||
<template v-slot:select>
|
||||
<div v-show="fullscreen">
|
||||
<PointTree :height="flag ? 106 : 50" @node-click="nodeClick" @pointTypeChange="pointTypeChange"></PointTree>
|
||||
</div>
|
||||
<div>
|
||||
<TableHeader :showReset="false" :timeKeyList="prop.timeKey" ref="TableHeaderRef"
|
||||
@selectChange="selectChange" datePicker v-if="fullscreen">
|
||||
<!-- <template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<el-select size="small" filterable v-model="tableStore.table.params.lineId">
|
||||
<el-option
|
||||
v-for="item in lineList"
|
||||
:key="item.lineId"
|
||||
:label="item.name"
|
||||
:value="item.lineId"
|
||||
/>
|
||||
<el-option v-for="item in lineList" :key="item.lineId" :label="item.name"
|
||||
:value="item.lineId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template> -->
|
||||
</TableHeader>
|
||||
<div v-loading="tableStore.table.loading">
|
||||
<my-echart
|
||||
class="tall"
|
||||
v-if="lineShow"
|
||||
:options="echartList1"
|
||||
:style="{
|
||||
width: prop.width,
|
||||
<my-echart class="tall" v-if="lineShow" :options="echartList1" :style="{
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}"
|
||||
/>
|
||||
<el-empty
|
||||
v-else
|
||||
description="暂无监测点"
|
||||
:style="{
|
||||
width: prop.width,
|
||||
}" />
|
||||
<el-empty v-else description="暂无监测点" :style="{
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}"
|
||||
/>
|
||||
}" />
|
||||
<!-- <my-echart
|
||||
class="mt10"
|
||||
:options="echartList1"
|
||||
@@ -51,6 +36,7 @@
|
||||
/> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, reactive, watch, h } from 'vue'
|
||||
@@ -59,7 +45,7 @@ import TableHeader from '@/components/table/header/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { limitProbabilityData, cslineList } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { getTime } from '@/utils/formatTime'
|
||||
|
||||
import PointTree from '@/components/tree/govern/pointTree.vue'
|
||||
const prop = defineProps({
|
||||
w: { type: [String, Number] },
|
||||
h: { type: [String, Number] },
|
||||
@@ -67,7 +53,8 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
|
||||
// const options = ref(JSON.parse(window.localStorage.getItem('lineIdList') || '[]'))
|
||||
@@ -106,17 +93,28 @@ const echartList1 = ref()
|
||||
|
||||
const probabilityData = ref()
|
||||
|
||||
const initLineList = async () => {
|
||||
cslineList({}).then(res => {
|
||||
if (res.data.length == 0) {
|
||||
lineShow.value = false
|
||||
return (tableStore.table.loading = false)
|
||||
// const initLineList = async () => {
|
||||
// cslineList({}).then(res => {
|
||||
// if (res.data.length == 0) {
|
||||
// lineShow.value = false
|
||||
// return (tableStore.table.loading = false)
|
||||
// }
|
||||
// lineShow.value = true
|
||||
// lineList.value = res.data
|
||||
// tableStore.table.params.lineId = lineList.value[0].lineId
|
||||
// tableStore.index()
|
||||
// })
|
||||
// }
|
||||
const nodeClick = (e: any) => {
|
||||
if (e == undefined) {
|
||||
}
|
||||
lineShow.value = true
|
||||
lineList.value = res.data
|
||||
tableStore.table.params.lineId = lineList.value[0].lineId
|
||||
if (e.level == 3) {
|
||||
tableStore.table.params.lineId = e.id
|
||||
tableStore.index()
|
||||
})
|
||||
}
|
||||
}
|
||||
const pointTypeChange = (val: any, obj: any) => {
|
||||
nodeClick(obj)
|
||||
}
|
||||
|
||||
// 越限程度概率分布
|
||||
@@ -438,7 +436,7 @@ const tableStore: any = new TableStore({
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
initLineList()
|
||||
// initLineList()
|
||||
})
|
||||
|
||||
const setTime = () => {
|
||||
@@ -475,6 +473,14 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.device-control {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:deep(.cn-tree) {
|
||||
padding: 0 10px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,45 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="device-control">
|
||||
<!--指标越限概率分布 -->
|
||||
<TableHeader
|
||||
:showReset="false"
|
||||
:timeKeyList="prop.timeKey"
|
||||
ref="TableHeaderRef"
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
v-if="fullscreen"
|
||||
>
|
||||
<template v-slot:select>
|
||||
<div v-show="fullscreen">
|
||||
<PointTree :height="flag ? 106 : 50" @node-click="nodeClick" @pointTypeChange="pointTypeChange"></PointTree>
|
||||
</div>
|
||||
<div>
|
||||
<TableHeader :showReset="false" :timeKeyList="prop.timeKey" ref="TableHeaderRef"
|
||||
@selectChange="selectChange" datePicker v-if="fullscreen">
|
||||
<!-- <template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<el-select size="small" filterable v-model="tableStore.table.params.lineId">
|
||||
<el-option
|
||||
v-for="item in lineList"
|
||||
:key="item.lineId"
|
||||
:label="item.name"
|
||||
:value="item.lineId"
|
||||
/>
|
||||
<el-option v-for="item in lineList" :key="item.lineId" :label="item.name"
|
||||
:value="item.lineId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template> -->
|
||||
</TableHeader>
|
||||
<div v-loading="tableStore.table.loading">
|
||||
<my-echart
|
||||
v-if="lineShow"
|
||||
class="tall"
|
||||
:options="echartList"
|
||||
:style="{
|
||||
width: prop.width,
|
||||
<my-echart v-if="lineShow" class="tall" :options="echartList" :style="{
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}"
|
||||
/>
|
||||
<el-empty
|
||||
v-else
|
||||
description="暂无监测点"
|
||||
:style="{
|
||||
width: prop.width,
|
||||
}" />
|
||||
<el-empty v-else description="暂无监测点" :style="{
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}"
|
||||
/>
|
||||
}" />
|
||||
<!-- <my-echart
|
||||
class="mt10"
|
||||
:options="echartList1"
|
||||
@@ -50,6 +35,8 @@
|
||||
/> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, reactive, watch, h } from 'vue'
|
||||
@@ -58,7 +45,7 @@ import TableHeader from '@/components/table/header/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { limitProbabilityData, cslineList } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { getTime } from '@/utils/formatTime'
|
||||
|
||||
import PointTree from '@/components/tree/govern/pointTree.vue'
|
||||
const prop = defineProps({
|
||||
w: { type: [String, Number] },
|
||||
h: { type: [String, Number] },
|
||||
@@ -66,7 +53,8 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
const lineShow = ref(true)
|
||||
// const options = ref(JSON.parse(window.localStorage.getItem('lineIdList') || '[]'))
|
||||
@@ -105,18 +93,31 @@ const echartList1 = ref()
|
||||
|
||||
const probabilityData = ref()
|
||||
|
||||
const initLineList = async () => {
|
||||
cslineList({}).then(res => {
|
||||
if (res.data.length == 0) {
|
||||
lineShow.value = false
|
||||
return (tableStore.table.loading = false)
|
||||
// const initLineList = async () => {
|
||||
// cslineList({}).then(res => {
|
||||
// if (res.data.length == 0) {
|
||||
// lineShow.value = false
|
||||
// return (tableStore.table.loading = false)
|
||||
// }
|
||||
// lineShow.value = true
|
||||
// lineList.value = res.data
|
||||
// tableStore.table.params.lineId = lineList.value[0].lineId
|
||||
// tableStore.index()
|
||||
// })
|
||||
// }
|
||||
|
||||
const nodeClick = (e: any) => {
|
||||
if (e == undefined) {
|
||||
}
|
||||
lineShow.value = true
|
||||
lineList.value = res.data
|
||||
tableStore.table.params.lineId = lineList.value[0].lineId
|
||||
if (e.level == 3) {
|
||||
tableStore.table.params.lineId = e.id
|
||||
tableStore.index()
|
||||
})
|
||||
}
|
||||
}
|
||||
const pointTypeChange = (val: any, obj: any) => {
|
||||
nodeClick(obj)
|
||||
}
|
||||
|
||||
|
||||
// 越限程度概率分布
|
||||
const initProbabilityData = () => {
|
||||
@@ -437,7 +438,7 @@ const tableStore: any = new TableStore({
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
initLineList()
|
||||
// initLineList()
|
||||
})
|
||||
|
||||
const setTime = () => {
|
||||
@@ -474,6 +475,13 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.device-control {
|
||||
display: flex;
|
||||
}
|
||||
:deep(.cn-tree) {
|
||||
padding: 0 10px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog draggable title="趋势图" v-model="dialogVisible" append-to-body width="70%">
|
||||
<el-dialog draggable :title="dialogTitle" v-model="dialogVisible" append-to-body width="70%">
|
||||
<!-- 总体指标占比详情谐波含有率 -->
|
||||
<div>
|
||||
<TableHeader ref="tableHeaderRef" :showSearch="false" @selectChange="selectChange">
|
||||
@@ -8,22 +8,10 @@
|
||||
<DatePicker ref="datePickerRef"></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计指标" label-width="80px">
|
||||
<el-select
|
||||
multiple
|
||||
:multiple-limit="2"
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
v-model="searchForm.index"
|
||||
placeholder="请选择统计指标"
|
||||
@change="onIndexChange($event)"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in indexOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
<el-select multiple :multiple-limit="2" collapse-tags collapse-tags-tooltip
|
||||
v-model="searchForm.index" placeholder="请选择统计指标" @change="onIndexChange($event)" filterable>
|
||||
<el-option v-for="item in indexOptions" :key="item.id" :label="item.name"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -33,12 +21,8 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
style="min-width: 120px !important"
|
||||
placeholder="请选择"
|
||||
v-model="searchForm.valueType"
|
||||
filterable
|
||||
>
|
||||
<el-select style="min-width: 120px !important" placeholder="请选择" v-model="searchForm.valueType"
|
||||
filterable>
|
||||
<el-option value="max" label="最大值"></el-option>
|
||||
<el-option value="min" label="最小值"></el-option>
|
||||
<el-option value="avg" label="平均值"></el-option>
|
||||
@@ -46,29 +30,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div
|
||||
class="history_count"
|
||||
v-for="(item, index) in countData"
|
||||
:key="index"
|
||||
v-show="item.countOptions.length != 0"
|
||||
>
|
||||
<div class="history_count" v-for="(item, index) in countData" :key="index"
|
||||
v-show="item.countOptions.length != 0">
|
||||
<span class="mr12">
|
||||
{{ item.name.includes('次数') ? item.name : item.name + '谐波次数' }}
|
||||
</span>
|
||||
<el-select
|
||||
v-model="item.count"
|
||||
@change="onCountChange($event, index)"
|
||||
placeholder="请选择谐波次数"
|
||||
style="width: 100px"
|
||||
class="mr20"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="vv in item.countOptions"
|
||||
:key="vv"
|
||||
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
|
||||
:value="vv"
|
||||
></el-option>
|
||||
<el-select v-model="item.count" @change="onCountChange($event, index)" placeholder="请选择谐波次数"
|
||||
style="width: 100px" class="mr20" filterable>
|
||||
<el-option v-for="vv in item.countOptions" :key="vv"
|
||||
:label="item.name.includes('间谐波') ? vv - 0.5 : vv" :value="vv"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -109,6 +79,7 @@ const props = defineProps({
|
||||
type: Array
|
||||
}
|
||||
})
|
||||
const dialogTitle = ref('趋势图')
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
// console.log("🚀 ~ props:", props.TrendList)
|
||||
@@ -184,7 +155,7 @@ const initCode = (field: string, title: string) => {
|
||||
? '谐波电压'
|
||||
: field.includes('iharm')
|
||||
? '谐波电流'
|
||||
: field.includes('voltageDevOvertime')
|
||||
: field.includes('uaberrance')
|
||||
? '电压偏差'
|
||||
: field.includes('ubalanceOvertime')
|
||||
? '不平衡'
|
||||
@@ -643,7 +614,7 @@ const onIndexChange = (val: any) => {
|
||||
}
|
||||
watch(
|
||||
() => searchForm.value.index,
|
||||
(val: any, oldval: any) => {},
|
||||
(val: any, oldval: any) => { },
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
@@ -652,6 +623,8 @@ watch(
|
||||
|
||||
const openDialog = async (row: any, field: any, title: any) => {
|
||||
dialogVisible.value = true
|
||||
|
||||
dialogTitle.value = row?.lineName + '_趋势图'
|
||||
trendRequestData.value = row
|
||||
|
||||
nextTick(() => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 指标越限详情 -->
|
||||
<el-dialog draggable title="指标越限详情" v-model="dialogVisible" append-to-body width="70%">
|
||||
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
|
||||
<template v-slot:select>
|
||||
<!-- <template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.lineId"
|
||||
@@ -19,7 +19,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template> -->
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent" isGroup :height="height"></Table>
|
||||
</el-dialog>
|
||||
@@ -28,7 +28,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, provide,nextTick } from 'vue'
|
||||
import { ref, provide, nextTick } from 'vue'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
@@ -40,7 +40,7 @@ const dialogVisible: any = ref(false)
|
||||
const harmonicRatioRef: any = ref(null)
|
||||
|
||||
const dialogFlag = ref(false)
|
||||
|
||||
const title = ref('指标越限详情')
|
||||
const options = ref()
|
||||
const height = mainHeight(0, 2).height as any
|
||||
const tableHeaderRef = ref()
|
||||
@@ -77,18 +77,18 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '日期',
|
||||
field: 'time',
|
||||
width: '150',
|
||||
width: '120',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
width: '150'
|
||||
width: '120'
|
||||
},
|
||||
{
|
||||
title: '越限(分钟)',
|
||||
title: '长时闪变越限(分钟)',
|
||||
field: 'flickerOvertime',
|
||||
width: '90',
|
||||
width: '100',
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flickerOvertime}</span>`
|
||||
@@ -140,15 +140,17 @@ const tableStore: any = new TableStore({
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.sortBy = ''
|
||||
tableStore.table.params.orderBy = ''
|
||||
const open = async (row: any,searchBeginTime:any,searchEndTime:any,data:any=[]) => {
|
||||
const open = async (row: any, searchBeginTime: any, searchEndTime: any, data: any = []) => {
|
||||
console.log("🚀 ~ open ~ row:", row)
|
||||
dialogVisible.value = true
|
||||
// initCSlineList()
|
||||
options.value = data
|
||||
title.value = row.lineName + '_指标越限详情'
|
||||
tableStore.table.params.lineId = row.lineId
|
||||
|
||||
nextTick(() => {
|
||||
tableHeaderRef.value.setTimeInterval([searchBeginTime, searchEndTime])
|
||||
tableStore.table.params.searchBeginTime =searchBeginTime
|
||||
tableStore.table.params.searchBeginTime = searchBeginTime
|
||||
tableStore.table.params.searchEndTime = searchEndTime
|
||||
tableStore.index()
|
||||
})
|
||||
@@ -157,11 +159,11 @@ const open = async (row: any,searchBeginTime:any,searchEndTime:any,data:any=[])
|
||||
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field != 'name' && column.field != 'time') {
|
||||
if (column.field != 'lineName' && column.field != 'name' && column.field != 'time') {
|
||||
dialogFlag.value = true
|
||||
dialogVisible.value = false
|
||||
nextTick(() => {
|
||||
harmonicRatioRef.value.openDialog(row,column.field,column.title.replace(/次/g, ""))
|
||||
harmonicRatioRef.value.openDialog(row, column.field, column.title.replace(/次/g, ""))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--主要监测点列表 -->
|
||||
<TableHeader
|
||||
:showReset="false"
|
||||
:timeKeyList="prop.timeKey"
|
||||
@selectChange="selectChange"
|
||||
v-if="fullscreen"
|
||||
|
||||
ref="TableHeaderRef"
|
||||
>
|
||||
<TableHeader :showReset="false" :timeKeyList="prop.timeKey" @selectChange="selectChange" v-if="fullscreen"
|
||||
ref="TableHeaderRef">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="关键字筛选">
|
||||
<el-input maxlength="32" show-word-limit v-model="tableStore.table.params.keywords" clearable placeholder="请输入监测点名称" />
|
||||
<el-input maxlength="32" show-word-limit v-model="tableStore.table.params.keywords" 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" />
|
||||
</div>
|
||||
@@ -41,7 +33,8 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
const OverLimitDetailsRef = ref()
|
||||
const headerHeight = ref(57)
|
||||
@@ -90,17 +83,17 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
minWidth: '90',
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${row.lineName}</span>`
|
||||
}
|
||||
},
|
||||
minWidth: 120,
|
||||
|
||||
|
||||
},
|
||||
{ title: '设备名称', field: 'devName', minWidth: 130, align: 'center' },
|
||||
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
|
||||
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
|
||||
{
|
||||
title: '监测对象类型',
|
||||
field: 'objType',
|
||||
minWidth: '90',
|
||||
minWidth: '100',
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
@@ -114,7 +107,11 @@ const tableStore: any = new TableStore({
|
||||
}
|
||||
},
|
||||
|
||||
{ title: '主要存在的电能质量问题', field: 'problems', minWidth: '150', showOverflow: true }
|
||||
{
|
||||
title: '主要存在的电能质量问题', field: 'problems', minWidth: '250', render: 'customTemplate', customTemplate: (row: any) => {
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${row.problems}</span>`
|
||||
}
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
setTime()
|
||||
@@ -131,7 +128,7 @@ provide('tableStore', tableStore)
|
||||
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field == 'lineName') {
|
||||
if (column.field == 'problems') {
|
||||
|
||||
let time = getTimeOfTheMonth('3');
|
||||
OverLimitDetailsRef.value.open(
|
||||
@@ -176,7 +173,13 @@ watch(
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.flag,
|
||||
val => {
|
||||
tableStore.showPage = fullscreen.value ? true : false
|
||||
}
|
||||
)
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -220,16 +220,33 @@ const setEchart = () => {
|
||||
}
|
||||
: {}
|
||||
],
|
||||
grid: {
|
||||
left: '10px',
|
||||
right: '20px'
|
||||
},
|
||||
// grid: {
|
||||
// left: '10px',
|
||||
// right: '30px',
|
||||
// },
|
||||
options: {
|
||||
// dataZoom: [
|
||||
// {
|
||||
// type: 'inside',
|
||||
// start: 0,
|
||||
// end: 100,
|
||||
// filterMode: 'filter'
|
||||
// },
|
||||
// {
|
||||
// type: 'slider',
|
||||
// start: 0,
|
||||
// end: 100,
|
||||
// height: 13,
|
||||
// bottom: '20px',
|
||||
// filterMode: 'filter'
|
||||
// }
|
||||
// ],
|
||||
series: [
|
||||
{
|
||||
type: 'bar',
|
||||
name: powerName, // 动态设置功率名称
|
||||
data: [],
|
||||
clip: true,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: function (params: any) {
|
||||
@@ -248,7 +265,7 @@ const setEchart = () => {
|
||||
type: 'line',
|
||||
step: 'end',
|
||||
showSymbol: false,
|
||||
// smooth: true,
|
||||
clip: true,
|
||||
data: [],
|
||||
yAxisIndex: 1
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 指标越限详情 -->
|
||||
<el-dialog draggable title="指标越限详情" v-model="dialogVisible" append-to-body width="70%">
|
||||
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<!-- <el-form-item label="监测点">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.lineId"
|
||||
placeholder="请选择监测点"
|
||||
@@ -18,7 +18,7 @@
|
||||
:value="item.lineId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent" isGroup :height="height"></Table>
|
||||
@@ -38,7 +38,7 @@ import { cslineList ,governLineList} from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
const harmonicRatioRef: any = ref(null)
|
||||
|
||||
const title = ref('指标越限详情')
|
||||
const options = ref()
|
||||
const height = mainHeight(0, 2).height as any
|
||||
const tableHeaderRef = ref()
|
||||
@@ -76,13 +76,13 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '日期',
|
||||
field: 'time',
|
||||
width: '150',
|
||||
width: '120',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
field: 'lineName',
|
||||
width: '150'
|
||||
width: '120'
|
||||
},
|
||||
{
|
||||
title: '长时闪变越限(%)',
|
||||
@@ -144,6 +144,7 @@ tableStore.table.params.orderBy = ''
|
||||
const time:any=ref([])
|
||||
const open = async (row: any,searchBeginTime:any,searchEndTime:any) => {
|
||||
dialogVisible.value = true
|
||||
title.value = row.lineName + '_指标越限详情'
|
||||
time.value=[searchBeginTime,searchEndTime]
|
||||
initCSlineList()
|
||||
tableStore.table.params.lineId = row.lineId
|
||||
@@ -159,7 +160,7 @@ const open = async (row: any,searchBeginTime:any,searchEndTime:any) => {
|
||||
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field != 'name' && column.field != 'time') {
|
||||
if (column.field != 'lineName' && column.field != 'name' && column.field != 'time') {
|
||||
dialogFlag.value = true
|
||||
dialogVisible.value = false
|
||||
nextTick(() => {
|
||||
|
||||
@@ -1,55 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<!-- 监测点列表 -->
|
||||
<TableHeader
|
||||
ref="TableHeaderRef"
|
||||
:showReset="false"
|
||||
@selectChange="selectChange"
|
||||
v-if="fullscreen"
|
||||
:timeKeyList="prop.timeKey"
|
||||
>
|
||||
<TableHeader ref="TableHeaderRef" :showReset="false" @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>
|
||||
@@ -73,7 +44,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import OverLimitDetails from '@/components/cockpit/monitoringPointList/components/overLimitDetails.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { uploadReport, getReportUrl } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { getTime } from '@/utils/formatTime'
|
||||
|
||||
|
||||
const prop = defineProps({
|
||||
w: { type: [String, Number] },
|
||||
@@ -82,7 +53,8 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
|
||||
const headerHeight = ref(57)
|
||||
@@ -135,16 +107,19 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
minWidth: '120',
|
||||
minWidth: 120,
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${row.lineName}</span>`
|
||||
}
|
||||
},
|
||||
{ title: '设备名称', field: 'devName', minWidth: 130, align: 'center' },
|
||||
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
|
||||
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
|
||||
{
|
||||
title: '监测类型',
|
||||
field: 'position',
|
||||
minWidth: '80',
|
||||
minWidth: '100',
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
@@ -162,28 +137,22 @@ const tableStore: any = new TableStore({
|
||||
title: '监测点状态',
|
||||
field: 'runStatus',
|
||||
render: 'tag',
|
||||
|
||||
width: 100,
|
||||
width: 90,
|
||||
custom: {
|
||||
停运: 'danger',
|
||||
退运: 'danger',
|
||||
运行: 'success',
|
||||
在线: 'success',
|
||||
中断: 'warning',
|
||||
离线: 'danger',
|
||||
检修: 'warning',
|
||||
调试: 'warning',
|
||||
// 0:运行;1:检修;2:停运;3:调试;4:退运
|
||||
0: 'success',
|
||||
1: 'warning',
|
||||
2: 'danger',
|
||||
3: 'warning',
|
||||
4: 'info',
|
||||
null: 'info'
|
||||
},
|
||||
replaceValue: {
|
||||
运行: '运行',
|
||||
在线: '在线',
|
||||
退运: '退运',
|
||||
停运: '停运',
|
||||
中断: '中断',
|
||||
检修: '检修',
|
||||
离线: '离线',
|
||||
调试: '调试',
|
||||
0: '运行',
|
||||
1: '检修',
|
||||
2: '停运',
|
||||
3: '调试',
|
||||
4: '退运',
|
||||
null: '/'
|
||||
}
|
||||
},
|
||||
@@ -198,7 +167,7 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '治理对象',
|
||||
field: 'sensitiveUser',
|
||||
minWidth: '90',
|
||||
minWidth: '100',
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
@@ -206,7 +175,7 @@ const tableStore: any = new TableStore({
|
||||
|
||||
|
||||
{
|
||||
title: '是否治理',
|
||||
title: '治理方案',
|
||||
field: 'govern',
|
||||
minWidth: '80',
|
||||
formatter: (row: any) => {
|
||||
@@ -241,7 +210,7 @@ const tableStore: any = new TableStore({
|
||||
// }
|
||||
// },
|
||||
{
|
||||
title: '报告',
|
||||
title: '治理前报告',
|
||||
field: 'reportFilePath',
|
||||
minWidth: '150',
|
||||
formatter: (row: any) => {
|
||||
@@ -347,7 +316,7 @@ const downloadTheReport = (lineId: string, name: string) => {
|
||||
forceDownloadPdf(res.data, name.split('/').pop() || '')
|
||||
})
|
||||
}
|
||||
const forceDownloadPdf = async (pdfUrl:any, fileName = '文件.pdf') => {
|
||||
const forceDownloadPdf = async (pdfUrl: any, fileName = '文件.pdf') => {
|
||||
try {
|
||||
// 1. 请求 PDF 并转为 Blob(关键:绕开浏览器直接解析)
|
||||
const response = await fetch(pdfUrl, {
|
||||
@@ -456,6 +425,12 @@ const handleUpload = async () => {
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
watch(
|
||||
() => prop.flag,
|
||||
val => {
|
||||
tableStore.showPage = fullscreen.value ? true : false
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.timeKey,
|
||||
val => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 指标越限详情 -->
|
||||
<el-dialog draggable title="指标越限详情" v-model="dialogVisible" append-to-body width="70%">
|
||||
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<!-- <el-form-item label="监测点">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.lineId"
|
||||
placeholder="请选择监测点"
|
||||
@@ -18,7 +18,7 @@
|
||||
:value="item.lineId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent" isGroup :height="height"></Table>
|
||||
@@ -38,7 +38,7 @@ import { cslineList } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
const harmonicRatioRef: any = ref(null)
|
||||
|
||||
const title = ref('指标越限详情')
|
||||
const options = ref()
|
||||
const height = mainHeight(0, 2).height as any
|
||||
const tableHeaderRef = ref()
|
||||
@@ -76,13 +76,13 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '日期',
|
||||
field: 'time',
|
||||
width: '150',
|
||||
width: '120',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
field: 'lineName',
|
||||
width: '150'
|
||||
width: '120'
|
||||
},
|
||||
{
|
||||
title: '长时闪变越限(%)',
|
||||
@@ -144,6 +144,7 @@ tableStore.table.params.orderBy = ''
|
||||
const open = async (row: any,searchBeginTime:any,searchEndTime:any,data: any) => {
|
||||
dialogVisible.value = true
|
||||
// initCSlineList()
|
||||
title.value = row.lineName + '_指标越限详情'
|
||||
options.value = data
|
||||
tableStore.table.params.lineId = row.lineId
|
||||
|
||||
@@ -158,7 +159,7 @@ const open = async (row: any,searchBeginTime:any,searchEndTime:any,data: any) =>
|
||||
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field != 'name' && column.field != 'time') {
|
||||
if (column.field != 'lineName' && column.field != 'name' && column.field != 'time') {
|
||||
dialogFlag.value = true
|
||||
dialogVisible.value = false
|
||||
nextTick(() => {
|
||||
|
||||
@@ -142,17 +142,20 @@ const tableStore: any = new TableStore({
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
minWidth: '90'
|
||||
minWidth: 120
|
||||
},
|
||||
{ title: '设备名称', field: 'devName', minWidth: 130, align: 'center' },
|
||||
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
|
||||
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
|
||||
{
|
||||
title: '越限占比(%)',
|
||||
children: [
|
||||
{
|
||||
title: '长时闪变',
|
||||
field: 'flicker',
|
||||
minWidth: '70',
|
||||
minWidth: '80',
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
return `<span style='cursor: pointer;text-decoration: underline;'>${row.flicker}</span>`
|
||||
|
||||
@@ -1,32 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--敏感负荷列表 -->
|
||||
<TableHeader
|
||||
ref="TableHeaderRef"
|
||||
:showReset="false"
|
||||
@selectChange="selectChange"
|
||||
v-if="fullscreen"
|
||||
:timeKeyList="prop.timeKey"
|
||||
>
|
||||
<TableHeader ref="TableHeaderRef" :showReset="false" @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 )`"
|
||||
isGroup
|
||||
></Table>
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent"
|
||||
:height="`calc(${prop.height} - ${headerHeight}px + ${fullscreen ? -58 : 56}px )`" isGroup></Table>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -44,7 +29,8 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
|
||||
const headerHeight = ref(57)
|
||||
@@ -91,13 +77,13 @@ const tableStore: any = new TableStore({
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '敏感负荷名称',
|
||||
title: '敏感用户名称',
|
||||
field: 'name',
|
||||
minWidth: '90'
|
||||
},
|
||||
|
||||
{
|
||||
title: '敏感负荷类型',
|
||||
title: '敏感用户类型',
|
||||
field: 'loadType',
|
||||
minWidth: '70',
|
||||
formatter: row => {
|
||||
@@ -125,7 +111,7 @@ const tableStore: any = new TableStore({
|
||||
setTime()
|
||||
},
|
||||
|
||||
loadCallback: () => {}
|
||||
loadCallback: () => { }
|
||||
})
|
||||
tableStore.table.params.searchValue = ''
|
||||
const tableRef = ref()
|
||||
@@ -179,5 +165,11 @@ watch(
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.flag,
|
||||
val => {
|
||||
tableStore.showPage = fullscreen.value ? true : false
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,203 +1,155 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 暂态事件详情 -->
|
||||
<el-dialog draggable title="暂态事件详情 " v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef" @selectChange="selectChange">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="监测点" v-if="props.showLine">
|
||||
<el-select v-model="tableStore.table.params.lineId" filterable placeholder="请选择监测点名称">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="暂态类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.eventType"
|
||||
style="min-width: 150px"
|
||||
clearable
|
||||
placeholder="请选择暂态类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in eventList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-dialog draggable title="暂态事件" v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport ref="tableHeaderRef" @selectChange="selectChange"
|
||||
@onResetForm="onResetForm">
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
|
||||
<MultiCondition v-model:visible="filterVisible" :params="tableStore.table.params" ref="multiConditionRef"
|
||||
@confirm="onFilterConfirm" />
|
||||
|
||||
<Table ref="tableRef" isGroup :height="heightRef"></Table>
|
||||
</el-dialog>
|
||||
<!-- 查看波形 -->
|
||||
<el-dialog
|
||||
v-model="isWaveCharts"
|
||||
draggable
|
||||
title="波形分析"
|
||||
append-to-body
|
||||
v-if="isWaveCharts"
|
||||
width="70%"
|
||||
@close="handleHideCharts"
|
||||
>
|
||||
<waveFormAnalysis
|
||||
v-loading="loading"
|
||||
ref="waveFormAnalysisRef"
|
||||
@handleHideCharts="handleHideCharts"
|
||||
:wp="wp"
|
||||
/>
|
||||
|
||||
<el-dialog v-model="isWaveCharts" draggable title="波形分析" append-to-body width="70%" @close="handleHideCharts">
|
||||
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
|
||||
@handleHideCharts="handleHideCharts" :wp="wp" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, provide } from 'vue'
|
||||
import { ref, provide, nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import MultiCondition from '@/views/govern/alarm/multiCondition.vue'
|
||||
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
|
||||
import { analyseWave } from '@/api/common'
|
||||
import { getSimpleLine } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
interface Props {
|
||||
showLine?: boolean
|
||||
}
|
||||
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showLine: true
|
||||
})
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
const waveFormAnalysisRef: any = ref(null)
|
||||
// 波形
|
||||
const dialogVisible = ref(false)
|
||||
const waveFormAnalysisRef = ref()
|
||||
const isWaveCharts = ref(false)
|
||||
const loading = ref(false)
|
||||
const wp = ref({})
|
||||
const boxoList: any = ref({})
|
||||
|
||||
const tableHeaderRef = ref()
|
||||
const filterVisible = ref(false)
|
||||
const multiConditionRef = ref<InstanceType<typeof MultiCondition>>()
|
||||
const currentOpenTime = ref('')
|
||||
|
||||
const dictData = useDictData()
|
||||
const ReasonList: any = dictData.getBasicData('Event_Reason')
|
||||
const EventTypeList: any = dictData.getBasicData('Event_Type')
|
||||
|
||||
const options = ref()
|
||||
const heightRef = ref(mainHeight(168, 2.1).height)
|
||||
const selectChange = (flag: boolean, h: any) => {
|
||||
const selectChange = (_flag: boolean, h: number) => {
|
||||
heightRef.value = mainHeight(h, 2.1).height
|
||||
}
|
||||
const eventList = [
|
||||
{ label: '电压暂降', value: '1' },
|
||||
{ label: '电压中断', value: '2' },
|
||||
{ label: '电压暂升', value: '3' }
|
||||
]
|
||||
const getSimpleLineList = async () => {
|
||||
const res = await getSimpleLine()
|
||||
options.value = res.data
|
||||
}
|
||||
|
||||
const tableStore: any = new TableStore({
|
||||
url: '/cs-harmonic-boot/event/pageEvent',
|
||||
url: '/cs-harmonic-boot/eventUser/queryEventpageWeb',
|
||||
method: 'POST',
|
||||
showPage: true,
|
||||
exportName: '暂态事件详情',
|
||||
exportName: '暂态事件',
|
||||
column: [
|
||||
{
|
||||
field: 'index',
|
||||
title: '序号',
|
||||
width: '80',
|
||||
width: 80,
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '暂态时间',
|
||||
field: 'startTime',
|
||||
minWidth: '180'
|
||||
},
|
||||
{
|
||||
title: '测点名称',
|
||||
field: 'lineName',
|
||||
minWidth: '150'
|
||||
},
|
||||
{
|
||||
title: '暂态类型',
|
||||
field: 'tag',
|
||||
minWidth: '100'
|
||||
},
|
||||
{
|
||||
title: '特征幅值(%)',
|
||||
field: 'amplitude',
|
||||
minWidth: '100'
|
||||
},
|
||||
{
|
||||
title: '暂降深度(%)',
|
||||
field: 'depth',
|
||||
minWidth: '100',
|
||||
formatter: (row: any) => {
|
||||
// 当暂态类型不是电压暂升时,计算暂降深度 = 100 - 特征幅值
|
||||
if (row.row.tag !== '电压暂升') {
|
||||
const amplitude = parseFloat(row.row.amplitude)
|
||||
if (!isNaN(amplitude)) {
|
||||
return 100 - amplitude
|
||||
}
|
||||
return '-'
|
||||
} else {
|
||||
// 电压暂升时不显示暂降深度
|
||||
return '/'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '持续时间(S)',
|
||||
field: 'persistTime',
|
||||
minWidth: '100'
|
||||
},
|
||||
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, 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'
|
||||
minWidth: 80,
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
formatter: (row: any) => 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) => ReasonList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
},
|
||||
{
|
||||
title: '波形',
|
||||
minWidth: '100',
|
||||
title: '暂降类型',
|
||||
field: 'advanceType',
|
||||
minWidth: 100,
|
||||
align: 'center',
|
||||
formatter: (row: any) => EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
},
|
||||
{ title: '监测点名称', field: 'lineName', minWidth: 130, align: 'center' },
|
||||
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true },
|
||||
{ title: '设备名称', field: 'equipmentName', minWidth: 130, align: 'center' },
|
||||
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
|
||||
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
|
||||
{
|
||||
title: '发生位置',
|
||||
field: 'sagSource',
|
||||
minWidth: 120,
|
||||
align: 'center',
|
||||
formatter: (row: any) => row.cellValue == 1 ? '上游' : row.cellValue == 2 ? '下游' : '未知'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
text: '波形分析',
|
||||
text: '暂无波形',
|
||||
type: 'info',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
|
||||
return row.wavePath
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '波形分析',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
loading: 'loading1',
|
||||
disabled: row => {
|
||||
return !row.wavePath
|
||||
},
|
||||
|
||||
click: async row => {
|
||||
disabled: (row: any) => !row.wavePath,
|
||||
click: async (row: any) => {
|
||||
row.loading1 = true
|
||||
|
||||
|
||||
dialogVisible.value = false
|
||||
// 在打开弹窗时立即设置高度
|
||||
nextTick(() => {
|
||||
if (waveFormAnalysisRef.value) {
|
||||
// waveFormAnalysisRef.value.setHeight(false, 360)
|
||||
waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
|
||||
}
|
||||
})
|
||||
await analyseWave(row.id)
|
||||
.then(res => {
|
||||
isWaveCharts.value = true
|
||||
loading.value = true
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
boxoList.value = row
|
||||
// boxoList.value = {
|
||||
// ...row,
|
||||
// duration: row.persistTime // 将 persistTime 值赋给 duration
|
||||
// }
|
||||
boxoList.value.featureAmplitude = (row.amplitude - 0) / 100
|
||||
// row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null
|
||||
boxoList.value.systemType = 'YPT'
|
||||
loading.value = true
|
||||
isWaveCharts.value = true
|
||||
boxoList.value = {
|
||||
...row,
|
||||
engineeringName: row.projectName,
|
||||
persistTime: row.evtParamTm,
|
||||
featureAmplitude:
|
||||
row.evtParamVVaDepth != '-' ? (row.evtParamVVaDepth - 0) / 100 : null,
|
||||
systemType: 'YPT',
|
||||
}
|
||||
wp.value = res.data
|
||||
}
|
||||
loading.value = false
|
||||
@@ -208,40 +160,142 @@ const tableStore: any = new TableStore({
|
||||
})
|
||||
|
||||
nextTick(() => {
|
||||
waveFormAnalysisRef.value &&
|
||||
if (waveFormAnalysisRef.value) {
|
||||
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
|
||||
waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
text: '暂无波形',
|
||||
type: 'info',
|
||||
icon: 'el-icon-DataLine',
|
||||
title: '波形下载',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Check',
|
||||
loading: 'loading2',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return row.wavePath
|
||||
disabled: (row: any) => !row.wavePath,
|
||||
click: (row: any) => {
|
||||
row.loading2 = true
|
||||
ElMessage.info('下载中......')
|
||||
getFileZip({ eventId: row.id }).then(res => {
|
||||
const blob = new Blob([res as unknown as BlobPart], { type: 'application/zip' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = row.wavePath.split('/')[2] || '波形文件'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
ElMessage.success('波形下载成功')
|
||||
row.loading2 = false
|
||||
}).catch(() => {
|
||||
row.loading2 = false
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {},
|
||||
loadCallback: () => {}
|
||||
beforeSearchFun: () => { },
|
||||
resetCallback: () => {
|
||||
restoreOpenDayTime()
|
||||
},
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.loading = false
|
||||
item.evtParamTm =
|
||||
item.evtParamTm.split('s')[0] != '-' ? (item.evtParamTm.split('s')[0] - 0).toFixed(2) : '-'
|
||||
item.evtParamVVaDepth =
|
||||
item.evtParamVVaDepth.split('%')[0] != '-'
|
||||
? (item.evtParamVVaDepth.split('%')[0] - 0).toFixed(2)
|
||||
: '-'
|
||||
})
|
||||
}
|
||||
})
|
||||
tableStore.table.params.eventType = ''
|
||||
|
||||
tableStore.table.params.type = 0
|
||||
Object.assign(tableStore.table.params, {
|
||||
featureAmplitudeMin: undefined,
|
||||
featureAmplitudeMax: undefined,
|
||||
evtParamTmMin: undefined,
|
||||
evtParamTmMax: undefined,
|
||||
severityMin: undefined,
|
||||
severityMax: undefined,
|
||||
fileFlag: ''
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
const open = async (time: any) => {
|
||||
tableStore.table.params.eventType = ''
|
||||
dialogVisible.value = true
|
||||
getSimpleLineList()
|
||||
tableStore.table.params.lineId = ''
|
||||
nextTick(() => {
|
||||
|
||||
const resetFilterParams = () => {
|
||||
Object.assign(tableStore.table.params, {
|
||||
featureAmplitudeMin: undefined,
|
||||
featureAmplitudeMax: undefined,
|
||||
evtParamTmMin: undefined,
|
||||
evtParamTmMax: undefined,
|
||||
severityMin: undefined,
|
||||
severityMax: undefined,
|
||||
fileFlag: ''
|
||||
})
|
||||
}
|
||||
|
||||
const restoreOpenDayTime = () => {
|
||||
if (!currentOpenTime.value || !tableHeaderRef.value) return
|
||||
tableHeaderRef.value.setInterval(5)
|
||||
tableHeaderRef.value.setTimeInterval([time, time])
|
||||
tableStore.table.params.searchBeginTime = time
|
||||
tableStore.table.params.searchEndTime = time
|
||||
tableHeaderRef.value.setTimeInterval([currentOpenTime.value, currentOpenTime.value])
|
||||
tableStore.table.params.searchBeginTime = currentOpenTime.value
|
||||
tableStore.table.params.searchEndTime = currentOpenTime.value
|
||||
}
|
||||
|
||||
const syncInitDataForReset = () => {
|
||||
if (!tableStore.initData) return
|
||||
Object.assign(tableStore.initData, {
|
||||
searchBeginTime: currentOpenTime.value,
|
||||
searchEndTime: currentOpenTime.value,
|
||||
startTime: currentOpenTime.value,
|
||||
endTime: currentOpenTime.value,
|
||||
featureAmplitudeMin: undefined,
|
||||
featureAmplitudeMax: undefined,
|
||||
evtParamTmMin: undefined,
|
||||
evtParamTmMax: undefined,
|
||||
severityMin: undefined,
|
||||
severityMax: undefined,
|
||||
fileFlag: ''
|
||||
})
|
||||
}
|
||||
|
||||
const openFilterDialog = () => {
|
||||
filterVisible.value = true
|
||||
}
|
||||
|
||||
const onFilterConfirm = () => {
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
|
||||
const onResetForm = () => {
|
||||
filterVisible.value = false
|
||||
resetFilterParams()
|
||||
multiConditionRef.value?.reset()
|
||||
syncInitDataForReset()
|
||||
nextTick(() => {
|
||||
restoreOpenDayTime()
|
||||
})
|
||||
}
|
||||
|
||||
const open = (time: string) => {
|
||||
currentOpenTime.value = time
|
||||
dialogVisible.value = true
|
||||
filterVisible.value = false
|
||||
resetFilterParams()
|
||||
multiConditionRef.value?.reset()
|
||||
tableStore.table.params.pageNum = 1
|
||||
|
||||
nextTick(() => {
|
||||
restoreOpenDayTime()
|
||||
tableStore.index()
|
||||
nextTick(() => {
|
||||
syncInitDataForReset()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -252,4 +306,5 @@ const handleHideCharts = () => {
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</template>
|
||||
</el-calendar>
|
||||
<!-- 暂态事件列表 -->
|
||||
<TransientList ref="transientListRef" :showLine="false" />
|
||||
<TransientList ref="transientListRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--暂态事件概率分布 -->
|
||||
<TableHeader
|
||||
ref="TableHeaderRef"
|
||||
:timeKeyList="prop.timeKey"
|
||||
:showReset="false"
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
v-if="fullscreen"
|
||||
></TableHeader>
|
||||
<my-echart
|
||||
class="tall"
|
||||
:options="echartList"
|
||||
:style="{
|
||||
<TableHeader ref="TableHeaderRef" :timeKeyList="prop.timeKey" :showReset="false" @selectChange="selectChange"
|
||||
datePicker v-if="fullscreen"></TableHeader>
|
||||
<my-echart class="tall" :options="echartList" :style="{
|
||||
width: prop.width,
|
||||
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}"
|
||||
/>
|
||||
}" />
|
||||
<!-- <my-echart
|
||||
class="mt10"
|
||||
:options="echartList1"
|
||||
@@ -170,7 +160,11 @@ const tableStore: any = new TableStore({
|
||||
},
|
||||
title: {
|
||||
text: '暂态事件概率分布',
|
||||
x: 'center'
|
||||
x: 'center',
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
fontSize: '15'
|
||||
},
|
||||
},
|
||||
visualMap: {
|
||||
max: 500,
|
||||
@@ -242,7 +236,7 @@ const tableStore: any = new TableStore({
|
||||
|
||||
echartList1.value = {
|
||||
title: {
|
||||
text: '越限时间概率分布'
|
||||
text: '暂态事件概率分布',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
||||
@@ -1,197 +1,178 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 暂态事件详情 -->
|
||||
<el-dialog draggable title="暂态事件详情 " v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef" @selectChange="selectChange">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="监测点">
|
||||
<el-select filterable v-model="tableStore.table.params.lineId" placeholder="请选择监测点名称">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.lineId"
|
||||
:label="item.name"
|
||||
:value="item.lineId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="暂态类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.eventType"
|
||||
style="min-width: 150px"
|
||||
clearable
|
||||
placeholder="请选择暂态类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in eventList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%">
|
||||
<TableHeader datePicker showExport ref="tableHeaderRef" @selectChange="selectChange"
|
||||
@onResetForm="onResetForm">
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
|
||||
<MultiCondition
|
||||
v-model:visible="filterVisible"
|
||||
:fixed-target="filterTarget"
|
||||
:params="tableStore.table.params"
|
||||
ref="multiConditionRef"
|
||||
@confirm="onFilterConfirm"
|
||||
/>
|
||||
|
||||
<Table ref="tableRef" isGroup :height="heightRef"></Table>
|
||||
</el-dialog>
|
||||
<!-- 查看波形 -->
|
||||
<el-dialog
|
||||
v-model="isWaveCharts"
|
||||
draggable
|
||||
title="波形分析"
|
||||
append-to-body
|
||||
width="70%"
|
||||
@close="handleHideCharts"
|
||||
>
|
||||
<waveFormAnalysis
|
||||
v-loading="loading"
|
||||
v-if="isWaveCharts"
|
||||
ref="waveFormAnalysisRef"
|
||||
@handleHideCharts="handleHideCharts"
|
||||
:wp="wp"
|
||||
/>
|
||||
|
||||
<el-dialog v-model="isWaveCharts" draggable title="波形分析" append-to-body width="70%" @close="handleHideCharts">
|
||||
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
|
||||
@handleHideCharts="handleHideCharts" :wp="wp" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, provide } from 'vue'
|
||||
import { ref, provide, nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import MultiCondition from '@/views/govern/alarm/multiCondition.vue'
|
||||
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
|
||||
import { analyseWave } from '@/api/common'
|
||||
import { getSimpleLine } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
|
||||
const dialogVisible: any = ref(false)
|
||||
const waveFormAnalysisRef: any = ref(null)
|
||||
// 波形
|
||||
const dialogVisible = ref(false)
|
||||
const waveFormAnalysisRef = ref()
|
||||
const isWaveCharts = ref(false)
|
||||
const loading = ref(false)
|
||||
const wp = ref({})
|
||||
const boxoList: any = ref({})
|
||||
|
||||
const title = ref('暂态事件')
|
||||
const tableHeaderRef = ref()
|
||||
const filterVisible = ref(false)
|
||||
const filterTarget = ref('')
|
||||
const multiConditionRef = ref<InstanceType<typeof MultiCondition>>()
|
||||
|
||||
const dictData = useDictData()
|
||||
const ReasonList: any = dictData.getBasicData('Event_Reason')
|
||||
const EventTypeList: any = dictData.getBasicData('Event_Type')
|
||||
|
||||
const options = ref()
|
||||
const heightRef = ref(mainHeight(168, 2.2).height)
|
||||
const selectChange = (flag: boolean, h: any) => {
|
||||
const tableParams = ref<any>({})
|
||||
const selectChange = (_flag: boolean, h: number) => {
|
||||
heightRef.value = mainHeight(h, 2.2).height
|
||||
}
|
||||
const eventList = [
|
||||
{ label: '电压暂降', value: '1' },
|
||||
{ label: '电压中断', value: '2' },
|
||||
{ label: '电压暂升', value: '3' }
|
||||
]
|
||||
const getSimpleLineList = async () => {
|
||||
const res = await getSimpleLine()
|
||||
options.value = res.data
|
||||
}
|
||||
|
||||
const tableStore: any = new TableStore({
|
||||
url: '/cs-harmonic-boot/event/pageEvent',
|
||||
url: '/cs-device-boot/csGroup/deviceDataByType',
|
||||
method: 'POST',
|
||||
showPage: true,
|
||||
exportName: '主要监测点列表',
|
||||
exportName: '暂态事件',
|
||||
column: [
|
||||
{
|
||||
field: 'index',
|
||||
title: '序号',
|
||||
width: '80',
|
||||
width: 80,
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ field: 'startTime', title: '发生时刻', minWidth: 180, sortable: true },
|
||||
{
|
||||
title: '暂态时间',
|
||||
field: 'startTime',
|
||||
minWidth: '180'
|
||||
},
|
||||
{
|
||||
title: '测点名称',
|
||||
field: 'lineName',
|
||||
minWidth: '150'
|
||||
},
|
||||
{
|
||||
title: '暂态类型',
|
||||
field: 'tag',
|
||||
minWidth: '100'
|
||||
},
|
||||
{
|
||||
title: '特征幅值(%)',
|
||||
field: 'amplitude',
|
||||
minWidth: '100'
|
||||
},
|
||||
{
|
||||
title: '暂降深度(%)',
|
||||
field: 'depth',
|
||||
minWidth: '100',
|
||||
field: 'featureAmplitude',
|
||||
title: '暂降幅值(%)',
|
||||
minWidth: 120,
|
||||
sortable: true,
|
||||
formatter: (row: any) => {
|
||||
// 当暂态类型不是电压暂升时,计算暂降深度 = 100 - 特征幅值
|
||||
if (row.row.tag !== '电压暂升') {
|
||||
const amplitude = parseFloat(row.row.amplitude)
|
||||
if (!isNaN(amplitude)) {
|
||||
return 100 - amplitude
|
||||
}
|
||||
return '-'
|
||||
} else {
|
||||
// 电压暂升时不显示暂降深度
|
||||
return '/'
|
||||
row.cellValue = row.cellValue != null ? Number(row.cellValue).toFixed(2) : '/'
|
||||
if (String(row.cellValue).split('.')[1] == '00') {
|
||||
row.cellValue = String(row.cellValue).split('.')[0]
|
||||
}
|
||||
return row.cellValue
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '持续时间(S)',
|
||||
field: 'persistTime',
|
||||
minWidth: '100'
|
||||
title: '持续时间(s)',
|
||||
minWidth: 110,
|
||||
formatter: (row: any) => row.cellValue ? (row.cellValue - 0).toFixed(2) : '/',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'phaseType',
|
||||
title: '相别',
|
||||
minWidth: 80,
|
||||
formatter: (row: any) => row.cellValue || '/'
|
||||
},
|
||||
{
|
||||
title: '严重度',
|
||||
field: 'severity',
|
||||
minWidth: '80'
|
||||
minWidth: 80,
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
formatter: (row: any) => row.cellValue ? row.cellValue : '/'
|
||||
},
|
||||
{ field: 'showName', title: '触发类型', minWidth: 100 },
|
||||
{
|
||||
title: '暂降原因',
|
||||
field: 'advanceReason',
|
||||
minWidth: 100,
|
||||
align: 'center',
|
||||
formatter: (row: any) => ReasonList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
},
|
||||
{
|
||||
title: '波形',
|
||||
width: '90',
|
||||
title: '暂降类型',
|
||||
field: 'advanceType',
|
||||
minWidth: 100,
|
||||
align: 'center',
|
||||
formatter: (row: any) => EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
},
|
||||
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true },
|
||||
{
|
||||
title: '发生位置',
|
||||
field: 'sagSource',
|
||||
minWidth: 120,
|
||||
align: 'center',
|
||||
formatter: (row: any) => row.cellValue == 1 ? '上游' : row.cellValue == 2 ? '下游' : '未知'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
width: 150,
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
text: '波形分析',
|
||||
type: 'primary',
|
||||
text: '暂无波形',
|
||||
type: 'info',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
loading: 'loading1',
|
||||
disabled: row => {
|
||||
return !row.wavePath
|
||||
},
|
||||
|
||||
click: async row => {
|
||||
row.loading1 = true
|
||||
|
||||
// 在打开弹窗时立即设置高度
|
||||
nextTick(() => {
|
||||
if (waveFormAnalysisRef.value) {
|
||||
// waveFormAnalysisRef.value.setHeight(false, 360)
|
||||
waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
|
||||
return row.wavePath
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '波形分析',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Check',
|
||||
render: 'basicButton',
|
||||
loading: 'loading1',
|
||||
disabled: (row: any) => !row.wavePath,
|
||||
click: async (row: any) => {
|
||||
row.loading1 = true
|
||||
await analyseWave(row.id)
|
||||
.then(res => {
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
loading.value = true
|
||||
isWaveCharts.value = true
|
||||
dialogVisible.value = false
|
||||
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
boxoList.value = row
|
||||
// boxoList.value = {
|
||||
// ...row,
|
||||
// duration: row.persistTime // 将 persistTime 值赋给 duration
|
||||
// }
|
||||
// boxoList.value.featureAmplitude =
|
||||
// row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null
|
||||
boxoList.value.featureAmplitude = (row.amplitude - 0) / 100
|
||||
boxoList.value.systemType = 'YPT'
|
||||
boxoList.value = {
|
||||
...row,
|
||||
systemType: 'YPT',
|
||||
engineeringName: tableParams.value.projectName,
|
||||
featureAmplitude:
|
||||
row.featureAmplitude != null ? Number(row.featureAmplitude / 100) : '-',
|
||||
persistTime: row.persistTime ? row.persistTime.toFixed(2) : '-',
|
||||
}
|
||||
wp.value = res.data
|
||||
}
|
||||
loading.value = false
|
||||
@@ -202,34 +183,108 @@ const tableStore: any = new TableStore({
|
||||
})
|
||||
|
||||
nextTick(() => {
|
||||
waveFormAnalysisRef.value &&
|
||||
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
|
||||
if (waveFormAnalysisRef.value) {
|
||||
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value)
|
||||
waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
text: '暂无波形',
|
||||
type: 'info',
|
||||
icon: 'el-icon-DataLine',
|
||||
title: '波形下载',
|
||||
type: 'primary',
|
||||
loading: 'loading2',
|
||||
icon: 'el-icon-Check',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return row.wavePath
|
||||
disabled: (row: any) => !row.wavePath,
|
||||
click: (row: any) => {
|
||||
row.loading2 = true
|
||||
ElMessage.info('下载中......')
|
||||
getFileZip({ eventId: row.id }).then(res => {
|
||||
const blob = new Blob([res as unknown as BlobPart], { type: 'application/zip' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = row.wavePath.split('/')[2] || '波形文件'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
ElMessage.success('波形下载成功')
|
||||
row.loading2 = false
|
||||
}).catch(() => {
|
||||
row.loading2 = false
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {},
|
||||
loadCallback: () => {}
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.devId = tableParams.value.devId
|
||||
tableStore.table.params.lineId = tableParams.value.lineId
|
||||
tableStore.table.params.list = tableParams.value.list
|
||||
tableStore.table.params.type = 3
|
||||
},
|
||||
loadCallback: () => { }
|
||||
})
|
||||
tableStore.table.params.eventType = ''
|
||||
tableStore.table.params.type = 3
|
||||
Object.assign(tableStore.table.params, {
|
||||
featureAmplitudeMin: undefined,
|
||||
featureAmplitudeMax: undefined,
|
||||
evtParamTmMin: undefined,
|
||||
evtParamTmMax: undefined,
|
||||
severityMin: undefined,
|
||||
severityMax: undefined,
|
||||
fileFlag: ''
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
const open = async (row: any, searchBeginTime: any, searchEndTime: any) => {
|
||||
tableStore.table.params.eventType = ''
|
||||
|
||||
const resetFilterParams = () => {
|
||||
Object.assign(tableStore.table.params, {
|
||||
featureAmplitudeMin: undefined,
|
||||
featureAmplitudeMax: undefined,
|
||||
evtParamTmMin: undefined,
|
||||
evtParamTmMax: undefined,
|
||||
severityMin: undefined,
|
||||
severityMax: undefined,
|
||||
fileFlag: ''
|
||||
})
|
||||
}
|
||||
|
||||
const openFilterDialog = () => {
|
||||
filterVisible.value = true
|
||||
}
|
||||
|
||||
const onFilterConfirm = () => {
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
|
||||
const onResetForm = () => {
|
||||
filterVisible.value = false
|
||||
resetFilterParams()
|
||||
multiConditionRef.value?.reset()
|
||||
tableStore.index()
|
||||
}
|
||||
|
||||
const open = (row: any, searchBeginTime: any, searchEndTime: any, type?: string) => {
|
||||
filterTarget.value = type || ''
|
||||
title.value = row.name + '_暂态事件'
|
||||
dialogVisible.value = true
|
||||
getSimpleLineList()
|
||||
tableStore.table.params.lineId = row.id
|
||||
filterVisible.value = false
|
||||
resetFilterParams()
|
||||
multiConditionRef.value?.reset()
|
||||
|
||||
const lineId = row.id || row.lineId
|
||||
tableParams.value = {
|
||||
lineId,
|
||||
devId: row.devId,
|
||||
engineeringName: row.engineeringName,
|
||||
list: row.devId ? [{ lineId, devId: row.devId }] : undefined,
|
||||
}
|
||||
tableStore.table.params.pageNum = 1
|
||||
|
||||
nextTick(() => {
|
||||
tableHeaderRef.value.setTimeInterval([searchBeginTime, searchEndTime])
|
||||
tableStore.table.params.searchBeginTime = searchBeginTime
|
||||
@@ -245,4 +300,5 @@ const handleHideCharts = () => {
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,27 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--暂态事件统计 -->
|
||||
<TableHeader
|
||||
ref="TableHeaderRef"
|
||||
:showReset="false"
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
v-if="fullscreen" :timeKeyList="prop.timeKey"
|
||||
></TableHeader>
|
||||
<my-echart
|
||||
class="tall"
|
||||
:options="echartList"
|
||||
:style="{
|
||||
<TableHeader ref="TableHeaderRef" :showReset="false" @selectChange="selectChange" datePicker v-if="fullscreen"
|
||||
:timeKeyList="prop.timeKey"></TableHeader>
|
||||
<my-echart class="tall" :options="echartList" :style="{
|
||||
width: prop.width,
|
||||
height: `calc(${prop.height} / 2 - ${headerHeight / 2}px + ${fullscreen ? 0 : 28}px )`
|
||||
}"
|
||||
/>
|
||||
<Table
|
||||
ref="tableRef"
|
||||
@cell-click="cellClickEvent"
|
||||
:height="`calc(${prop.height} / 2 - ${headerHeight / 2}px + ${fullscreen ? 0 : 28}px )`"
|
||||
isGroup
|
||||
></Table>
|
||||
}" />
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent"
|
||||
:height="`calc(${prop.height} / 2 - ${headerHeight / 2}px + ${fullscreen ? 0 : 28}px )`" isGroup></Table>
|
||||
<TransientStatisticsDetail ref="transientStatisticsDetailRef"></TransientStatisticsDetail>
|
||||
</div>
|
||||
</template>
|
||||
@@ -129,7 +116,11 @@ const eventEcharts = () => {
|
||||
title: [
|
||||
{
|
||||
text: '暂态事件统计',
|
||||
left: 'center'
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
fontSize: '15'
|
||||
},
|
||||
},
|
||||
{
|
||||
text: rawData.eventOff + rawData.eventDown + rawData.eventUp + '次',
|
||||
@@ -173,15 +164,30 @@ const tableStore: any = new TableStore({
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
title: '监测点名称',
|
||||
field: 'name',
|
||||
minWidth: '90'
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: '设备名称', field: 'devName', minWidth: 130, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '项目名称', field: 'projectName', minWidth: 130, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: '电压中断(次)',
|
||||
field: 'eventOff',
|
||||
minWidth: '70',
|
||||
minWidth: '90',
|
||||
sortable: true,
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
@@ -191,7 +197,7 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '电压暂降(次)',
|
||||
field: 'eventDown',
|
||||
minWidth: '80',
|
||||
minWidth: '90',
|
||||
sortable: true,
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
@@ -201,7 +207,7 @@ const tableStore: any = new TableStore({
|
||||
{
|
||||
title: '电压暂升(次)',
|
||||
field: 'eventUp',
|
||||
minWidth: '80',
|
||||
minWidth: '90',
|
||||
sortable: true,
|
||||
render: 'customTemplate',
|
||||
customTemplate: (row: any) => {
|
||||
@@ -224,11 +230,13 @@ provide('tableStore', tableStore)
|
||||
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field != 'name') {
|
||||
if (column.field != 'name' && column.field != 'devName' && column.field != 'projectName' && column.field != 'engineeringName') {
|
||||
transientStatisticsDetailRef.value.open(
|
||||
row,
|
||||
tableStore.table.params.searchBeginTime || prop.timeValue?.[0],
|
||||
tableStore.table.params.searchEndTime || prop.timeValue?.[1]
|
||||
tableStore.table.params.searchEndTime || prop.timeValue?.[1],
|
||||
column.field=='eventOff'?'中断':column.field=='eventDown'?'暂降':column.field=='eventUp'?'暂升':''
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="device-control">
|
||||
<!--趋势对比 -->
|
||||
<TableHeader
|
||||
datePicker
|
||||
ref="TableHeaderRef"
|
||||
:timeKeyList="prop.timeKey"
|
||||
:showReset="false"
|
||||
@selectChange="selectChange"
|
||||
v-if="fullscreen"
|
||||
>
|
||||
<div v-show="fullscreen">
|
||||
<!-- <PointTree :height="flag ? 106 : 50" @node-click="nodeClick" @pointTypeChange="pointTypeChange"></PointTree> -->
|
||||
<APFTree :height="flag ? 126 : 70" @node-click="handleNodeClick" @init="handleNodeClick"></APFTree>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<TableHeader datePicker ref="TableHeaderRef" :timeKeyList="prop.timeKey" :showReset="false"
|
||||
@selectChange="selectChange" v-if="fullscreen">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="监测对象">
|
||||
<el-select
|
||||
filterable
|
||||
v-model="tableStore.table.params.sensitiveUserId"
|
||||
placeholder="请选择监测对象"
|
||||
clearable
|
||||
>
|
||||
<!-- <el-form-item label="监测对象">
|
||||
<el-select filterable v-model="tableStore.table.params.sensitiveUserId" placeholder="请选择监测对象"
|
||||
clearable>
|
||||
<el-option v-for="item in idList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="监测点名称">
|
||||
<el-select v-model="tableStore.table.params.lineId" placeholder="请选择监测点名称" clearable>
|
||||
<el-option
|
||||
@@ -32,21 +28,19 @@
|
||||
</el-form-item> -->
|
||||
<el-form-item label="电能质量指标">
|
||||
<el-select v-model="tableStore.table.params.indicator" placeholder="请选择电能质量指标" clearable>
|
||||
<el-option v-for="item in indicatorList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
<el-option v-for="item in indicatorList" :key="item.id" :label="item.name"
|
||||
:value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-radio-group v-model="tableStore.table.params.dataLevel">
|
||||
<el-radio-group v-model="tableStore.table.params.dataLevel" @change="tableStore.index()">
|
||||
<el-radio-button label="一次值" value="Primary" />
|
||||
<el-radio-button label="二次值" value="Secondary" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
style="min-width: 120px !important"
|
||||
placeholder="请选择"
|
||||
v-model="tableStore.table.params.valueType"
|
||||
>
|
||||
<el-select style="min-width: 120px !important" placeholder="请选择"
|
||||
v-model="tableStore.table.params.valueType">
|
||||
<el-option value="max" label="最大值"></el-option>
|
||||
<el-option value="min" label="最小值"></el-option>
|
||||
<el-option value="avg" label="平均值"></el-option>
|
||||
@@ -54,33 +48,23 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div v-if="shouldShowHarmonicCount()" style="display: flex; color: var(--el-text-color-regular)">
|
||||
<div v-if="shouldShowHarmonicCount()"
|
||||
style="display: flex; color: var(--el-text-color-regular)">
|
||||
<span style="width: 160px">{{ getHarmonicTypeName() }}谐波次数</span>
|
||||
<el-select
|
||||
v-model="tableStore.table.params.harmonicCount"
|
||||
placeholder="请选择谐波次数"
|
||||
style="min-width: 80px !important"
|
||||
>
|
||||
<el-option
|
||||
v-for="num in harmonicCountOptions"
|
||||
:key="num"
|
||||
:label="num"
|
||||
:value="num"
|
||||
></el-option>
|
||||
<el-select v-model="tableStore.table.params.harmonicCount" placeholder="请选择谐波次数"
|
||||
style="min-width: 80px !important">
|
||||
<el-option v-for="num in harmonicCountOptions" :key="num" :label="num"
|
||||
:value="num"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<my-echart
|
||||
v-loading="tableStore.table.loading"
|
||||
class="tall"
|
||||
:options="echartList"
|
||||
:style="{
|
||||
width: prop.width,
|
||||
<my-echart v-loading="tableStore.table.loading" class="tall" :options="echartList" :style="{
|
||||
width: `calc(${prop.width} - ${fullscreen ? 290 : 0}px)`,
|
||||
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px)`
|
||||
}"
|
||||
/>
|
||||
}" />
|
||||
</div>
|
||||
<!-- <el-empty description="暂无数据" /> -->
|
||||
</div>
|
||||
</template>
|
||||
@@ -94,7 +78,7 @@ import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { getTime } from '@/utils/formatTime'
|
||||
import { yMethod, exportCSV } from '@/utils/echartMethod'
|
||||
import { max } from 'lodash'
|
||||
import APFTree from '@/components/tree/govern/APFTree.vue'
|
||||
const prop = defineProps({
|
||||
w: { type: [String, Number] },
|
||||
h: { type: [String, Number] },
|
||||
@@ -102,7 +86,8 @@ const prop = defineProps({
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: Array as () => string[] },
|
||||
timeValue: { type: Object },
|
||||
interval: { type: Number }
|
||||
interval: { type: Number },
|
||||
flag: { type: Boolean }
|
||||
})
|
||||
|
||||
const TableHeaderRef = ref()
|
||||
@@ -136,12 +121,26 @@ const initListByIds = () => {
|
||||
getListByIds({}).then((res: any) => {
|
||||
if (res.data?.length > 0) {
|
||||
idList.value = res.data
|
||||
initCode()
|
||||
|
||||
} else {
|
||||
tableStore.index()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const handleNodeClick = async (data: any) => {
|
||||
|
||||
|
||||
if (data?.level == 3 || data?.level == 2) {
|
||||
tableStore.table.params.sensitiveUserId = data.id
|
||||
await tableStore.index()
|
||||
} else {
|
||||
tableStore.table.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
|
||||
headerHeight.value = height
|
||||
|
||||
@@ -158,7 +157,7 @@ const initCode = () => {
|
||||
indicatorList.value = item.data
|
||||
tableStore.table.params.indicator = indicatorList.value[0].id
|
||||
nextTick(() => {
|
||||
tableStore.index()
|
||||
// tableStore.index()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -192,7 +191,7 @@ const setEchart = () => {
|
||||
if (!afterGroupedByPhase[phase]) {
|
||||
afterGroupedByPhase[phase] = []
|
||||
}
|
||||
afterGroupedByPhase[phase].push([item.time, item.statisticalData, item.unit, 'dotted'])
|
||||
afterGroupedByPhase[phase].push([item.time, item.statisticalData, item.unit, 'dashed'])
|
||||
})
|
||||
|
||||
// 构建系列数据
|
||||
@@ -224,7 +223,6 @@ const setEchart = () => {
|
||||
},
|
||||
lineStyle: {
|
||||
type: 'solid', // 实线
|
||||
width: 2 // 线条宽度
|
||||
},
|
||||
yAxisIndex: 0
|
||||
})
|
||||
@@ -249,7 +247,6 @@ const setEchart = () => {
|
||||
},
|
||||
lineStyle: {
|
||||
type: 'dashed', // 虚线
|
||||
width: 2 // 线条宽度
|
||||
},
|
||||
yAxisIndex: 0
|
||||
})
|
||||
@@ -285,9 +282,9 @@ const setEchart = () => {
|
||||
|
||||
return {
|
||||
name: item.name,
|
||||
icon: isBefore
|
||||
? 'rect'
|
||||
: 'path://M0,2 L8,2 L8,6 L0,6 Z M12,2 L20,2 L20,6 L12,6 Z M24,2 L32,2 L32,6 L24,6 Z M36,2 L44,2 L44,6 L36,6 Z', // 矩形组成的粗虚线
|
||||
// icon: isBefore
|
||||
// ? 'rect'
|
||||
// : 'path://M0,2 L8,2 L8,6 L0,6 Z M12,2 L20,2 L20,6 L12,6 Z M24,2 L32,2 L32,6 L24,6 Z M36,2 L44,2 L44,6 L36,6 Z', // 矩形组成的粗虚线
|
||||
itemStyle: {
|
||||
color: color // 明确指定图例图标的颜色
|
||||
},
|
||||
@@ -326,11 +323,16 @@ const setEchart = () => {
|
||||
let str = `${xname}<br>`
|
||||
params.forEach((el: any, index: any) => {
|
||||
let marker = ''
|
||||
if (el.value[3] == 'dashed') {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
|
||||
}
|
||||
} else {
|
||||
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`//`<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
||||
|
||||
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
||||
}
|
||||
|
||||
str += `${marker}${el.seriesName.split('(')[0]}:${
|
||||
el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == null ? '' : el.value[2]) : '-'
|
||||
str += `${marker}${el.seriesName.split('(')[0]}:${el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == null ? '' : el.value[2]) : '-'
|
||||
}<br>`
|
||||
})
|
||||
return str
|
||||
@@ -338,9 +340,11 @@ const setEchart = () => {
|
||||
},
|
||||
legend: {
|
||||
data: legendData,
|
||||
icon: 'rect',
|
||||
// icon: 'rect',
|
||||
itemWidth: 18,
|
||||
itemHeight: 3,
|
||||
type: 'scroll',
|
||||
|
||||
itemStyle: {
|
||||
borderWidth: 0
|
||||
},
|
||||
@@ -379,9 +383,9 @@ const tableStore: any = new TableStore({
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
setTime()
|
||||
if (!tableStore.table.params.sensitiveUserId && idList.value?.length > 0) {
|
||||
tableStore.table.params.sensitiveUserId = idList.value[0].id
|
||||
}
|
||||
// if (!tableStore.table.params.sensitiveUserId && idList.value?.length > 0) {
|
||||
// tableStore.table.params.sensitiveUserId = idList.value[0].id
|
||||
// }
|
||||
let lists: any = []
|
||||
// 处理电能质量指标
|
||||
const selectedIndicator = indicatorList.value?.find(
|
||||
@@ -420,7 +424,8 @@ tableStore.table.params.valueType = 'avg'
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
initListByIds()
|
||||
initCode()
|
||||
// initListByIds()
|
||||
})
|
||||
|
||||
const setTime = () => {
|
||||
@@ -504,4 +509,11 @@ watch(
|
||||
// :deep(.el-select) {
|
||||
// min-width: 80px;
|
||||
// }
|
||||
.device-control {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:deep(.cn-tree) {
|
||||
padding: 0 10px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -45,7 +45,7 @@ const initChart = () => {
|
||||
color: '#000',
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
fontSize: '18'
|
||||
fontSize: '15'
|
||||
},
|
||||
// },
|
||||
...(props.options?.title || null)
|
||||
@@ -108,14 +108,14 @@ const initChart = () => {
|
||||
|
||||
bottom: '20px',
|
||||
end: 100,
|
||||
filterMode: 'none'
|
||||
filterMode: 'filter'
|
||||
},
|
||||
{
|
||||
start: 0,
|
||||
height: 13,
|
||||
bottom: '20px',
|
||||
end: 100,
|
||||
filterMode: 'none'
|
||||
filterMode: 'filter'
|
||||
}
|
||||
// {
|
||||
// show: true,
|
||||
|
||||
@@ -684,7 +684,7 @@ const initWave = (
|
||||
align: 'left'
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: '16px',
|
||||
fontSize: '14px',
|
||||
color: props.DColor ? '#000' : echartsColor.WordColor
|
||||
}
|
||||
},
|
||||
@@ -809,13 +809,15 @@ const initWave = (
|
||||
height: 13,
|
||||
start: 0,
|
||||
bottom: '20px',
|
||||
end: 100
|
||||
end: 100,
|
||||
filterMode: 'filter'
|
||||
},
|
||||
{
|
||||
start: 0,
|
||||
height: 13,
|
||||
bottom: '20px',
|
||||
end: 100
|
||||
end: 100,
|
||||
filterMode: 'filter'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
@@ -1027,7 +1029,7 @@ const drawPics = (
|
||||
left: 'center',
|
||||
text: '', //titlename || title,
|
||||
textStyle: {
|
||||
fontSize: '16px',
|
||||
fontSize: '15px',
|
||||
color: props.DColor ? '#000' : echartsColor.WordColor
|
||||
}
|
||||
},
|
||||
|
||||
@@ -448,7 +448,7 @@ const initWave = (
|
||||
left: 'center',
|
||||
text: titleText,
|
||||
textStyle: {
|
||||
fontSize: '16px',
|
||||
fontSize: '14px',
|
||||
color: props.DColor ? '#000' : echartsColor.WordColor
|
||||
}
|
||||
},
|
||||
@@ -565,13 +565,15 @@ const initWave = (
|
||||
height: 13,
|
||||
start: 0,
|
||||
bottom: '20px',
|
||||
end: 100
|
||||
end: 100,
|
||||
filterMode: 'filter'
|
||||
},
|
||||
{
|
||||
start: 0,
|
||||
height: 13,
|
||||
bottom: '20px',
|
||||
end: 100
|
||||
end: 100,
|
||||
filterMode: 'filter'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="onComSearch"
|
||||
v-if="showSearch"
|
||||
v-if="showSearch &&showQuery"
|
||||
:loading="tableStore.table.loading"
|
||||
type="primary"
|
||||
:icon="Search"
|
||||
@@ -102,6 +102,7 @@ interface Props {
|
||||
showSearch?: boolean
|
||||
nextFlag?: boolean //控制时间是否可以往后推
|
||||
theCurrentTime?: boolean //控制时间前3天展示上个月时间
|
||||
showQuery?: boolean //是否显示查詢
|
||||
showReset?: boolean //是否显示重置
|
||||
showExport?: boolean //导出控制
|
||||
timeCacheFlag?: boolean //是否取缓存时间
|
||||
@@ -115,6 +116,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
nextFlag: false,
|
||||
theCurrentTime: true,
|
||||
showReset: true,
|
||||
showQuery: true,
|
||||
showExport: false,
|
||||
timeCacheFlag: true,
|
||||
timeKeyList: () => ['1', '2', '3', '4', '5'] // 修改为箭头函数返回空数组
|
||||
|
||||
168
src/components/tree/govern/APFTree.vue
Normal file
168
src/components/tree/govern/APFTree.vue
Normal file
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<div class="apf-tree">
|
||||
<div class="cn-tree" :style="{ height: `calc(100vh - 125px - ${height}px)` }">
|
||||
<div style="display: flex; align-items: center" class="mb10">
|
||||
<el-input maxlength="32" show-word-limit v-model.trim="filterText" placeholder="请输入内容" clearable>
|
||||
<template #prefix>
|
||||
<Icon name="el-icon-Search" style="font-size: 16px" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-tree style="flex: 1; overflow: auto" :props="defaultProps" highlight-current
|
||||
:filter-node-method="filterNode" node-key="id" default-expand-all :data="tree" ref="treRef"
|
||||
@node-click="clickNode" :expand-on-click-node="false">
|
||||
<template #default="{ node, data: nodeData }">
|
||||
<span class="custom-tree-node">
|
||||
<Icon :name="nodeData.icon" style="font-size: 16px" :style="{ color: nodeData.color }"
|
||||
v-if="nodeData.icon" />
|
||||
<span style="margin-left: 5px">{{ node.label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
import { ElTree } from 'element-plus'
|
||||
import { getUserDevTree } from '@/api/cs-device-boot/csLedger'
|
||||
import { useConfig } from '@/stores/config'
|
||||
import { querySysExcel } from '@/api/harmonic-boot/luckyexcel'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { createLineTreeDecorators } from './lineTreeUtils'
|
||||
import { bootstrapWithTemplate } from './treeCommonUtils'
|
||||
import { createTreeFilterNode } from './treeFilterUtils'
|
||||
|
||||
interface Props {
|
||||
template?: boolean
|
||||
type?: string
|
||||
height?: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), { template: false, type: 'apf', height: 0 })
|
||||
|
||||
defineOptions({ name: 'govern/APFTree', inheritAttrs: false })
|
||||
|
||||
const emit = defineEmits(['init', 'node-click', 'deviceTypeChange', 'Policy'])
|
||||
|
||||
const config = useConfig()
|
||||
const dictData = useDictData()
|
||||
const tree = ref<any[]>([])
|
||||
const treRef = ref<InstanceType<typeof ElTree>>()
|
||||
const filterText = ref('')
|
||||
|
||||
const defaultProps = { children: 'children', label: 'name', value: 'id' }
|
||||
const decorators = createLineTreeDecorators(() => config.getColorVal('elementUiPrimary'))
|
||||
const filterNode = createTreeFilterNode()
|
||||
|
||||
watch(filterText, val => treRef.value?.filter(val))
|
||||
|
||||
/** 将 { 用户名: 设备[] | null } 转为两级树 */
|
||||
function transformUserDevTree(data: Record<string, any[] | null>) {
|
||||
const nodes: any[] = []
|
||||
const devices: any[] = []
|
||||
const { primary, statusColor, applyMeta } = decorators
|
||||
|
||||
if (!data || typeof data !== 'object') {
|
||||
return { nodes, devices }
|
||||
}
|
||||
|
||||
Object.entries(data).forEach(([userName, deviceList]) => {
|
||||
const hasDevices = Array.isArray(deviceList) && deviceList.length > 0
|
||||
const userId = hasDevices ? deviceList[0]?.monitorUser || userName : `apf-user-${userName}`
|
||||
|
||||
const children = hasDevices
|
||||
? deviceList.map((device: any) => {
|
||||
const node = {
|
||||
...device,
|
||||
level: 2,
|
||||
pid: userId,
|
||||
pname: userName
|
||||
}
|
||||
applyMeta(node, {
|
||||
icon: 'el-icon-Platform',
|
||||
color: statusColor(device.runStatus)
|
||||
})
|
||||
devices.push(node)
|
||||
return node
|
||||
})
|
||||
: undefined
|
||||
|
||||
const userNode: any = {
|
||||
id: userId,
|
||||
name: userName,
|
||||
level: 1,
|
||||
...(children ? { children } : {})
|
||||
}
|
||||
applyMeta(userNode, { icon: 'el-icon-User', color: primary(), disabled: true })
|
||||
nodes.push(userNode)
|
||||
})
|
||||
|
||||
return { nodes, devices }
|
||||
}
|
||||
|
||||
async function selectFirstDevice(devices: any[]) {
|
||||
const node = devices[0]
|
||||
if (!node) {
|
||||
emit('init', { ...node })
|
||||
return
|
||||
}
|
||||
|
||||
await nextTick()
|
||||
treRef.value?.setCurrentKey(node.id)
|
||||
emit('init', { level: 2, ...node })
|
||||
}
|
||||
|
||||
async function loadTree() {
|
||||
tree.value = []
|
||||
const res = await getUserDevTree({ type: props.type })
|
||||
const { nodes, devices } = transformUserDevTree(res.data)
|
||||
tree.value = nodes
|
||||
await selectFirstDevice(devices)
|
||||
}
|
||||
|
||||
const clickNode = (node: any) => {
|
||||
if (node?.children?.length) return
|
||||
emit('node-click', node)
|
||||
}
|
||||
|
||||
bootstrapWithTemplate(
|
||||
props.template,
|
||||
loadTree,
|
||||
() => querySysExcel({ id: dictData.state.area[0]?.id }),
|
||||
data => emit('Policy', data)
|
||||
)
|
||||
|
||||
watch(() => props.type, () => {
|
||||
loadTree()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.apf-tree {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cn-tree {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
|
||||
overflow-y: auto;
|
||||
|
||||
:deep(.el-tree) {
|
||||
border: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
:deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) {
|
||||
background-color: var(--el-color-primary-light-7);
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -77,7 +77,11 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
|
||||
config.url == '/cs-harmonic-boot/limitRateDetailD/limitProbabilityData' ||
|
||||
config.url == '/system-boot/dictTree/queryByCode' ||
|
||||
config.url == '/system-boot/dictTree/queryByid' ||
|
||||
config.url == '/system-boot/dictTree/query'
|
||||
config.url == '/system-boot/dictTree/query'||
|
||||
config.url == '/cs-harmonic-boot/csevent/f47Curve'||
|
||||
config.url == '/cs-harmonic-boot/sysExcel/querySysExcel'||
|
||||
config.url == '/cs-device-boot/csLedger/lineTree'||
|
||||
config.url == '/cs-harmonic-boot/pqSensitiveUser/getUserDevTree'
|
||||
)
|
||||
)
|
||||
removePending(config)
|
||||
|
||||
@@ -60,16 +60,16 @@ const tabsList = ref([
|
||||
])
|
||||
const rankOptions = ref([
|
||||
{
|
||||
value: '1,7',
|
||||
label: '1级(ERROR)'
|
||||
value: '1',
|
||||
label: '1级'
|
||||
},
|
||||
{
|
||||
value: '2,6',
|
||||
label: '2级(WARN)'
|
||||
value: '2',
|
||||
label: '2级'
|
||||
},
|
||||
{
|
||||
value: '3,4,5',
|
||||
label: '3级(DEBUG,NORMAL)'
|
||||
value: '3',
|
||||
label: '3级'
|
||||
},
|
||||
// {
|
||||
// value: '4',
|
||||
|
||||
@@ -37,16 +37,16 @@ const props = defineProps(['deviceTree'])
|
||||
const refheader = ref()
|
||||
const rankOptions = ref([
|
||||
{
|
||||
value: '1,7',
|
||||
label: '1级(ERROR)'
|
||||
value: '1',
|
||||
label: '1级'
|
||||
},
|
||||
{
|
||||
value: '2,6',
|
||||
label: '2级(WARN)'
|
||||
value: '2',
|
||||
label: '2级'
|
||||
},
|
||||
{
|
||||
value: '3,4,5',
|
||||
label: '3级(DEBUG,NORMAL)'
|
||||
value: '3',
|
||||
label: '3级'
|
||||
},
|
||||
// {
|
||||
// value: '4',
|
||||
@@ -151,12 +151,12 @@ const tableStore = new TableStore({
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.searchValue = ''
|
||||
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 deviceTreeOptions = ref<any>(props.deviceTree)
|
||||
// deviceTreeOptions.value.map((item: any, index: any) => {
|
||||
// if (item?.children.length == 0) {
|
||||
// deviceTreeOptions.value.splice(index, 1)
|
||||
// }
|
||||
// })
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
|
||||
@@ -50,12 +50,8 @@ const props = defineProps(['deviceTree'])
|
||||
|
||||
const refheader = ref()
|
||||
const waveFormAnalysisRef = ref()
|
||||
const view = ref(true)
|
||||
const isWaveCharts = ref(false)
|
||||
const view2 = ref(false)
|
||||
const showBoxi = ref(true)
|
||||
const loading = ref(false)
|
||||
const bxactiveName = ref('ssbx')
|
||||
const boxoList: any = ref({})
|
||||
const analysisListRef = ref()
|
||||
const wp = ref({})
|
||||
@@ -103,9 +99,6 @@ const tableStore = new TableStore({
|
||||
return EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
{ title: '监测点名称', field: 'lineName', minWidth: 130, align: 'center' },
|
||||
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true, },
|
||||
{ title: '设备名称', field: 'equipmentName', minWidth: 130, align: 'center' },
|
||||
@@ -116,8 +109,6 @@ const tableStore = new TableStore({
|
||||
return row.cellValue == 1 ? '上游' : row.cellValue == 2 ? '下游' : '未知'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
@@ -144,12 +135,15 @@ const tableStore = new TableStore({
|
||||
if (res != undefined) {
|
||||
loading.value = true
|
||||
isWaveCharts.value = true
|
||||
boxoList.value = row
|
||||
boxoList.value.engineeringName = row.projectName
|
||||
boxoList.value.persistTime = row.evtParamTm
|
||||
boxoList.value.featureAmplitude =
|
||||
row.evtParamVVaDepth != '-' ? (row.evtParamVVaDepth - 0) / 100 : null
|
||||
boxoList.value.systemType = 'YPT'
|
||||
|
||||
boxoList.value = {
|
||||
...row,
|
||||
engineeringName: row.projectName,
|
||||
persistTime: row.evtParamTm,
|
||||
featureAmplitude:
|
||||
row.evtParamVVaDepth != '-' ? (row.evtParamVVaDepth - 0) / 100 : null,
|
||||
systemType: 'YPT',
|
||||
}
|
||||
wp.value = res.data
|
||||
}
|
||||
loading.value = false
|
||||
@@ -164,27 +158,7 @@ const tableStore = new TableStore({
|
||||
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
|
||||
// waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(200, 190)
|
||||
})
|
||||
// row.loading1 = true
|
||||
// view.value = false
|
||||
// view2.value = true
|
||||
// loading.value = true
|
||||
// boxoList.value = row
|
||||
// boxoList.value.systemType = 'WX'
|
||||
|
||||
// boxoList.value.persistTime = row.evtParamTm != '-' ? row.evtParamTm - 0 : null
|
||||
// await analyseWave(row.id)
|
||||
// .then(res => {
|
||||
// row.loading1 = false
|
||||
// if (res != undefined) {
|
||||
// wp.value = res.data
|
||||
|
||||
// }
|
||||
// loading.value = false
|
||||
// })
|
||||
// .catch(() => {
|
||||
// row.loading1 = false
|
||||
// loading.value = false
|
||||
// })
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
</el-tab-pane>
|
||||
|
||||
|
||||
<el-tab-pane label="异常事件" name="5">
|
||||
<Abnormal v-if="activeName == '5'" :deviceTree="deviceTree" :key="key" />
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
@@ -26,7 +24,6 @@ import { ref, onMounted, provide } from 'vue'
|
||||
import Steady from './Steady.vue'
|
||||
import Transient from './Transient.vue'
|
||||
import Device from './Device.vue'
|
||||
import Abnormal from './Abnormal.vue'
|
||||
import Front from './Front.vue'
|
||||
import { getDeviceTree } from '@/api/cs-device-boot/csLedger'
|
||||
defineOptions({
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="触发类型">
|
||||
<el-select v-model="params.target" clearable placeholder="请选择触发类型" multiple collapse-tags
|
||||
style="width: 317px">
|
||||
<el-select v-model="params.target" :clearable="!hasFixedTarget" placeholder="请选择触发类型" multiple
|
||||
collapse-tags style="width: 317px">
|
||||
<el-option v-for="item in eventTypeList" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
@@ -51,16 +51,36 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const getDefaultFilterParams = () => ({
|
||||
const ALL_EVENT_TYPES = [
|
||||
{ label: '暂降', value: '暂降' },
|
||||
{ label: '暂升', value: '暂升' },
|
||||
{ label: '中断', value: '中断' },
|
||||
{ label: '瞬态', value: '瞬态' },
|
||||
{ label: '振荡', value: '振荡' },
|
||||
]
|
||||
|
||||
const parseFixedTargets = (fixedTarget?: string | string[]) => {
|
||||
if (!fixedTarget) return []
|
||||
const values = Array.isArray(fixedTarget) ? fixedTarget : fixedTarget.split(/[,,]/).map(item => item.trim())
|
||||
return values.filter(Boolean)
|
||||
}
|
||||
|
||||
const getInitialTarget = (fixedTarget?: string | string[]) => {
|
||||
const fixed = parseFixedTargets(fixedTarget)
|
||||
return fixed.length ? [...fixed] : []
|
||||
}
|
||||
|
||||
const getDefaultFilterParams = (fixedTarget?: string | string[]) => ({
|
||||
featureAmplitudeMin: undefined as number | undefined,
|
||||
featureAmplitudeMax: undefined as number | undefined,
|
||||
evtParamTmMin: undefined as number | undefined,
|
||||
evtParamTmMax: undefined as number | undefined,
|
||||
severityMin: undefined as number | undefined,
|
||||
severityMax: undefined as number | undefined,
|
||||
target: [] as string[],
|
||||
target: getInitialTarget(fixedTarget),
|
||||
fileFlag: '' as string | number
|
||||
})
|
||||
|
||||
@@ -68,19 +88,33 @@ const visible = defineModel<boolean>('visible', { default: false })
|
||||
|
||||
const props = defineProps<{
|
||||
params: Record<string, any>
|
||||
fixedTarget?: string | string[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
confirm: []
|
||||
}>()
|
||||
|
||||
const eventTypeList = [
|
||||
{ label: '暂降', value: '暂降' },
|
||||
{ label: '暂升', value: '暂升' },
|
||||
{ label: '中断', value: '中断' },
|
||||
{ label: '瞬态', value: '瞬态' },
|
||||
{ label: '振荡', value: '振荡' },
|
||||
]
|
||||
const hasFixedTarget = computed(() => parseFixedTargets(props.fixedTarget).length > 0)
|
||||
|
||||
const eventTypeList = computed(() => {
|
||||
const fixed = parseFixedTargets(props.fixedTarget)
|
||||
if (!fixed.length) return ALL_EVENT_TYPES
|
||||
|
||||
return fixed.map(value => {
|
||||
const matched = ALL_EVENT_TYPES.find(item => item.value === value)
|
||||
return matched || { label: value, value }
|
||||
})
|
||||
})
|
||||
|
||||
const syncFixedTarget = () => {
|
||||
const fixed = parseFixedTargets(props.fixedTarget)
|
||||
if (fixed.length) {
|
||||
props.params.target = [...fixed]
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.fixedTarget, syncFixedTarget, { immediate: true })
|
||||
|
||||
const fileFlagOptions = [
|
||||
{ label: '存在', value: 1 },
|
||||
@@ -115,7 +149,8 @@ const validateRange = (
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
Object.assign(props.params, getDefaultFilterParams())
|
||||
Object.assign(props.params, getDefaultFilterParams(props.fixedTarget))
|
||||
syncFixedTarget()
|
||||
}
|
||||
|
||||
const onConfirm = () => {
|
||||
|
||||
448
src/views/govern/analyze/APF/APF.vue
Normal file
448
src/views/govern/analyze/APF/APF.vue
Normal file
@@ -0,0 +1,448 @@
|
||||
<template>
|
||||
<div class=" analyze-apf" :style="{ height: pageHeight.height }" v-loading="loading">
|
||||
<APFTree @node-click="nodeClick" :height="60" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></APFTree>
|
||||
<div class="analyze-apf-right" v-if="formInline.devId">
|
||||
<div ref="headerRef">
|
||||
<TableHeader :showSearch="false" ref="tableHeaderRef" @selectChange="selectChange"
|
||||
>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="时间:">
|
||||
<DatePicker ref="datePickerRef" :timeKeyList="['3', '4', '5']"></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计指标:">
|
||||
<el-select style="width: 200px" v-model.trim="formInline.statisticalId" filterable
|
||||
@change="frequencyFlag" placeholder="请选择">
|
||||
<el-option v-for="item in zblist" :key="item.value" :label="item.label"
|
||||
:value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="谐波次数:" v-show="frequencyShow">
|
||||
<el-select v-model.trim="formInline.frequency" filterable placeholder="请选择"
|
||||
style="width: 100px">
|
||||
<el-option v-for="item in 49" :key="item + 1" :label="item + 1"
|
||||
:value="item + 1"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="值类型:">
|
||||
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择">
|
||||
<el-option v-for="item in typelist" :key="item.value" :label="item.label"
|
||||
:value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" @click="search" icon="el-icon-Search">查询</el-button>
|
||||
<el-button :type="timeControl ? 'primary' : ''" icon="el-icon-Sort" @click="setTimeControl">
|
||||
缺失数据
|
||||
</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
|
||||
<el-empty description="暂无数据" v-if="!echartsData" style="flex: 1"></el-empty>
|
||||
<template v-else>
|
||||
<div :style="echartHeight">
|
||||
<MyEchart :options="echartsData" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<el-empty v-else :style="echartHeight" description="请选择设备" class="analyze-apf-right" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
// import DeviceTree from '@/components/tree/govern/deviceTree.vue'
|
||||
import APFTree from '@/components/tree/govern/APFTree.vue'
|
||||
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { getDevCapacity } from '@/api/cs-device-boot/capacity'
|
||||
import { queryCommonStatisticalByTime } from '@/api/cs-harmonic-boot/stable'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { yMethod, completeTimeSeries } from '@/utils/echartMethod'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
const timeControl = ref(false)
|
||||
|
||||
|
||||
const tableHeaderRef = ref()
|
||||
const headerRef = ref()
|
||||
const pageHeight = mainHeight(80)
|
||||
const echartHeight = ref(mainHeight(130))
|
||||
const loading = ref(false)
|
||||
const echartsData = ref<any>(null)
|
||||
const datePickerRef = ref()
|
||||
const formInline = reactive({
|
||||
statisticalId: '',
|
||||
valueType: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
devId: '',
|
||||
frequency: ''
|
||||
})
|
||||
const dataLists = ref<any[]>([])
|
||||
const timeFlag = ref(true)
|
||||
const frequencyShow = ref(false)
|
||||
const devCapacity = ref(0)
|
||||
const flag = ref(false)
|
||||
const typelist = [
|
||||
{
|
||||
label: '平均值',
|
||||
value: 'avg'
|
||||
},
|
||||
{
|
||||
label: '最大值',
|
||||
value: 'max'
|
||||
},
|
||||
{
|
||||
label: '最小值',
|
||||
value: 'min'
|
||||
},
|
||||
{
|
||||
label: 'CP95值',
|
||||
value: 'cp95'
|
||||
}
|
||||
]
|
||||
const zblist = ref<any[]>([])
|
||||
|
||||
const init = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
queryByCode('Web_Apf').then(res => {
|
||||
queryCsDictTree(res.data?.id).then(res => {
|
||||
zblist.value = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
formInline.statisticalId = zblist.value[0]?.value
|
||||
formInline.valueType = typelist[0].value
|
||||
resolve(null)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
const deviceTypeChange = (val: any, obj: any) => {
|
||||
flag.value = true
|
||||
nodeClick(obj)
|
||||
}
|
||||
const nodeClick = async (e: anyObj) => {
|
||||
if ((e.level == 2 || e.level == 3)) {
|
||||
formInline.devId = e.id
|
||||
loading.value = true
|
||||
if (zblist.value.length === 0) {
|
||||
await init()
|
||||
}
|
||||
getDevCapacity(formInline.devId)
|
||||
.then(res => {
|
||||
devCapacity.value = res.data
|
||||
|
||||
search()
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
const lineStyle = [
|
||||
{ type: 'solid', width: 3 },
|
||||
{ type: 'dotted', width: 3 },
|
||||
{ type: 'dashed', width: 3 }
|
||||
]
|
||||
const search = () => {
|
||||
if (timeFlag.value) {
|
||||
datePickerRef.value && datePickerRef.value.setInterval(5)
|
||||
timeFlag.value = false
|
||||
}
|
||||
loading.value = true
|
||||
formInline.startTime = datePickerRef.value.timeValue[0]
|
||||
formInline.endTime = datePickerRef.value.timeValue[1]
|
||||
if (!frequencyShow.value) {
|
||||
formInline.frequency = ''
|
||||
}
|
||||
|
||||
queryCommonStatisticalByTime(formInline)
|
||||
.then(({ data }: { data: any[] }) => {
|
||||
dataLists.value = data
|
||||
setEchart()
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
const setEchart = () => {
|
||||
loading.value = true
|
||||
let data = JSON.parse(JSON.stringify(dataLists.value))
|
||||
if (data.length) {
|
||||
let list = processingOfData(data, 'unit')
|
||||
|
||||
echartsData.value = {}
|
||||
let legend: any[] = []
|
||||
let xAxis: any[] = []
|
||||
let yAxis: any[] = []
|
||||
let series: any[] = []
|
||||
let color: any[] = []
|
||||
let title = ''
|
||||
data.forEach(item => {
|
||||
if (!xAxis.includes(item.time)) {
|
||||
xAxis.push(item.time)
|
||||
}
|
||||
// if (!legend.includes(item.anotherName)) {
|
||||
// legend.push(item.anotherName)
|
||||
// }
|
||||
})
|
||||
let units = Object.keys(list)
|
||||
// console.log('🚀 ~ .then ~ units:', units)
|
||||
for (let unit in list) {
|
||||
console.log('🚀 ~ .then ~ unit:', unit)
|
||||
let [min, max] = yMethod(list[unit].map((item: any) => item.statisticalData))
|
||||
yAxis.push({
|
||||
name: unit == 'null' ? '' : unit,
|
||||
type: 'value',
|
||||
// max: 10,
|
||||
min: min,
|
||||
max: max,
|
||||
// splitNumber: 5,
|
||||
// minInterval: 1,
|
||||
|
||||
axisLine: {
|
||||
show: true,
|
||||
//symbol: ["none", "arrow"],
|
||||
lineStyle: {
|
||||
color: '#333'
|
||||
}
|
||||
}
|
||||
})
|
||||
// processingOfData(list[unit], 'anotherName')
|
||||
let anotherList = processingOfData(list[unit], 'anotherName')
|
||||
for (let k in anotherList) {
|
||||
title = k
|
||||
let lineName = lineStyle[Object.keys(anotherList).indexOf(k)]
|
||||
let phaseList = processingOfData(anotherList[k], 'phase')
|
||||
for (let j in phaseList) {
|
||||
color.push(j == 'A' ? '#DAA520' : j == 'B' ? '#2E8B57' : j == 'C' ? '#A52a2a' : '#0000CC')
|
||||
legend.push(
|
||||
j == 'T' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j
|
||||
)
|
||||
series.push({
|
||||
name: j == 'T' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j,
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
|
||||
// data: phaseList[j].map(item => [
|
||||
// item.time,
|
||||
// Math.floor(item.statisticalData * 100) / 100,
|
||||
// unit,
|
||||
// lineName.type
|
||||
// ]),
|
||||
data: timeControl.value
|
||||
? completeTimeSeries(
|
||||
phaseList[j].map(item => [
|
||||
item.time,
|
||||
Math.floor(item.statisticalData * 100) / 100,
|
||||
unit,
|
||||
lineName.type
|
||||
])
|
||||
)
|
||||
: phaseList[j].map(item => [
|
||||
item.time,
|
||||
Math.floor(item.statisticalData * 100) / 100,
|
||||
unit,
|
||||
lineName.type
|
||||
]),
|
||||
|
||||
lineStyle: lineName,
|
||||
yAxisIndex: unit.indexOf(units)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echartsData.value = {
|
||||
title: {
|
||||
text: zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
|
||||
},
|
||||
tooltip: {
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
color: '#fff',
|
||||
fontSize: 16
|
||||
}
|
||||
},
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontStyle: 'normal',
|
||||
opacity: 0.35,
|
||||
fontSize: 14
|
||||
},
|
||||
backgroundColor: 'rgba(0,0,0,0.55)',
|
||||
borderWidth: 0,
|
||||
formatter(params: any) {
|
||||
const xname = params[0].value[0]
|
||||
let str = `${xname}<br>`
|
||||
params.forEach((el: any, index: any) => {
|
||||
let marker = ''
|
||||
if (el.value[3] == 'dashed') {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
|
||||
}
|
||||
} else {
|
||||
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
||||
}
|
||||
|
||||
str += `${marker}${el.seriesName.split('(')[0]}:${el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == 'null' ? '' : el.value[2]) : '-'
|
||||
}<br>`
|
||||
})
|
||||
return str
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
itemWidth: 20,
|
||||
itemHeight: 20,
|
||||
itemStyle: { opacity: 0 }, //去圆点
|
||||
type: 'scroll', // 开启滚动分页
|
||||
top: 25
|
||||
// data: legend
|
||||
},
|
||||
grid: {
|
||||
left: '20px',
|
||||
right: '40px',
|
||||
bottom: '50px',
|
||||
top: '80px',
|
||||
containLabel: true
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {}
|
||||
}
|
||||
},
|
||||
color: color,
|
||||
xAxis: {
|
||||
name: '',
|
||||
type: 'time',
|
||||
axisLabel: {
|
||||
formatter: {
|
||||
day: '{MM}-{dd}',
|
||||
month: '{MM}',
|
||||
year: '{yyyy}'
|
||||
}
|
||||
}
|
||||
|
||||
// boundaryGap: false,
|
||||
// data: xAxis,
|
||||
// axisLabel: {
|
||||
// formatter: function (value: string) {
|
||||
// return value.split(' ').join('\n')
|
||||
// }
|
||||
// },
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// // symbol: ["none", "arrow"],
|
||||
// lineStyle: {
|
||||
// color: '#333'
|
||||
// }
|
||||
// }
|
||||
},
|
||||
yAxis: yAxis,
|
||||
// [
|
||||
// {
|
||||
// name: '畸变率:(%)',
|
||||
// type: 'value',
|
||||
// // max: 10,
|
||||
// min: min1,
|
||||
// max: max1,
|
||||
// splitNumber: 5,
|
||||
// minInterval: 1,
|
||||
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// //symbol: ["none", "arrow"],
|
||||
// lineStyle: {
|
||||
// color: '#333'
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '电流:(A)',
|
||||
// type: 'value',
|
||||
// min: min,
|
||||
// max: max,
|
||||
// splitNumber: 5,
|
||||
// minInterval: 1,
|
||||
// splitLine: {
|
||||
// show: false
|
||||
// },
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// //symbol: ["none", "arrow"],
|
||||
// lineStyle: {
|
||||
// color: '#333'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
options: {
|
||||
series: series
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echartsData.value = null
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
const setTimeControl = () => {
|
||||
timeControl.value = !timeControl.value
|
||||
setEchart()
|
||||
}
|
||||
|
||||
const processingOfData = (data: any, type: string) => {
|
||||
let groupedData: any = {}
|
||||
|
||||
data.forEach(item => {
|
||||
if (!groupedData[item[type]]) {
|
||||
groupedData[item[type]] = []
|
||||
}
|
||||
groupedData[item[type]].push(item)
|
||||
})
|
||||
return groupedData
|
||||
}
|
||||
const frequencyFlag = () => {
|
||||
let name = zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
|
||||
if (name.includes('含有率') || name.includes('幅值')) {
|
||||
frequencyShow.value = true
|
||||
formInline.frequency = 2
|
||||
} else {
|
||||
frequencyShow.value = false
|
||||
}
|
||||
tableHeaderRef.value && tableHeaderRef.value?.computedSearchRow()
|
||||
}
|
||||
const selectChange = (flag: boolean) => {
|
||||
setTimeout(() => {
|
||||
echartHeight.value = mainHeight(23 + headerRef.value.offsetHeight)
|
||||
}, 100)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.analyze-apf {
|
||||
display: flex;
|
||||
|
||||
&-right {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
// padding: 10px 10px 10px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.el-select {
|
||||
min-width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,449 +1,28 @@
|
||||
<template>
|
||||
<div class="default-main analyze-apf" :style="{ height: pageHeight.height }" v-loading="loading">
|
||||
<DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
|
||||
<div class="analyze-apf-right" v-if="formInline.devId">
|
||||
<div ref="headerRef">
|
||||
<TableHeader :showSearch="false" ref="tableHeaderRef" @selectChange="selectChange"
|
||||
>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="时间:">
|
||||
<DatePicker ref="datePickerRef" :timeKeyList="['3', '4', '5']"></DatePicker>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计指标:">
|
||||
<el-select style="width: 200px" v-model.trim="formInline.statisticalId" filterable
|
||||
@change="frequencyFlag" placeholder="请选择">
|
||||
<el-option v-for="item in zblist" :key="item.value" :label="item.label"
|
||||
:value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="谐波次数:" v-show="frequencyShow">
|
||||
<el-select v-model.trim="formInline.frequency" filterable placeholder="请选择"
|
||||
style="width: 100px">
|
||||
<el-option v-for="item in 49" :key="item + 1" :label="item + 1"
|
||||
:value="item + 1"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="值类型:">
|
||||
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择">
|
||||
<el-option v-for="item in typelist" :key="item.value" :label="item.label"
|
||||
:value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" @click="search" icon="el-icon-Search">查询</el-button>
|
||||
<el-button :type="timeControl ? 'primary' : ''" icon="el-icon-Sort" @click="setTimeControl">
|
||||
缺失数据
|
||||
</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
|
||||
<el-empty description="暂无数据" v-if="!echartsData" style="flex: 1"></el-empty>
|
||||
<template v-else>
|
||||
<div :style="echartHeight">
|
||||
<MyEchart :options="echartsData" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<el-empty v-else description="请选择设备" class="analyze-apf-right" />
|
||||
<div class="default-main apf">
|
||||
<el-tabs type="border-card" v-model="activeName">
|
||||
<el-tab-pane label="APF" name="1">
|
||||
<APF v-if="activeName == '1'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="DVR" name="2">
|
||||
<DVR v-if="activeName == '2'" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
|
||||
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { getDevCapacity } from '@/api/cs-device-boot/capacity'
|
||||
import { queryCommonStatisticalByTime } from '@/api/cs-harmonic-boot/stable'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { yMethod, completeTimeSeries } from '@/utils/echartMethod'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
const timeControl = ref(false)
|
||||
import APF from './APF.vue'
|
||||
import DVR from '../DVR/index.vue'
|
||||
defineOptions({
|
||||
name: 'govern/analyze/APF'
|
||||
})
|
||||
const activeName = ref('1')
|
||||
|
||||
const tableHeaderRef = ref()
|
||||
const headerRef = ref()
|
||||
const pageHeight = mainHeight(20)
|
||||
const echartHeight = ref(mainHeight(80))
|
||||
const loading = ref(false)
|
||||
const echartsData = ref<any>(null)
|
||||
const datePickerRef = ref()
|
||||
const formInline = reactive({
|
||||
statisticalId: '',
|
||||
valueType: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
devId: '',
|
||||
frequency: ''
|
||||
})
|
||||
const dataLists = ref<any[]>([])
|
||||
const timeFlag = ref(true)
|
||||
const frequencyShow = ref(false)
|
||||
const devCapacity = ref(0)
|
||||
const flag = ref(false)
|
||||
const typelist = [
|
||||
{
|
||||
label: '平均值',
|
||||
value: 'avg'
|
||||
},
|
||||
{
|
||||
label: '最大值',
|
||||
value: 'max'
|
||||
},
|
||||
{
|
||||
label: '最小值',
|
||||
value: 'min'
|
||||
},
|
||||
{
|
||||
label: 'CP95值',
|
||||
value: 'cp95'
|
||||
}
|
||||
]
|
||||
const zblist = ref<any[]>([])
|
||||
|
||||
const init = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
queryByCode('Web_Apf').then(res => {
|
||||
queryCsDictTree(res.data?.id).then(res => {
|
||||
zblist.value = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
formInline.statisticalId = zblist.value[0]?.value
|
||||
formInline.valueType = typelist[0].value
|
||||
resolve(null)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
const deviceTypeChange = (val: any, obj: any) => {
|
||||
flag.value = true
|
||||
nodeClick(obj)
|
||||
}
|
||||
const nodeClick = async (e: anyObj) => {
|
||||
if ((e.level == 2 || e.level == 3)) {
|
||||
formInline.devId = e.id
|
||||
loading.value = true
|
||||
if (zblist.value.length === 0) {
|
||||
await init()
|
||||
}
|
||||
getDevCapacity(formInline.devId)
|
||||
.then(res => {
|
||||
devCapacity.value = res.data
|
||||
|
||||
search()
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
const lineStyle = [
|
||||
{ type: 'solid', width: 3 },
|
||||
{ type: 'dotted', width: 3 },
|
||||
{ type: 'dashed', width: 3 }
|
||||
]
|
||||
const search = () => {
|
||||
if (timeFlag.value) {
|
||||
datePickerRef.value && datePickerRef.value.setInterval(5)
|
||||
timeFlag.value = false
|
||||
}
|
||||
loading.value = true
|
||||
formInline.startTime = datePickerRef.value.timeValue[0]
|
||||
formInline.endTime = datePickerRef.value.timeValue[1]
|
||||
if (!frequencyShow.value) {
|
||||
formInline.frequency = ''
|
||||
}
|
||||
|
||||
queryCommonStatisticalByTime(formInline)
|
||||
.then(({ data }: { data: any[] }) => {
|
||||
dataLists.value = data
|
||||
setEchart()
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
const setEchart = () => {
|
||||
loading.value = true
|
||||
let data = JSON.parse(JSON.stringify(dataLists.value))
|
||||
if (data.length) {
|
||||
let list = processingOfData(data, 'unit')
|
||||
|
||||
echartsData.value = {}
|
||||
let legend: any[] = []
|
||||
let xAxis: any[] = []
|
||||
let yAxis: any[] = []
|
||||
let series: any[] = []
|
||||
let color: any[] = []
|
||||
let title = ''
|
||||
data.forEach(item => {
|
||||
if (!xAxis.includes(item.time)) {
|
||||
xAxis.push(item.time)
|
||||
}
|
||||
// if (!legend.includes(item.anotherName)) {
|
||||
// legend.push(item.anotherName)
|
||||
// }
|
||||
})
|
||||
let units = Object.keys(list)
|
||||
// console.log('🚀 ~ .then ~ units:', units)
|
||||
for (let unit in list) {
|
||||
console.log('🚀 ~ .then ~ unit:', unit)
|
||||
let [min, max] = yMethod(list[unit].map((item: any) => item.statisticalData))
|
||||
yAxis.push({
|
||||
name: unit == 'null' ? '' : unit,
|
||||
type: 'value',
|
||||
// max: 10,
|
||||
min: min,
|
||||
max: max,
|
||||
// splitNumber: 5,
|
||||
// minInterval: 1,
|
||||
|
||||
axisLine: {
|
||||
show: true,
|
||||
//symbol: ["none", "arrow"],
|
||||
lineStyle: {
|
||||
color: '#333'
|
||||
}
|
||||
}
|
||||
})
|
||||
// processingOfData(list[unit], 'anotherName')
|
||||
let anotherList = processingOfData(list[unit], 'anotherName')
|
||||
for (let k in anotherList) {
|
||||
title = k
|
||||
let lineName = lineStyle[Object.keys(anotherList).indexOf(k)]
|
||||
let phaseList = processingOfData(anotherList[k], 'phase')
|
||||
for (let j in phaseList) {
|
||||
color.push(j == 'A' ? '#DAA520' : j == 'B' ? '#2E8B57' : j == 'C' ? '#A52a2a' : '#0000CC')
|
||||
legend.push(
|
||||
j == 'T' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j
|
||||
)
|
||||
series.push({
|
||||
name: j == 'T' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j,
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
|
||||
// data: phaseList[j].map(item => [
|
||||
// item.time,
|
||||
// Math.floor(item.statisticalData * 100) / 100,
|
||||
// unit,
|
||||
// lineName.type
|
||||
// ]),
|
||||
data: timeControl.value
|
||||
? completeTimeSeries(
|
||||
phaseList[j].map(item => [
|
||||
item.time,
|
||||
Math.floor(item.statisticalData * 100) / 100,
|
||||
unit,
|
||||
lineName.type
|
||||
])
|
||||
)
|
||||
: phaseList[j].map(item => [
|
||||
item.time,
|
||||
Math.floor(item.statisticalData * 100) / 100,
|
||||
unit,
|
||||
lineName.type
|
||||
]),
|
||||
|
||||
lineStyle: lineName,
|
||||
yAxisIndex: unit.indexOf(units)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echartsData.value = {
|
||||
title: {
|
||||
text: zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
|
||||
},
|
||||
tooltip: {
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
color: '#fff',
|
||||
fontSize: 16
|
||||
}
|
||||
},
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontStyle: 'normal',
|
||||
opacity: 0.35,
|
||||
fontSize: 14
|
||||
},
|
||||
backgroundColor: 'rgba(0,0,0,0.55)',
|
||||
borderWidth: 0,
|
||||
formatter(params: any) {
|
||||
const xname = params[0].value[0]
|
||||
let str = `${xname}<br>`
|
||||
params.forEach((el: any, index: any) => {
|
||||
let marker = ''
|
||||
if (el.value[3] == 'dashed') {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
|
||||
}
|
||||
} else {
|
||||
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
||||
}
|
||||
|
||||
str += `${marker}${el.seriesName.split('(')[0]}:${el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == 'null' ? '' : el.value[2]) : '-'
|
||||
}<br>`
|
||||
})
|
||||
return str
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
itemWidth: 20,
|
||||
itemHeight: 20,
|
||||
itemStyle: { opacity: 0 }, //去圆点
|
||||
type: 'scroll', // 开启滚动分页
|
||||
top: 25
|
||||
// data: legend
|
||||
},
|
||||
grid: {
|
||||
left: '20px',
|
||||
right: '40px',
|
||||
bottom: '50px',
|
||||
top: '80px',
|
||||
containLabel: true
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {}
|
||||
}
|
||||
},
|
||||
color: color,
|
||||
xAxis: {
|
||||
name: '',
|
||||
type: 'time',
|
||||
axisLabel: {
|
||||
formatter: {
|
||||
day: '{MM}-{dd}',
|
||||
month: '{MM}',
|
||||
year: '{yyyy}'
|
||||
}
|
||||
}
|
||||
|
||||
// boundaryGap: false,
|
||||
// data: xAxis,
|
||||
// axisLabel: {
|
||||
// formatter: function (value: string) {
|
||||
// return value.split(' ').join('\n')
|
||||
// }
|
||||
// },
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// // symbol: ["none", "arrow"],
|
||||
// lineStyle: {
|
||||
// color: '#333'
|
||||
// }
|
||||
// }
|
||||
},
|
||||
yAxis: yAxis,
|
||||
// [
|
||||
// {
|
||||
// name: '畸变率:(%)',
|
||||
// type: 'value',
|
||||
// // max: 10,
|
||||
// min: min1,
|
||||
// max: max1,
|
||||
// splitNumber: 5,
|
||||
// minInterval: 1,
|
||||
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// //symbol: ["none", "arrow"],
|
||||
// lineStyle: {
|
||||
// color: '#333'
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '电流:(A)',
|
||||
// type: 'value',
|
||||
// min: min,
|
||||
// max: max,
|
||||
// splitNumber: 5,
|
||||
// minInterval: 1,
|
||||
// splitLine: {
|
||||
// show: false
|
||||
// },
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// //symbol: ["none", "arrow"],
|
||||
// lineStyle: {
|
||||
// color: '#333'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
options: {
|
||||
series: series
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echartsData.value = null
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
const setTimeControl = () => {
|
||||
timeControl.value = !timeControl.value
|
||||
setEchart()
|
||||
}
|
||||
|
||||
const processingOfData = (data: any, type: string) => {
|
||||
let groupedData: any = {}
|
||||
|
||||
data.forEach(item => {
|
||||
if (!groupedData[item[type]]) {
|
||||
groupedData[item[type]] = []
|
||||
}
|
||||
groupedData[item[type]].push(item)
|
||||
})
|
||||
return groupedData
|
||||
}
|
||||
const frequencyFlag = () => {
|
||||
let name = zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
|
||||
if (name.includes('含有率') || name.includes('幅值')) {
|
||||
frequencyShow.value = true
|
||||
formInline.frequency = 2
|
||||
} else {
|
||||
frequencyShow.value = false
|
||||
}
|
||||
tableHeaderRef.value && tableHeaderRef.value?.computedSearchRow()
|
||||
}
|
||||
const selectChange = (flag: boolean) => {
|
||||
setTimeout(() => {
|
||||
echartHeight.value = mainHeight(23 + headerRef.value.offsetHeight)
|
||||
}, 100)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.analyze-apf {
|
||||
display: flex;
|
||||
|
||||
&-right {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
padding: 10px 10px 10px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.el-select {
|
||||
min-width: 100px;
|
||||
:deep(.cn-tree) {
|
||||
padding: 0 10px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div>
|
||||
<div class="analyze-dvr" v-show="!isWaveCharts" :style="{ height: pageHeight.height }" v-loading="loading">
|
||||
<DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
|
||||
<!-- <DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree> -->
|
||||
<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>
|
||||
<TableHeader datePicker showExport @onResetForm="onResetForm">
|
||||
<template v-slot:select>
|
||||
<el-form-item label="触发类型">
|
||||
<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.eventType" clearable placeholder="请选择事件类型">
|
||||
<el-option v-for="item in eventList" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="位置">
|
||||
<el-select v-model.trim="tableStore.table.params.location" clearable placeholder="请选择位置">
|
||||
<el-option v-for="item in locationList" :key="item.value" :label="item.label"
|
||||
@@ -18,45 +24,24 @@
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table v-if="view" ref="tableRef"></Table>
|
||||
</div>
|
||||
<el-empty v-else description="请选择设备" class="analyze-dvr-right" />
|
||||
|
||||
<MultiCondition v-model:visible="filterVisible" :params="tableStore.table.params" ref="multiConditionRef"
|
||||
@confirm="onFilterConfirm" />
|
||||
|
||||
<!-- 补召日志 -->
|
||||
<analysisList ref="analysisListRef"></analysisList>
|
||||
</div>
|
||||
|
||||
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
|
||||
@handleHideCharts="isWaveCharts = false" :wp="wp" style="padding: 10px" />
|
||||
<!-- <div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<div v-if="view2" style="display: flex">
|
||||
<el-radio-group v-model.trim="value" @change="changeView">
|
||||
<el-radio-button label="一次值" :value="1" />
|
||||
<el-radio-button label="二次值" :value="2" />
|
||||
@handleHideCharts="isWaveCharts = false" :wp="wp" />
|
||||
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-button v-if="view2" @click="backbxlb" class="el-icon-refresh-right" icon="el-icon-Back"
|
||||
style="float: right">
|
||||
返回
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-tabs v-if="view2" class="default-main" v-model.trim="bxactiveName" @tab-click="bxhandleClick">
|
||||
<el-tab-pane label="瞬时波形" name="ssbx" class="boxbx pt10 pb10"
|
||||
:style="'height:' + bxecharts + ';overflow-y: scroll;'">
|
||||
<shushiboxi v-if="bxactiveName == 'ssbx' && showBoxi" :value="value" :boxoList="boxoList" :wp="wp">
|
||||
</shushiboxi>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="RMS波形" class="boxbx pt10 pb10" name="rmsbx"
|
||||
:style="'height:' + bxecharts + ';overflow-y: scroll;'">
|
||||
<rmsboxi v-if="bxactiveName == 'rmsbx' && showBoxi" :value="value" :boxoList="boxoList" :wp="wp">
|
||||
</rmsboxi>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -65,91 +50,58 @@ import { ref, nextTick, provide, onMounted } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import APFTree from '@/components/tree/govern/APFTree.vue'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import analysisList from '@/views/govern/device/control/analysisList/index.vue'
|
||||
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
|
||||
import { analyseWave } from '@/api/common'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
|
||||
import MultiCondition from '@/views/govern/alarm/multiCondition.vue'
|
||||
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { ElMessage } from 'element-plus'
|
||||
defineOptions({
|
||||
name: 'govern/analyze/DVR/index'
|
||||
})
|
||||
const pageHeight = mainHeight(20)
|
||||
const DeviceType = ref([])
|
||||
const pageHeight = mainHeight(80)
|
||||
const loading = ref(false)
|
||||
const view = ref(true)
|
||||
const view2 = ref(false)
|
||||
const showBoxi = ref(true)
|
||||
|
||||
const isWaveCharts = ref(false)
|
||||
const bxactiveName = ref('ssbx')
|
||||
const analysisListRef = ref()
|
||||
const boxoList: any = ref({})
|
||||
const wp = ref({})
|
||||
const eventList = ref([
|
||||
{
|
||||
value: 'Evt_Sys_DipStr',
|
||||
label: '电压暂降'
|
||||
},
|
||||
{
|
||||
value: 'Evt_Sys_SwlStr',
|
||||
label: '电压暂升'
|
||||
},
|
||||
{
|
||||
value: 'Evt_Sys_IntrStr',
|
||||
label: '电压中断'
|
||||
}
|
||||
])
|
||||
const locationList = ref([
|
||||
{
|
||||
value: 'grid',
|
||||
label: '电网侧'
|
||||
},
|
||||
{
|
||||
value: 'load',
|
||||
label: '负载侧'
|
||||
}
|
||||
])
|
||||
const filterVisible = ref(false)
|
||||
|
||||
const waveFormAnalysisRef = ref()
|
||||
const dictData = useDictData()
|
||||
const ReasonList: any = dictData.getBasicData('Event_Reason')
|
||||
const EventTypeList: any = dictData.getBasicData('Event_Type')
|
||||
const multiConditionRef = ref<InstanceType<typeof MultiCondition>>()
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-harmonic-boot/eventUser/queryEventpageWeb',
|
||||
method: 'POST',
|
||||
publicHeight: 60,
|
||||
column: [
|
||||
{
|
||||
field: 'index',
|
||||
title: '序号',
|
||||
width: '80',
|
||||
width: 80,
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '发生时刻', field: 'startTime', sortable: true, minWidth: 180 },
|
||||
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
|
||||
{ title: '暂降幅值(%)', minWidth: 120, field: 'evtParamVVaDepth', align: 'center', sortable: true, },
|
||||
{ title: '持续时间(s)', field: 'evtParamTm', minWidth: 110, align: 'center', sortable: true },
|
||||
{
|
||||
title: '暂降幅值(%)',
|
||||
field: 'evtParamVVaDepth',
|
||||
minWidth: 120,
|
||||
formatter: (row: any) => {
|
||||
let a = row.cellValue.split('%')[0] - 0
|
||||
return a ? a.toFixed(2) : '-'
|
||||
},
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: '持续时间(s)',
|
||||
field: 'evtParamTm',
|
||||
sortable: true,
|
||||
minWidth: 110,
|
||||
formatter: (row: any) => {
|
||||
const val = row.cellValue
|
||||
if (val === null || val === undefined || val === '' ) return '-'
|
||||
const num = Number(val)
|
||||
if (Number.isNaN(num)) return '-'
|
||||
return Math.floor(num * 10000) / 100
|
||||
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 },
|
||||
{ title: '触发类型', field: 'showName', minWidth: 100, align: 'center' },
|
||||
{
|
||||
title: '暂降原因', field: 'advanceReason', minWidth: 100, align: 'center', formatter: (row: any) => {
|
||||
return ReasonList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
@@ -160,7 +112,14 @@ const tableStore = new TableStore({
|
||||
return EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '未知'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
{ title: '监测点名称', field: 'lineName', minWidth: 130, align: 'center' },
|
||||
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true, },
|
||||
{ title: '设备名称', field: 'equipmentName', minWidth: 130, align: 'center' },
|
||||
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
|
||||
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
|
||||
{
|
||||
title: '发生位置', field: 'sagSource', minWidth: 120, align: 'center', formatter: (row: any) => {
|
||||
return row.cellValue == 1 ? '上游' : row.cellValue == 2 ? '下游' : '未知'
|
||||
@@ -168,43 +127,40 @@ const tableStore = new TableStore({
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
width: '180',
|
||||
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
text: '波形分析',
|
||||
title: '波形分析',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
loading: 'loading1',
|
||||
disabled: row => {
|
||||
return !row.wavePath && row.evtParamTm < 20
|
||||
return !row.wavePath
|
||||
},
|
||||
|
||||
click: async row => {
|
||||
row.loading1 = true
|
||||
|
||||
|
||||
await analyseWave(row.id)
|
||||
.then(res => {
|
||||
isWaveCharts.value = true
|
||||
loading.value = true
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
boxoList.value = row
|
||||
boxoList.value.featureAmplitude =
|
||||
row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth.split('%')[0] / 100 : null
|
||||
boxoList.value.persistTime =
|
||||
row.evtParamTm != '-' ? Math.floor(row.evtParamTm * 10000) / 100 : null
|
||||
// boxoList.value.systemType = 'WX'
|
||||
boxoList.value.systemType = 'YPT'
|
||||
loading.value = true
|
||||
isWaveCharts.value = true
|
||||
boxoList.value = {
|
||||
...row,
|
||||
engineeringName: row.projectName,
|
||||
persistTime: row.evtParamTm,
|
||||
featureAmplitude:
|
||||
row.evtParamVVaDepth != '-' ? (row.evtParamVVaDepth - 0) / 100 : null,
|
||||
systemType: 'YPT',
|
||||
}
|
||||
wp.value = res.data
|
||||
}
|
||||
loading.value = false
|
||||
@@ -217,18 +173,9 @@ const tableStore = new TableStore({
|
||||
nextTick(() => {
|
||||
waveFormAnalysisRef.value &&
|
||||
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
|
||||
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(false, 150)
|
||||
// waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(200, 190)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
text: '暂无波形',
|
||||
type: 'info',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return !(!row.wavePath && row.evtParamTm < 20)
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -239,7 +186,6 @@ const tableStore = new TableStore({
|
||||
loading: 'loading2',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
// && row.evtParamTm < 20
|
||||
return !row.wavePath
|
||||
},
|
||||
click: row => {
|
||||
@@ -260,17 +206,78 @@ const tableStore = new TableStore({
|
||||
row.loading2 = false
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
text: '暂不支持补召',
|
||||
type: 'info',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
let code = DeviceType.value.filter((item: any) => item.id == row.devType)[0]?.code
|
||||
return !(code == 'Direct_Connected_Device' || code == 'Gateway')
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
text: '波形补召',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-DataLine',
|
||||
render: 'basicButton',
|
||||
loading: 'loading2',
|
||||
disabled: row => {
|
||||
return row.wavePath
|
||||
},
|
||||
click: row => {
|
||||
let code = DeviceType.value.filter((item: any) => item.id == row.devType)[0]?.code
|
||||
|
||||
if (code == 'Portable') {
|
||||
// 便携式设备
|
||||
analysisListRef.value &&
|
||||
analysisListRef.value.open({
|
||||
lineId: row.lineId,
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
],
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.loading = false
|
||||
item.evtParamTm = item.evtParamTm.split('s')[0]
|
||||
item.evtParamTm =
|
||||
item.evtParamTm.split('s')[0] != '-' ? (item.evtParamTm.split('s')[0] - 0).toFixed(2) : '-'
|
||||
item.evtParamVVaDepth =
|
||||
item.evtParamVVaDepth.split('%')[0] != '-' ? (item.evtParamVVaDepth.split('%')[0] - 0).toFixed(2) : '-'
|
||||
})
|
||||
}
|
||||
})
|
||||
Object.assign(tableStore.table.params, {
|
||||
featureAmplitudeMin: undefined,
|
||||
featureAmplitudeMax: undefined,
|
||||
evtParamTmMin: undefined,
|
||||
evtParamTmMax: undefined,
|
||||
severityMin: undefined,
|
||||
severityMax: undefined,
|
||||
fileFlag: ''
|
||||
})
|
||||
const flag = ref(false)
|
||||
tableStore.table.params.type = 0
|
||||
tableStore.table.params.eventType = ''
|
||||
@@ -282,7 +289,7 @@ const deviceTypeChange = (val: any, obj: any) => {
|
||||
}
|
||||
const nodeClick = async (e: anyObj) => {
|
||||
// console.log("🚀 ~ nodeClick ~ e:", e)
|
||||
if ((e.level == 2 || e.level == 3) ) {
|
||||
if ((e.level == 2 || e.level == 3)) {
|
||||
loading.value = false
|
||||
tableStore.table.params.deviceId = e.id
|
||||
nextTick(() => {
|
||||
@@ -290,25 +297,31 @@ const nodeClick = async (e: anyObj) => {
|
||||
})
|
||||
}
|
||||
}
|
||||
const openFilterDialog = () => {
|
||||
filterVisible.value = true
|
||||
}
|
||||
const onFilterConfirm = () => {
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
// 重置
|
||||
const onResetForm = () => {
|
||||
filterVisible.value = false
|
||||
tableStore.table.params.cascader = ''
|
||||
tableStore.table.params.deviceTypeId = ''
|
||||
tableStore.table.params.engineeringid = ''
|
||||
tableStore.table.params.projectId = ''
|
||||
tableStore.table.params.deviceId = ''
|
||||
tableStore.table.params.deviceTypeName = ''
|
||||
multiConditionRef.value?.reset()
|
||||
}
|
||||
onMounted(() => {
|
||||
queryByCode('Device_Type').then(res => {
|
||||
queryCsDictTree(res.data.id).then((list: any) => {
|
||||
DeviceType.value = list.data
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const changeView = () => {
|
||||
showBoxi.value = false
|
||||
setTimeout(() => {
|
||||
showBoxi.value = true
|
||||
}, 0)
|
||||
}
|
||||
const bxhandleClick = (tab: any) => {
|
||||
if (tab.name == 'ssbx') {
|
||||
bxactiveName.value = 'ssbx'
|
||||
} else if (tab.name == 'rmsbx') {
|
||||
bxactiveName.value = 'rmsbx'
|
||||
}
|
||||
// console.log(tab, event);
|
||||
}
|
||||
const backbxlb = () => {
|
||||
view.value = true
|
||||
view2.value = false
|
||||
}
|
||||
const bxecharts = mainHeight(95).height as any
|
||||
</script>
|
||||
|
||||
@@ -320,7 +333,7 @@ const bxecharts = mainHeight(95).height as any
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
padding: 10px 10px 10px 0;
|
||||
// padding: 10px 10px 10px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item style="position: relative; z-index: 2" v-else>
|
||||
<span style="font-size: 16px; font-weight: bold; color: var(--el-color-primary)">
|
||||
治理设备/便携式设备不支持操作!
|
||||
MQTT通讯方式的设备暂不支持修改!
|
||||
</span>
|
||||
</el-form-item>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<el-form class="main-form overview_scroll" :label-position="'right'" label-width="130px"
|
||||
:inline="true" ref="mainForm" :model="formData">
|
||||
<!--工程-->
|
||||
<el-form-item id="id300" class="form-item" label="工程名称:"
|
||||
<el-form-item id="id300" class="form-item" label="工程名称"
|
||||
v-if="nodeLevel > 0 || pageStatus == 2" prop="engineeringParam.name"
|
||||
:rules="{ required: true, message: '请输入工程名称', trigger: 'blur' }">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model="formData.engineeringParam.name" placeholder="请输入工程名称"
|
||||
@@ -78,7 +78,7 @@
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<!-- 省下拉框 -->
|
||||
<el-form-item id="id200" class="form-item" label="省:" prop="engineeringParam.province"
|
||||
<el-form-item id="id200" class="form-item" label="省" prop="engineeringParam.province"
|
||||
v-if="nodeLevel > 0 || pageStatus == 2"
|
||||
:rules="{ required: true, message: '请选择省', trigger: 'change' }">
|
||||
<el-select clearable filterable v-model="formData.engineeringParam.province" :disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))
|
||||
@@ -88,7 +88,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 市下拉框 -->
|
||||
<el-form-item id="id200" class="form-item" label="市:" prop="engineeringParam.city"
|
||||
<el-form-item id="id200" class="form-item" label="市" prop="engineeringParam.city"
|
||||
v-if="nodeLevel > 0 || pageStatus == 2"
|
||||
:rules="{ required: true, message: '请选择市', trigger: 'change' }">
|
||||
<el-select clearable filterable v-model="formData.engineeringParam.city" :disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))
|
||||
@@ -98,13 +98,13 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="描述:" prop="engineeringParam.description"
|
||||
<el-form-item class="form-item" label="描述" prop="engineeringParam.description"
|
||||
v-if="nodeLevel > 0 || pageStatus == 2">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model="formData.engineeringParam.description" placeholder="请输入描述"
|
||||
:disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="排序:" prop="engineeringParam.sort"
|
||||
<el-form-item class="form-item" label="排序" prop="engineeringParam.sort"
|
||||
v-if="nodeLevel > 0 || pageStatus == 2"
|
||||
:rules="[{ required: true, message: '请输入排序', trigger: 'blur' }]">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model.trim.number="formData.engineeringParam.sort"
|
||||
@@ -120,7 +120,7 @@
|
||||
<el-tab-pane v-for="(item, index) in formData.projectInfoList" :key="index"
|
||||
:label="item.name ? item.name : '新建项目' + index" :name="index + ''">
|
||||
<div class="flex mt10">
|
||||
<el-form-item class="form-item" label="项目名称:"
|
||||
<el-form-item class="form-item" label="项目名称"
|
||||
:prop="'projectInfoList[' + index + '].name'" :rules="[
|
||||
{ required: true, message: '请输入项目名称', trigger: 'blur' }
|
||||
]">
|
||||
@@ -131,7 +131,7 @@
|
||||
)
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="地址:"
|
||||
<el-form-item class="form-item" label="地址"
|
||||
:prop="'projectInfoList[' + index + '].area'"
|
||||
:rules="[{ required: true, message: '请输入地址', trigger: 'blur' }]">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model="item.area" placeholder="请输入地址" :disabled="!(
|
||||
@@ -141,7 +141,7 @@
|
||||
)
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="描述:"
|
||||
<el-form-item class="form-item" label="描述"
|
||||
:prop="'projectInfoList[' + index + '].description'"
|
||||
:rules="[{ required: true, message: '请输入描述', trigger: 'blur' }]">
|
||||
<el-input maxlength="300" show-word-limit clearable v-model="item.description" placeholder="请输入描述"
|
||||
@@ -152,7 +152,7 @@
|
||||
)
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="拓扑图:" :prop="'projectInfoList[' + index + '].topoId'"
|
||||
<el-form-item label="拓扑图" :prop="'projectInfoList[' + index + '].topoId'"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择拓扑图', trigger: 'change' }
|
||||
]">
|
||||
@@ -175,7 +175,7 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="排序:"
|
||||
<el-form-item class="form-item" label="排序"
|
||||
:prop="'projectInfoList[' + index + '].sort'"
|
||||
:rules="[{ required: true, message: '请输入排序', trigger: 'blur' }]">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model.trim.number="item.sort" placeholder="请输入排序"
|
||||
@@ -202,7 +202,7 @@
|
||||
<el-tab-pane v-for="(busItem, bIndex) in formData.deviceInfoList" :key="bIndex"
|
||||
:label="busItem.name ? busItem.name : '新建设备' + bIndex" :name="bIndex + ''">
|
||||
<div class="flex mt10">
|
||||
<el-form-item class="form-item" label="设备名称:"
|
||||
<el-form-item class="form-item" label="设备名称"
|
||||
:prop="'deviceInfoList[' + bIndex + '].name'" :rules="[
|
||||
{ required: true, message: '请输入设备名称', trigger: 'blur' }
|
||||
]">
|
||||
@@ -214,7 +214,7 @@
|
||||
)
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item id="id200" class="form-item" label="设备类型:"
|
||||
<el-form-item id="id200" class="form-item" label="设备类型"
|
||||
:prop="'deviceInfoList[' + bIndex + '].devType'" :rules="[
|
||||
{ required: true, message: '请选择设备类型', trigger: 'change' }
|
||||
]">
|
||||
@@ -231,7 +231,7 @@
|
||||
:value=" item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item id="id200" class="form-item" label="设备型号:"
|
||||
<el-form-item id="id200" class="form-item" label="设备型号"
|
||||
:prop="'deviceInfoList[' + bIndex + '].devModel'" :rules="[
|
||||
{ required: true, message: '请选择设备型号', trigger: 'change' }
|
||||
]">
|
||||
@@ -248,12 +248,12 @@
|
||||
:value="option.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item id="id200" class="form-item" label="设备接入方式:"
|
||||
<el-form-item id="id200" class="form-item" label="设备通讯方式"
|
||||
:prop="'deviceInfoList[' + bIndex + '].devAccessMethod'" :rules="[
|
||||
{ required: true, message: '请选择设备接入方式', trigger: 'change' }
|
||||
{ required: true, message: '请选择设备通讯方式', trigger: 'change' }
|
||||
]">
|
||||
<el-select clearable filterable v-model="busItem.devAccessMethod"
|
||||
placeholder="请选择设备接入方式" style="width: 100%" :disabled="!(
|
||||
placeholder="请选择设备通讯方式" style="width: 100%" :disabled="!(
|
||||
(nodeLevel == 3 && pageStatus == 3) ||
|
||||
((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) &&
|
||||
pageStatus == 2)
|
||||
@@ -264,7 +264,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="设备mac地址:"
|
||||
<el-form-item class="form-item" label="设备mac地址"
|
||||
:prop="'deviceInfoList[' + bIndex + '].mac'" :rules="{
|
||||
required: true,
|
||||
message: '请输入设备mac地址',
|
||||
@@ -275,7 +275,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" v-if="busItem.devAccessMethod == 'CLD'"
|
||||
label="icd模型:" :prop="'deviceInfoList[' + bIndex + '].idc'">
|
||||
label="icd模型" :prop="'deviceInfoList[' + bIndex + '].idc'">
|
||||
<el-select clearable filterable v-model="busItem.icd"
|
||||
placeholder="请选择icd模型" style="width: 100%" :disabled="!(
|
||||
(nodeLevel == 3 && pageStatus == 3) ||
|
||||
@@ -288,7 +288,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="合同号:"
|
||||
<el-form-item class="form-item" label="合同号"
|
||||
:prop="'deviceInfoList[' + bIndex + '].cntractNo'">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model="busItem.cntractNo" placeholder="请输入合同号"
|
||||
:disabled="!(
|
||||
@@ -299,7 +299,7 @@
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="busItem.devAccessMethod == 'CLD'" class="form-item"
|
||||
label="所属前置机:" :prop="'deviceInfoList[' + bIndex + '].nodeId'" :rules="[
|
||||
label="所属前置机" :prop="'deviceInfoList[' + bIndex + '].nodeId'" :rules="[
|
||||
{ required: true, message: '请选择所属前置机', trigger: 'change' }
|
||||
]">
|
||||
<el-select clearable filterable v-model="busItem.nodeId"
|
||||
@@ -310,12 +310,12 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="busItem.devAccessMethod == 'CLD'" class="form-item"
|
||||
label="进程号:" :prop="'deviceInfoList[' + bIndex + '].nodeProcess'">
|
||||
label="进程号" :prop="'deviceInfoList[' + bIndex + '].nodeProcess'">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model="busItem.nodeProcess" placeholder="自动分配"
|
||||
:disabled="true"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="busItem.devAccessMethod == 'CLD'" class="form-item"
|
||||
label="日志等级:" :prop="'deviceInfoList[' + bIndex + '].devLogLevel'">
|
||||
label="日志等级" :prop="'deviceInfoList[' + bIndex + '].devLogLevel'">
|
||||
<el-select clearable filterable v-model="busItem.devLogLevel"
|
||||
placeholder="请选择日志等级" style="width: 100%" :disabled="!(
|
||||
(nodeLevel == 3 && pageStatus == 3) ||
|
||||
@@ -327,7 +327,7 @@
|
||||
:label="value.label" :value="value.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="是否启用:"
|
||||
<el-form-item class="form-item" label="是否启用"
|
||||
:prop="'deviceInfoList[' + bIndex + '].usageStatus'">
|
||||
<el-select clearable filterable v-model="busItem.usageStatus"
|
||||
placeholder="请选择是否启用" style="width: 100%" :disabled="!(
|
||||
@@ -340,7 +340,7 @@
|
||||
<el-option label="停用" :value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="是否支持升级:"
|
||||
<el-form-item class="form-item" label="是否支持升级"
|
||||
v-if="busItem.devAccessMethod == 'CLD'"
|
||||
:prop="'deviceInfoList[' + bIndex + '].upgrade'">
|
||||
<el-select clearable filterable v-model="busItem.upgrade"
|
||||
@@ -355,7 +355,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item
|
||||
label="接入:"
|
||||
label="接入"
|
||||
v-if="connectionMethod == 'MQTT' && busItem?.id"
|
||||
>
|
||||
<el-button
|
||||
@@ -368,7 +368,7 @@
|
||||
{{ accessLoading ? '接入中' : '接入' }}
|
||||
</el-button>
|
||||
</el-form-item> -->
|
||||
<el-form-item class="form-item" label="排序:"
|
||||
<el-form-item class="form-item" label="排序"
|
||||
:prop="'deviceInfoList[' + bIndex + '].sort'"
|
||||
:rules="[{ required: true, message: '请输入排序', trigger: 'blur' }]">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model.trim.number="busItem.sort"
|
||||
@@ -395,7 +395,7 @@
|
||||
<el-tab-pane v-for="(lineItem, lIndex) in formData.lineInfoList" :key="lIndex"
|
||||
:label="lineItem.name ? lineItem.name : '新建监测点' + lIndex" :name="lIndex + ''">
|
||||
<div class="flex mt10" v-if="connectionMethod != 'MQTT'">
|
||||
<el-form-item class="form-item" label="监测点名称:"
|
||||
<el-form-item class="form-item" label="监测点名称"
|
||||
:prop="'lineInfoList[' + lIndex + '].name'" :rules="{
|
||||
required: true,
|
||||
message: '请输入监测点名称',
|
||||
@@ -409,7 +409,7 @@
|
||||
)
|
||||
"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="线路号:"
|
||||
<el-form-item class="form-item" label="线路号"
|
||||
:prop="'lineInfoList[' + lIndex + '].lineNo'" :rules="{
|
||||
required: true,
|
||||
message: '请选择线路号',
|
||||
@@ -426,7 +426,7 @@
|
||||
:label="option.name" :value="option.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="接线方式:"
|
||||
<el-form-item class="form-item" label="接线方式"
|
||||
:prop="'lineInfoList[' + lIndex + '].conType'" :rules="{
|
||||
required: true,
|
||||
message: '请选择接线方式',
|
||||
@@ -443,7 +443,7 @@
|
||||
:label="option.name" :value="option.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="电压等级:"
|
||||
<el-form-item class="form-item" label="电压等级"
|
||||
:prop="'lineInfoList[' + lIndex + '].volGrade'" :rules="{
|
||||
required: true,
|
||||
message: '请选择电压等级',
|
||||
@@ -462,7 +462,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="PT变比:"
|
||||
<el-form-item class="form-item" label="PT变比"
|
||||
:prop="'lineInfoList[' + lIndex + '].ptRatio'"
|
||||
:rules="{ required: true, message: '请输入pt', trigger: 'blur' }">
|
||||
<div style="width: 100%; display: flex; justify-content: space-between">
|
||||
@@ -493,7 +493,7 @@
|
||||
"></el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="CT变比:"
|
||||
<el-form-item class="form-item" label="CT变比"
|
||||
:prop="'lineInfoList[' + lIndex + '].ctRatio'"
|
||||
:rules="{ required: true, message: '请输入ct', trigger: 'blur' }">
|
||||
<div style="width: 100%; display: flex; justify-content: space-between">
|
||||
@@ -524,7 +524,7 @@
|
||||
"></el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="统计间隔:"
|
||||
<el-form-item class="form-item" label="统计间隔"
|
||||
:prop="'lineInfoList[' + lIndex + '].lineInterval'" :rules="{
|
||||
required: true,
|
||||
message: '请选择统计间隔',
|
||||
@@ -542,7 +542,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="基准容量(MVA):"
|
||||
<el-form-item class="form-item" label="基准容量(MVA)"
|
||||
:prop="'lineInfoList[' + lIndex + '].basicCapacity'"
|
||||
:rules="{ required: true, message: '请输入基准容量', trigger: 'blur' }">
|
||||
<el-input maxlength="32" show-word-limit clearable-number :controls="false" :min="0"
|
||||
@@ -553,7 +553,7 @@
|
||||
)
|
||||
" placeholder="请输入基准容量(MVA)"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="短路容量(MVA):"
|
||||
<el-form-item class="form-item" label="短路容量(MVA)"
|
||||
:prop="'lineInfoList[' + lIndex + '].shortCircuitCapacity'"
|
||||
:rules="{ required: true, message: '请输入短路容量', trigger: 'blur' }">
|
||||
<el-input maxlength="32" show-word-limit clearable-number :controls="false" :min="0"
|
||||
@@ -565,7 +565,7 @@
|
||||
)
|
||||
" placeholder="请输入短路容量(MVA)"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="设备容量(MVA):"
|
||||
<el-form-item class="form-item" label="设备容量(MVA)"
|
||||
:prop="'lineInfoList[' + lIndex + '].devCapacity'"
|
||||
:rules="{ required: true, message: '请输入设备容量', trigger: 'blur' }">
|
||||
<el-input maxlength="32" show-word-limit clearable-number :controls="false" :min="0"
|
||||
@@ -576,7 +576,7 @@
|
||||
)
|
||||
" placeholder="请输入设备容量(MVA)"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="协议容量(MVA):"
|
||||
<el-form-item class="form-item" label="协议容量(MVA)"
|
||||
:prop="'lineInfoList[' + lIndex + '].protocolCapacity'"
|
||||
:rules="{ required: true, message: '请输入协议容量', trigger: 'blur' }">
|
||||
<el-input maxlength="32" show-word-limit clearable-number :controls="false" :min="0"
|
||||
@@ -587,7 +587,7 @@
|
||||
)
|
||||
" placeholder="请输入协议容量(MVA)"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="运行状态:"
|
||||
<el-form-item class="form-item" label="运行状态"
|
||||
:prop="'lineInfoList[' + lIndex + '].runStatus'" :rules="{
|
||||
required: true,
|
||||
message: '请选择运行状态',
|
||||
@@ -609,9 +609,9 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="用户对象:">
|
||||
<!-- <el-form-item class="form-item" label="敏感用户">
|
||||
<el-select clearable filterable v-model="lineItem.monitorUser"
|
||||
placeholder="请选择用户对象" :disabled="!(
|
||||
placeholder="请选择敏感用户" :disabled="!(
|
||||
(nodeLevel == 4 && pageStatus == 3) ||
|
||||
((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) &&
|
||||
pageStatus == 2)
|
||||
@@ -620,8 +620,8 @@
|
||||
<el-option v-for="option in userList" :key="option.id"
|
||||
:label="option.name" :value="option.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="监测对象类型:"
|
||||
</el-form-item> -->
|
||||
<el-form-item class="form-item" label="监测对象类型"
|
||||
>
|
||||
<el-select clearable filterable v-model="lineItem.monitorObj"
|
||||
placeholder="请选择监测对象类型" :disabled="!(
|
||||
@@ -634,7 +634,7 @@
|
||||
:label="option.name" :value="option.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="监测位置:"
|
||||
<el-form-item class="form-item" label="监测位置"
|
||||
>
|
||||
<el-select clearable filterable v-model="lineItem.position"
|
||||
placeholder="请选择监测位置" :disabled="!(
|
||||
@@ -647,7 +647,7 @@
|
||||
:label="option.name" :value="option.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="是否治理:"
|
||||
<!-- <el-form-item class="form-item" label="是否治理"
|
||||
>
|
||||
<el-select clearable filterable v-model="lineItem.govern"
|
||||
placeholder="请选择是否治理" :disabled="!(
|
||||
@@ -659,9 +659,9 @@
|
||||
<el-option label="未治理" :value="0" />
|
||||
<el-option label="已治理" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item class="form-item" label="日志等级:"
|
||||
<el-form-item class="form-item" label="日志等级"
|
||||
:prop="'lineInfoList[' + lIndex + '].lineLogLevel'" :rules="{
|
||||
required: true,
|
||||
message: '请选择日志等级',
|
||||
@@ -679,7 +679,7 @@
|
||||
:label="value.label" :value="value.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="是否主要监测点:"
|
||||
<el-form-item class="form-item" label="是否主要监测点"
|
||||
:prop="'lineInfoList[' + lIndex + '].isImportant'" :rules="{
|
||||
required: true,
|
||||
message: '请选择是否主要监测点',
|
||||
@@ -699,32 +699,32 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="flex mt10" v-else>
|
||||
<el-form-item class="form-item" label="监测点名称:">
|
||||
<el-form-item class="form-item" label="监测点名称">
|
||||
<el-input maxlength="32" show-word-limit clearable v-model="lineItem.name" placeholder="请输入监测点名称"
|
||||
:disabled="true"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="线路号:">
|
||||
<!-- <el-form-item class="form-item" label="线路号">
|
||||
<el-select clearable filterable v-model="lineItem.lineNo"
|
||||
placeholder="请选择线路号" :disabled="true">
|
||||
<el-option v-for="option in pointNumArr" :key="option.name"
|
||||
:label="option.name" :value="option.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="接线方式:">
|
||||
</el-form-item> -->
|
||||
<el-form-item class="form-item" label="接线方式">
|
||||
<el-select clearable filterable v-model="lineItem.conType"
|
||||
placeholder="请选择接线方式" :disabled="true">
|
||||
<el-option v-for="option in wiringTypeArr" :key="option.name"
|
||||
:label="option.name" :value="option.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="统计间隔:">
|
||||
<el-form-item class="form-item" label="统计间隔">
|
||||
<el-select clearable filterable v-model="lineItem.lineInterval"
|
||||
placeholder="请选择统计间隔" :disabled="true">
|
||||
<el-option v-for="option in lineSpaceArr" :key="option.name"
|
||||
:label="option.name" :value="option.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="PT变比:">
|
||||
<el-form-item class="form-item" label="PT变比">
|
||||
<div style="width: 100%; display: flex; justify-content: space-between">
|
||||
<el-input maxlength="32" show-word-limit clearable-number :controls="false" :min="1"
|
||||
style="width: 48%" oninput="value=value.replace(/[^\d]/g,'')"
|
||||
@@ -741,7 +741,7 @@
|
||||
v-model.number="lineItem.pt2Ratio" :disabled="true"></el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item" label="CT变比:">
|
||||
<el-form-item class="form-item" label="CT变比">
|
||||
<div style="width: 100%; display: flex; justify-content: space-between">
|
||||
<el-input maxlength="32" show-word-limit clearable-number :controls="false" :min="1"
|
||||
style="width: 48%" oninput="value=value.replace(/[^\d]/g,'')"
|
||||
@@ -759,7 +759,7 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="电压等级:">
|
||||
<el-form-item class="form-item" label="电压等级">
|
||||
<el-select clearable filterable v-model="lineItem.volGrade"
|
||||
placeholder="请选择电压等级" :disabled="true">
|
||||
<el-option v-for="option in voltageLevelOptions" :key="option.value"
|
||||
@@ -767,7 +767,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="监测位置:">
|
||||
<el-form-item class="form-item" label="监测位置">
|
||||
<el-select clearable filterable v-model="lineItem.position"
|
||||
placeholder="请选择监测位置" :disabled="true">
|
||||
<el-option v-for="option in linePosition" :key="option.id"
|
||||
@@ -775,8 +775,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-item" label="运行状态:">
|
||||
<!-- (0:运行;1:检修;2:停运;3:调试;4:退运) -->
|
||||
<!-- <el-form-item class="form-item" label="运行状态">
|
||||
<el-select clearable filterable v-model="lineItem.runStatus"
|
||||
placeholder="请选择通讯状态" :disabled="true">
|
||||
<el-option label="运行" :value="0" />
|
||||
@@ -785,7 +784,7 @@
|
||||
<el-option label="调试" :value="3" />
|
||||
<el-option label="退运" :value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -2816,7 +2815,7 @@ const area = async () => {
|
||||
|
||||
queryCsDictTree(res.data.id).then(res => {
|
||||
devTypeOptions.value = res.data
|
||||
console.log("🚀 ~ area ~ devTypeOptions.value:", devTypeOptions.value)
|
||||
console.log("🚀 ~ area ~ devTypeOptions.value", devTypeOptions.value)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1208,6 +1208,7 @@ const handleClick = async (tab?: any) => {
|
||||
}
|
||||
//运行趋势
|
||||
if (dataSet.value.includes('_devRunTrend')) {
|
||||
tableLoading.value=true
|
||||
setTimeout(async () => {
|
||||
if (tab.props != undefined) await (datePickerRef.value && datePickerRef.value?.setInterval(5))
|
||||
|
||||
|
||||
@@ -5,18 +5,26 @@
|
||||
<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-colgroup v-for="(item, colIndex) in section.abcItems" :key="`abc-${colIndex}`" align="center"
|
||||
:title="item.otherName" :width="getMetricWidth(section)">
|
||||
<vxe-column align="center" :field="`v${colIndex}A`" :title="item.phaseLabels[0]"
|
||||
<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.phaseLabels[1]"
|
||||
<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.phaseLabels[2]"
|
||||
<vxe-column align="center" :field="`v${colIndex}C`" :title="item.data.phaseLabels![2]"
|
||||
:width="getPhaseWidth(section)" :formatter="cellFormatter"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-column v-for="(item, colIndex) in section.scalarItems" :key="`scalar-${colIndex}`"
|
||||
align="center" :field="`s${colIndex}`" :title="item.otherName" :width="getMetricWidth(section)"
|
||||
show-overflow :formatter="cellFormatter"></vxe-column>
|
||||
<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>
|
||||
</vxe-colgroup>
|
||||
<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-table>
|
||||
@@ -32,27 +40,36 @@
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const ROW_WITH_ABC = 4
|
||||
const ROW_WITH_GROUP = 4
|
||||
const ROW_SCALAR_ONLY = 5
|
||||
|
||||
const SECONDARY_KEYWORDS = ['正序', '负序', '零序', '无功', '有功', '视在'] as const
|
||||
|
||||
interface SubColumn {
|
||||
subTitle: string
|
||||
value: unknown
|
||||
}
|
||||
|
||||
interface DisplayMetric {
|
||||
name: string
|
||||
otherName: string
|
||||
unit?: string | null
|
||||
type: 'abc' | 'scalar' | 't-multi'
|
||||
valueA?: unknown
|
||||
valueB?: unknown
|
||||
valueC?: unknown
|
||||
valueM?: unknown
|
||||
phaseLabels: [string, string, string]
|
||||
sort: number
|
||||
phaseLabels?: [string, string, string]
|
||||
subItems?: SubColumn[]
|
||||
}
|
||||
|
||||
interface MetricItem {
|
||||
type: 'abc' | 'scalar'
|
||||
type: 'abc' | 'scalar' | 't-multi'
|
||||
data: DisplayMetric
|
||||
}
|
||||
|
||||
interface TableSection {
|
||||
abcItems: DisplayMetric[]
|
||||
scalarItems: DisplayMetric[]
|
||||
columns: MetricItem[]
|
||||
row: Record<string, unknown>
|
||||
slotsPerRow: number
|
||||
emptySlotCount: number
|
||||
@@ -64,6 +81,7 @@ interface RawMetricItem {
|
||||
unit?: string | null
|
||||
phase?: string
|
||||
sort?: number
|
||||
otherNameSort?: number
|
||||
data?: unknown
|
||||
otherName?: string
|
||||
valueA?: unknown
|
||||
@@ -72,9 +90,14 @@ interface RawMetricItem {
|
||||
valueM?: unknown
|
||||
}
|
||||
|
||||
interface NameGroup {
|
||||
name: string
|
||||
items: RawMetricItem[]
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -87,6 +110,9 @@ 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 formatCellValue = (value: unknown): string | number => {
|
||||
if (value == null || value === 3.14159) return '/'
|
||||
return typeof value === 'number' || typeof value === 'string' ? value : String(value)
|
||||
@@ -94,140 +120,200 @@ const formatCellValue = (value: unknown): string | number => {
|
||||
|
||||
const cellFormatter = ({ cellValue }: { cellValue: unknown }) => formatCellValue(cellValue)
|
||||
|
||||
const buildOtherName = (name: string, unit?: string | null) => (unit ? `${name}(${unit})` : name)
|
||||
const buildTitle = (name: string, unit?: string | null) => (unit ? `${name}(${unit})` : name)
|
||||
|
||||
const getSharedUnit = (items: RawMetricItem[]) => {
|
||||
const units = [...new Set(items.map(item => item.unit ?? null))]
|
||||
return units.length === 1 ? units[0] : null
|
||||
}
|
||||
|
||||
const getPrimaryTitle = (item: DisplayMetric) => buildTitle(item.name, item.unit)
|
||||
|
||||
const getScalarTitle = (item: DisplayMetric) => buildTitle(item.otherName || item.name, item.unit)
|
||||
|
||||
const isNewFormat = (item: RawMetricItem) => item.targetId != null && item.phase != null && 'data' in item
|
||||
|
||||
const hasAbcValues = (item: DisplayMetric | RawMetricItem) =>
|
||||
item.valueA != null || item.valueB != null || item.valueC != null
|
||||
const isGroupedColumn = (item: MetricItem) => item.type === 'abc' || item.type === 't-multi'
|
||||
|
||||
const normalizeOldItem = (item: RawMetricItem): DisplayMetric => ({
|
||||
otherName: item.otherName || buildOtherName(item.name || ''),
|
||||
const extractSubTitle = (otherName: string) => {
|
||||
for (const keyword of SECONDARY_KEYWORDS) {
|
||||
if (otherName.includes(keyword)) return keyword
|
||||
}
|
||||
return otherName
|
||||
}
|
||||
|
||||
const groupByName = (list: RawMetricItem[]): NameGroup[] => {
|
||||
const order: string[] = []
|
||||
const map = new Map<string, RawMetricItem[]>()
|
||||
|
||||
list.forEach(item => {
|
||||
const name = item.name || ''
|
||||
if (!map.has(name)) {
|
||||
order.push(name)
|
||||
map.set(name, [])
|
||||
}
|
||||
map.get(name)!.push(item)
|
||||
})
|
||||
|
||||
return order.map(name => ({ name, items: map.get(name)! }))
|
||||
}
|
||||
|
||||
const buildAbcMetric = (name: string, items: RawMetricItem[]): DisplayMetric => {
|
||||
const phaseMap: Record<string, unknown> = {}
|
||||
items.forEach(item => {
|
||||
if (item.phase != null) phaseMap[item.phase] = item.data
|
||||
})
|
||||
|
||||
for (const { keys, labels } of PHASE_GROUPS) {
|
||||
if (keys.some(key => phaseMap[key] != null)) {
|
||||
return {
|
||||
name,
|
||||
otherName: items[0].otherName || name,
|
||||
unit: items[0].unit ?? null,
|
||||
type: 'abc',
|
||||
valueA: phaseMap[keys[0]],
|
||||
valueB: phaseMap[keys[1]],
|
||||
valueC: phaseMap[keys[2]],
|
||||
phaseLabels: labels,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
otherName: items[0].otherName || name,
|
||||
unit: items[0].unit ?? null,
|
||||
type: 'abc',
|
||||
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相'],
|
||||
}
|
||||
}
|
||||
|
||||
const buildTMetric = (name: string, items: RawMetricItem[]): DisplayMetric => {
|
||||
const needSubHeader = items.some(item => (item.otherName || item.name || '') !== name)
|
||||
|
||||
if (!needSubHeader) {
|
||||
return {
|
||||
name,
|
||||
otherName: items[0].otherName || name,
|
||||
unit: items[0].unit ?? null,
|
||||
type: 'scalar',
|
||||
valueM: items[0].data,
|
||||
}
|
||||
}
|
||||
|
||||
const sharedUnit = getSharedUnit(items)
|
||||
const unitsDiffer = sharedUnit == null && new Set(items.map(item => item.unit ?? null)).size > 1
|
||||
|
||||
return {
|
||||
name,
|
||||
otherName: name,
|
||||
unit: sharedUnit,
|
||||
type: 't-multi',
|
||||
subItems: items.map(item => {
|
||||
const keyword = extractSubTitle(item.otherName || item.name || '')
|
||||
return {
|
||||
subTitle: unitsDiffer ? buildTitle(keyword, item.unit) : keyword,
|
||||
value: item.data,
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
const groupToMetric = (group: NameGroup): DisplayMetric => {
|
||||
const { name, items } = group
|
||||
const phases = items.map(item => item.phase)
|
||||
const allT = phases.every(phase => phase === 'T')
|
||||
|
||||
if (allT) return buildTMetric(name, items)
|
||||
|
||||
return buildAbcMetric(name, items)
|
||||
}
|
||||
|
||||
const normalizeOldItem = (item: RawMetricItem): DisplayMetric => {
|
||||
const name = item.name || ''
|
||||
const otherName = item.otherName || name
|
||||
const hasAbc = item.valueA != null || item.valueB != null || item.valueC != null
|
||||
|
||||
if (hasAbc) {
|
||||
return {
|
||||
name,
|
||||
otherName,
|
||||
unit: item.unit ?? null,
|
||||
type: 'abc',
|
||||
valueA: item.valueA,
|
||||
valueB: item.valueB,
|
||||
valueC: item.valueC,
|
||||
valueM: item.valueM,
|
||||
phaseLabels: ['A相', 'B相', 'C相'],
|
||||
sort: item.sort ?? 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getHarmonicOrder = (name: string) => {
|
||||
const match = name.match(/^(\d+(?:\.\d+)?)次/)
|
||||
return match ? parseFloat(match[1]) : null
|
||||
}
|
||||
|
||||
const getGroupKey = (item: RawMetricItem) => `${item.targetId}_${item.name}`
|
||||
|
||||
const groupNewFormatData = (list: RawMetricItem[]): DisplayMetric[] => {
|
||||
const groupMap = new Map<string, { name: string; unit: string | null; sort: number; phases: Record<string, unknown> }>()
|
||||
|
||||
list.forEach(item => {
|
||||
const key = getGroupKey(item)
|
||||
if (!groupMap.has(key)) {
|
||||
groupMap.set(key, {
|
||||
name: item.name || '',
|
||||
return {
|
||||
name,
|
||||
otherName,
|
||||
unit: item.unit ?? null,
|
||||
sort: item.sort ?? 0,
|
||||
phases: {},
|
||||
})
|
||||
type: 'scalar',
|
||||
valueM: item.valueM,
|
||||
}
|
||||
if (item.phase != null) {
|
||||
groupMap.get(key)!.phases[item.phase] = item.data
|
||||
}
|
||||
})
|
||||
|
||||
return Array.from(groupMap.values())
|
||||
.sort((a, b) => {
|
||||
if (a.sort !== b.sort) return a.sort - b.sort
|
||||
const orderA = getHarmonicOrder(a.name)
|
||||
const orderB = getHarmonicOrder(b.name)
|
||||
if (orderA != null && orderB != null) return orderA - orderB
|
||||
return a.name.localeCompare(b.name, 'zh-CN')
|
||||
})
|
||||
.map(group => {
|
||||
const otherName = buildOtherName(group.name, group.unit)
|
||||
const phaseKeys = Object.keys(group.phases)
|
||||
|
||||
if (phaseKeys.length === 1 && phaseKeys[0] === 'T') {
|
||||
return {
|
||||
otherName,
|
||||
valueM: group.phases.T,
|
||||
phaseLabels: ['A相', 'B相', 'C相'],
|
||||
sort: group.sort,
|
||||
}
|
||||
}
|
||||
|
||||
for (const { keys, labels } of PHASE_GROUPS) {
|
||||
if (keys.some(key => group.phases[key] != null)) {
|
||||
return {
|
||||
otherName,
|
||||
valueA: group.phases[keys[0]],
|
||||
valueB: group.phases[keys[1]],
|
||||
valueC: group.phases[keys[2]],
|
||||
phaseLabels: labels,
|
||||
sort: group.sort,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
otherName,
|
||||
valueM: phaseKeys.length === 1 ? group.phases[phaseKeys[0]] : undefined,
|
||||
valueA: group.phases.A ?? group.phases.AB,
|
||||
valueB: group.phases.B ?? group.phases.BC,
|
||||
valueC: group.phases.C ?? group.phases.CA,
|
||||
phaseLabels: group.phases.AB != null ? ['AB', 'BC', 'CA'] : ['A相', 'B相', 'C相'],
|
||||
sort: group.sort,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const normalizeMetrics = (data: RawMetricItem[]): DisplayMetric[] => {
|
||||
if (!data?.length) return []
|
||||
if (isNewFormat(data[0])) {
|
||||
return groupNewFormatData(data)
|
||||
return groupByName(data).map(groupToMetric)
|
||||
}
|
||||
return data.map(normalizeOldItem).sort((a, b) => a.sort - b.sort)
|
||||
return data.map(normalizeOldItem)
|
||||
}
|
||||
|
||||
const buildRow = (abcItems: DisplayMetric[], scalarItems: DisplayMetric[]) => {
|
||||
const toMetricItem = (data: DisplayMetric): MetricItem => ({
|
||||
type: data.type,
|
||||
data,
|
||||
})
|
||||
|
||||
const buildRow = (columns: MetricItem[]) => {
|
||||
const row: Record<string, unknown> = {}
|
||||
abcItems.forEach((item, index) => {
|
||||
row[`v${index}A`] = item.valueA
|
||||
row[`v${index}B`] = item.valueB
|
||||
row[`v${index}C`] = item.valueC
|
||||
columns.forEach((item, colIndex) => {
|
||||
if (item.type === 'abc') {
|
||||
row[`v${colIndex}A`] = item.data.valueA
|
||||
row[`v${colIndex}B`] = item.data.valueB
|
||||
row[`v${colIndex}C`] = item.data.valueC
|
||||
} else if (item.type === 't-multi') {
|
||||
item.data.subItems?.forEach((sub, subIndex) => {
|
||||
row[`t${colIndex}_${subIndex}`] = sub.value
|
||||
})
|
||||
scalarItems.forEach((item, index) => {
|
||||
row[`s${index}`] = item.valueM
|
||||
} else {
|
||||
row[`s${colIndex}`] = item.data.valueM
|
||||
}
|
||||
})
|
||||
return row
|
||||
}
|
||||
|
||||
const buildTableSections = (abcList: DisplayMetric[], scalarList: DisplayMetric[]) => {
|
||||
const unified: MetricItem[] = [
|
||||
...abcList.map(data => ({ type: 'abc' as const, data })),
|
||||
...scalarList.map(data => ({ type: 'scalar' as const, data })),
|
||||
]
|
||||
|
||||
const buildTableSections = (metrics: DisplayMetric[]) => {
|
||||
const unified = metrics.map(toMetricItem)
|
||||
const sections: TableSection[] = []
|
||||
let index = 0
|
||||
|
||||
while (index < unified.length) {
|
||||
const hasAbc = unified[index].type === 'abc'
|
||||
const maxCount = hasAbc ? ROW_WITH_ABC : ROW_SCALAR_ONLY
|
||||
const chunk = unified.slice(index, index + maxCount)
|
||||
index += chunk.length
|
||||
const remaining = unified.length - index
|
||||
let slotsPerRow = isGroupedColumn(unified[index]) ? ROW_WITH_GROUP : ROW_SCALAR_ONLY
|
||||
|
||||
if (slotsPerRow === ROW_SCALAR_ONLY) {
|
||||
const peekCount = Math.min(ROW_SCALAR_ONLY, remaining)
|
||||
if (unified.slice(index, index + peekCount).some(isGroupedColumn)) {
|
||||
slotsPerRow = ROW_WITH_GROUP
|
||||
}
|
||||
}
|
||||
|
||||
const columns = unified.slice(index, index + Math.min(slotsPerRow, remaining))
|
||||
index += columns.length
|
||||
|
||||
const abcItems = chunk.filter(item => item.type === 'abc').map(item => item.data)
|
||||
const scalarItems = chunk.filter(item => item.type === 'scalar').map(item => item.data)
|
||||
const slotsPerRow = abcItems.length > 0 ? ROW_WITH_ABC : ROW_SCALAR_ONLY
|
||||
const metricCount = abcItems.length + scalarItems.length
|
||||
sections.push({
|
||||
abcItems,
|
||||
scalarItems,
|
||||
row: buildRow(abcItems, scalarItems),
|
||||
columns,
|
||||
row: buildRow(columns),
|
||||
slotsPerRow,
|
||||
emptySlotCount: slotsPerRow - metricCount,
|
||||
emptySlotCount: Math.max(0, slotsPerRow - columns.length),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -236,11 +322,7 @@ const buildTableSections = (abcList: DisplayMetric[], scalarList: DisplayMetric[
|
||||
|
||||
const setData = (data: RawMetricItem[], _targetType?: unknown) => {
|
||||
const list = JSON.parse(JSON.stringify(data || [])) as RawMetricItem[]
|
||||
const metrics = normalizeMetrics(list)
|
||||
const abcList = metrics.filter(item => hasAbcValues(item))
|
||||
const scalarList = metrics.filter(item => !hasAbcValues(item))
|
||||
|
||||
tableSections.value = buildTableSections(abcList, scalarList)
|
||||
tableSections.value = buildTableSections(normalizeMetrics(list))
|
||||
}
|
||||
|
||||
defineExpose({ setData })
|
||||
|
||||
@@ -73,7 +73,7 @@ const tableStore: any = new TableStore({
|
||||
sortable: true,
|
||||
formatter: (row: any) => {
|
||||
//row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
|
||||
row.cellValue = row.cellValue != null ? Number(row.cellValue).toFixed(2) : '-'
|
||||
row.cellValue = row.cellValue != null ? Number(row.cellValue).toFixed(2) : '/'
|
||||
if (String(row.cellValue).split('.')[1] == '00') {
|
||||
row.cellValue = String(row.cellValue).split('.')[0]
|
||||
}
|
||||
@@ -88,7 +88,7 @@ const tableStore: any = new TableStore({
|
||||
formatter: (row: any) => {
|
||||
// console.log('🚀 ~ row.cellValue:', row.cellValue)
|
||||
|
||||
return row.cellValue ? (row.cellValue - 0).toFixed(2) : '-'
|
||||
return row.cellValue ? (row.cellValue - 0).toFixed(2) : '/'
|
||||
},
|
||||
sortable: true
|
||||
},
|
||||
@@ -97,7 +97,7 @@ const tableStore: any = new TableStore({
|
||||
title: '相别',
|
||||
minWidth: 80,
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '-'
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -151,12 +151,14 @@ const tableStore: any = new TableStore({
|
||||
loading.value = true
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
boxoList.value = row
|
||||
boxoList.value.systemType = 'YPT'
|
||||
boxoList.value.engineeringName = tableParams.value.engineeringName
|
||||
boxoList.value.featureAmplitude =
|
||||
row.featureAmplitude != null ? Number(row.featureAmplitude / 100) : '-'
|
||||
boxoList.value.persistTime = row.persistTime ? row.persistTime.toFixed(2) : '-'
|
||||
boxoList.value = {
|
||||
...row,
|
||||
systemType: 'YPT',
|
||||
engineeringName: tableParams.value.engineeringName,
|
||||
featureAmplitude:
|
||||
row.featureAmplitude != null ? Number(row.featureAmplitude / 100) : '-',
|
||||
persistTime: row.persistTime ? row.persistTime.toFixed(2) : '-',
|
||||
}
|
||||
wp.value = res.data
|
||||
view.value = false
|
||||
view2.value = true
|
||||
|
||||
@@ -127,6 +127,8 @@ const countOptions: any = ref([])
|
||||
// Harmonic_Type
|
||||
// portable-harmonic
|
||||
const legendDictList: any = ref([])
|
||||
|
||||
|
||||
queryByCode(
|
||||
props?.TrendList?.lineType == 0
|
||||
? 'apf-harmonic'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-show="!isWaveCharts">
|
||||
<TableHeader showExport ref="headerRef" @onResetForm="onResetForm">
|
||||
<TableHeader showExport ref="headerRef" :showQuery="false" @onResetForm="onResetForm">
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
|
||||
</template>
|
||||
@@ -57,7 +57,8 @@ const multiConditionRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-harmonic-boot/data/getEventByItem',
|
||||
method: 'POST',
|
||||
paramsPOST: true,
|
||||
// paramsPOST: true,
|
||||
exportName: '暂态事件',
|
||||
showPage: false,
|
||||
publicHeight: 355,
|
||||
column: [
|
||||
@@ -151,10 +152,12 @@ const tableStore = new TableStore({
|
||||
isWaveCharts.value = true
|
||||
row.loading1 = false
|
||||
if (res != undefined) {
|
||||
boxoList.value = row
|
||||
boxoList.value.featureAmplitude =
|
||||
row.featureAmplitude != '-' ? (row.featureAmplitude - 0) / 100 : null
|
||||
boxoList.value.systemType = 'YPT'
|
||||
boxoList.value = {
|
||||
...row,
|
||||
featureAmplitude:
|
||||
row.featureAmplitude != '-' ? (row.featureAmplitude - 0) / 100 : null,
|
||||
systemType: 'YPT',
|
||||
}
|
||||
wp.value = res.data
|
||||
|
||||
|
||||
|
||||
@@ -78,17 +78,19 @@ export default {
|
||||
this.leftData = val
|
||||
const config = useConfig()
|
||||
this.leftData.forEach(item => {
|
||||
item.icon = 'el-icon-HomeFilled'
|
||||
item.color = config.getColorVal('elementUiPrimary')
|
||||
item.icon = 'el-icon-Platform'
|
||||
// item.color = config.getColorVal('elementUiPrimary')
|
||||
item.color = item.runStatus == 2 ? '#2ab914' : "#e26257"
|
||||
item.children.forEach(item2 => {
|
||||
item2.icon = 'el-icon-List'
|
||||
item2.color = config.getColorVal('elementUiPrimary')
|
||||
item2.icon = 'local-监测点'
|
||||
// item2.color = config.getColorVal('elementUiPrimary')
|
||||
item2.color = item.runStatus == 2 ? '#2ab914' : "#e26257"
|
||||
item2.children.forEach(item3 => {
|
||||
item3.icon = 'el-icon-Platform'
|
||||
item3.icon = 'el-icon-List'
|
||||
item3.color = config.getColorVal('elementUiPrimary')
|
||||
if (item3.comFlag === 1) {
|
||||
item3.color = '#e26257 !important'
|
||||
}
|
||||
// if (item3.runStatus === 1) {
|
||||
// item3.color = '#e26257 !important'
|
||||
// }
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -100,17 +102,19 @@ export default {
|
||||
const config = useConfig()
|
||||
this.$emit('getData', this.rightData)
|
||||
this.rightData.forEach(item => {
|
||||
item.icon = 'el-icon-HomeFilled'
|
||||
item.color = config.getColorVal('elementUiPrimary')
|
||||
item.icon = 'el-icon-Platform'
|
||||
// item.color = config.getColorVal('elementUiPrimary')
|
||||
item.color = item.runStatus == 2 ? '#2ab914' : "#e26257"
|
||||
item.children.forEach(item2 => {
|
||||
item2.icon = 'el-icon-List'
|
||||
item2.color = config.getColorVal('elementUiPrimary')
|
||||
item2.icon = 'local-监测点'
|
||||
// item2.color = config.getColorVal('elementUiPrimary')
|
||||
item2.color = item.runStatus == 2 ? '#2ab914' : "#e26257"
|
||||
item2.children.forEach(item3 => {
|
||||
item3.icon = 'el-icon-Platform'
|
||||
item3.icon = 'el-icon-List'
|
||||
item3.color = config.getColorVal('elementUiPrimary')
|
||||
if (item3.comFlag === 1) {
|
||||
item3.color = '#e26257 !important'
|
||||
}
|
||||
// if (item3.runStatus === 1) {
|
||||
// item3.color = '#e26257 !important'
|
||||
// }
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
93
src/views/govern/log/components/front.vue
Normal file
93
src/views/govern/log/components/front.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div>
|
||||
<TableHeader datePicker showExport>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="设备名称">
|
||||
<el-input maxlength="32" show-word-limit
|
||||
|
||||
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
placeholder="请输入设备名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" :isGroup="true" />
|
||||
</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/debug'
|
||||
})
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-device-boot/process/queryPage',
|
||||
method: 'POST',
|
||||
publicHeight: 65,
|
||||
column: [
|
||||
{
|
||||
field: 'index',
|
||||
title: '序号',
|
||||
width: '80',
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '设备名称', field: 'devName', align: 'center' },
|
||||
{ title: '操作用户', field: 'operatorName', align: 'center' },
|
||||
{
|
||||
title: '操作内容',
|
||||
field: 'process',
|
||||
align: 'center',
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue == 1
|
||||
? '设备登记'
|
||||
: row.cellValue == 2
|
||||
? '功能调试'
|
||||
: row.cellValue == 3
|
||||
? '出厂调试'
|
||||
: row.cellValue == 4
|
||||
? '设备投运'
|
||||
: ''
|
||||
}
|
||||
},
|
||||
{ title: '开始时间', field: 'startTime', align: 'center', sortable: true },
|
||||
{
|
||||
title: '结束时间',
|
||||
field: 'endTime',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.result = item.result === 1 ? '成功' : '失败'
|
||||
// for (let key in item) {
|
||||
// if (typeof item[key] !== 'number') {
|
||||
// item[key] = item[key] || '/'
|
||||
// }
|
||||
// }
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.searchState = 0
|
||||
tableStore.table.params.sortBy = ''
|
||||
tableStore.table.params.orderBy = ''
|
||||
tableStore.table.params.searchValue = ''
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
</script>
|
||||
@@ -1,92 +1,29 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker showExport>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="设备名称">
|
||||
<el-input maxlength="32" show-word-limit
|
||||
|
||||
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
placeholder="请输入设备名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" :isGroup="true" />
|
||||
<div class="default-main apf">
|
||||
<el-tabs type="border-card" v-model="activeName">
|
||||
<el-tab-pane label="治理交互日志" name="1">
|
||||
<governance v-if="activeName == '1'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="前置交互日志" name="2">
|
||||
<front v-if="activeName == '2'" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</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'
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
import front from './components/front.vue'
|
||||
import governance from './components/governance.vue'
|
||||
defineOptions({
|
||||
name: 'govern/log/debug'
|
||||
})
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-device-boot/process/queryPage',
|
||||
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: 'devName', align: 'center' },
|
||||
{ title: '操作用户', field: 'operatorName', align: 'center' },
|
||||
{
|
||||
title: '操作内容',
|
||||
field: 'process',
|
||||
align: 'center',
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue == 1
|
||||
? '设备登记'
|
||||
: row.cellValue == 2
|
||||
? '功能调试'
|
||||
: row.cellValue == 3
|
||||
? '出厂调试'
|
||||
: row.cellValue == 4
|
||||
? '设备投运'
|
||||
: ''
|
||||
}
|
||||
},
|
||||
{ title: '开始时间', field: 'startTime', align: 'center', sortable: true },
|
||||
{
|
||||
title: '结束时间',
|
||||
field: 'endTime',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
formatter: (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
}
|
||||
],
|
||||
const activeName = ref('1')
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.result = item.result === 1 ? '成功' : '失败'
|
||||
// for (let key in item) {
|
||||
// if (typeof item[key] !== 'number') {
|
||||
// item[key] = item[key] || '/'
|
||||
// }
|
||||
// }
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.searchState = 0
|
||||
tableStore.table.params.sortBy = ''
|
||||
tableStore.table.params.orderBy = ''
|
||||
tableStore.table.params.searchValue = ''
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.cn-tree) {
|
||||
padding: 0 10px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
256
src/views/govern/manage/components/factoryForm.vue
Normal file
256
src/views/govern/manage/components/factoryForm.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<el-dialog :title="dialogTitle" v-model="visible" :close-on-click-modal="false" :before-close="handleBeforeClose"
|
||||
draggable width="800px">
|
||||
<el-form :model="form" label-width="auto" :rules="rules" ref="ruleFormRef" class="form-two">
|
||||
<el-form-item label="设备名称" prop="name">
|
||||
<el-input maxlength="32" show-word-limit v-model.trim="form.name" autocomplete="off" clearable
|
||||
placeholder="请输入(项目名称+设备名称)"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="网络设备ID" prop="ndid" class="top">
|
||||
<el-input maxlength="32" show-word-limit v-model.trim="form.ndid" autocomplete="off"
|
||||
placeholder="请输入网络设备ID"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型" prop="devType" class="top">
|
||||
<el-select v-model.trim="form.devType" placeholder="请选择设备类型" @change="formDevTypeChange" clearable>
|
||||
<el-option v-for="item in formDevTypeOptions" :key="item.value" :label="item.label || item.name"
|
||||
:value="item.value || item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号" prop="devModel" class="top">
|
||||
<el-select v-model.trim="form.devModel" filterable placeholder="请选择设备型号" clearable>
|
||||
<el-option v-for="item in formDevModelOptionsFilter" :key="item.value" :label="item.label"
|
||||
:value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="治理类型" class="top">
|
||||
<el-select v-model.trim="form.governType" filterable placeholder="请选择治理类型" clearable>
|
||||
<el-option label="暂态" value="event"></el-option>
|
||||
<el-option label="稳态" value="harmonic"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="敏感用户"class="top">
|
||||
<div style="display: flex;">
|
||||
<el-select v-model.trim="form.monitorUser" style="width: 230px;" filterable placeholder="请选择敏感用户"
|
||||
clearable>
|
||||
<el-option v-for="option in userList" :key="option.id" :label="option.name"
|
||||
:value="option.id"></el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" icon="el-icon-Plus" class="ml10" @click="addMonitorUser" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="治理方法" class="top">
|
||||
<el-input maxlength="32" show-word-limit v-model="form.governMethod" autocomplete="off" clearable
|
||||
placeholder="例: 250A APF 或 100kVar SVG"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议" prop="devAccessMethod" class="top">
|
||||
<el-select v-model.trim="form.devAccessMethod" placeholder="请选择通讯协议" clearable disabled>
|
||||
<el-option label="MQTT" value="MQTT"></el-option>
|
||||
<el-option label="CLD" value="CLD"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关联项目" class="top">
|
||||
<el-cascader v-model.trim="form.association" filterable :options="engineeringList"
|
||||
:props="cascaderProps" clearable placeholder="请选择关联项目" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" class="top" prop="sort">
|
||||
<el-input-number v-model.trim="form.sort" style="width: 100%;" :min="0" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
addEquipmentDelivery,
|
||||
editEquipmentDelivery,
|
||||
portableDeviceRegister,
|
||||
} from '@/api/cs-system-boot/device'
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter() // 路由对象
|
||||
const props = defineProps<{
|
||||
userList: any[]
|
||||
engineeringList: any[]
|
||||
devTypeOptions: any[]
|
||||
devTypeOptions2: any
|
||||
devModelOptions: any[]
|
||||
devModelOptions2: any[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
success: []
|
||||
}>()
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false })
|
||||
|
||||
const dialogTitle = ref('新增设备')
|
||||
const ruleFormRef = ref()
|
||||
const form: any = reactive(getDefaultForm())
|
||||
|
||||
const cascaderProps = {
|
||||
label: 'projectName',
|
||||
value: 'projectId',
|
||||
children: 'projectInfoList'
|
||||
}
|
||||
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '请输入设备名', trigger: 'blur' }],
|
||||
ndid: [{ required: true, message: '请输入网络设备id', trigger: 'blur' }],
|
||||
devType: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
||||
devModel: [{ required: true, message: '请选择设备型号', trigger: 'change' }],
|
||||
devAccessMethod: [{ required: true, message: '请输入接入方式', trigger: 'blur' }],
|
||||
cntractNo: [{ required: true, message: '请输入合同号', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
function getDefaultForm() {
|
||||
return {
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'MQTT',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
ndid: '',
|
||||
associatedEngineering: '',
|
||||
associatedProject: '',
|
||||
association: [] as any[],
|
||||
sort: 0,
|
||||
monitorUser: '',
|
||||
governType: '',
|
||||
governMethod: '',
|
||||
id: undefined as string | number | undefined,
|
||||
}
|
||||
}
|
||||
|
||||
const normalizeFormValue = (value: unknown, fallback = '') =>
|
||||
value == null ? fallback : value
|
||||
|
||||
const buildSubmitPayload = () => {
|
||||
const association = Array.isArray(form.association) ? form.association : []
|
||||
return {
|
||||
id: form.id,
|
||||
cntractNo: normalizeFormValue(form.cntractNo),
|
||||
devAccessMethod: normalizeFormValue(form.devAccessMethod, 'MQTT'),
|
||||
devModel: normalizeFormValue(form.devModel),
|
||||
devType: normalizeFormValue(form.devType),
|
||||
name: normalizeFormValue(form.name),
|
||||
ndid: normalizeFormValue(form.ndid),
|
||||
associatedEngineering: normalizeFormValue(association[0]),
|
||||
associatedProject: normalizeFormValue(association[1]),
|
||||
sort: form.sort ?? 0,
|
||||
monitorUser: normalizeFormValue(form.monitorUser),
|
||||
governType: normalizeFormValue(form.governType),
|
||||
governMethod: normalizeFormValue(form.governMethod),
|
||||
}
|
||||
}
|
||||
|
||||
const formDevModelOptionsFilter = computed(() => {
|
||||
if (form.devAccessMethod === 'CLD') {
|
||||
return props.devModelOptions2.filter((item: any) => {
|
||||
return form.devType ? item.pid == form.devType : true
|
||||
})
|
||||
}
|
||||
return props.devModelOptions.filter((item: any) => {
|
||||
return form.devType ? item.pid == form.devType : true
|
||||
})
|
||||
})
|
||||
|
||||
const formDevTypeOptions = computed(() => {
|
||||
if (form.devAccessMethod === 'CLD') {
|
||||
return [props.devTypeOptions2]
|
||||
}
|
||||
return props.devTypeOptions
|
||||
})
|
||||
|
||||
const formDevTypeChange = (e: any) => {
|
||||
if (!e) return
|
||||
form.devModel = ''
|
||||
}
|
||||
|
||||
const openAdd = () => {
|
||||
dialogTitle.value = '新增设备'
|
||||
Object.assign(form, getDefaultForm())
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
const openEdit = (row: any) => {
|
||||
dialogTitle.value = '编辑设备'
|
||||
Object.assign(form, getDefaultForm())
|
||||
for (const key in form) {
|
||||
if (key in row) {
|
||||
form[key] = row[key]
|
||||
}
|
||||
}
|
||||
form.association = row.associatedProject ? [row.associatedEngineering, row.associatedProject] : []
|
||||
form.id = row.id
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
const clearForm = () => {
|
||||
ruleFormRef.value?.resetFields()
|
||||
nextTick(() => {
|
||||
Object.assign(form, getDefaultForm())
|
||||
})
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
clearForm()
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
const handleBeforeClose = (done: () => void) => {
|
||||
clearForm()
|
||||
done()
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
clearForm()
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
const addMonitorUser = () => {
|
||||
sessionStorage.setItem('factoryNeedRefreshUserList', '1')
|
||||
router.push({
|
||||
name: 'govern/sensitiveLoadMange/index',
|
||||
})
|
||||
}
|
||||
const onSubmit = () => {
|
||||
ruleFormRef.value.validate((valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
const payload = buildSubmitPayload()
|
||||
|
||||
if (dialogTitle.value === '新增设备') {
|
||||
addEquipmentDelivery(payload).then(res => {
|
||||
ElMessage.success('新增成功')
|
||||
const devType = props.devTypeOptions.find((item: any) => item.value == payload.devType)
|
||||
if (devType?.code === 'Portable') {
|
||||
setTimeout(() => {
|
||||
ElMessage.warning('设备正在接入中,请稍等。')
|
||||
}, 3000)
|
||||
portableDeviceRegister({ nDid: res.data.ndid })
|
||||
.then(pres => {
|
||||
ElMessage.success(pres.message)
|
||||
})
|
||||
.catch(() => { })
|
||||
}
|
||||
resetForm()
|
||||
emit('success')
|
||||
})
|
||||
} else {
|
||||
editEquipmentDelivery(payload).then(() => {
|
||||
ElMessage.success('修改成功')
|
||||
resetForm()
|
||||
emit('success')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ openAdd, openEdit })
|
||||
</script>
|
||||
@@ -3,12 +3,8 @@
|
||||
<TableHeader>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="关键字筛选">
|
||||
<el-input maxlength="32" show-word-limit
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
style="width: 200px"
|
||||
clearable
|
||||
placeholder="请输入设备名称/网络设备ID"
|
||||
/>
|
||||
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"
|
||||
style="width: 200px" clearable placeholder="请输入设备名称/网络设备ID" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="流程阶段">
|
||||
<el-select v-model.trim="tableStore.table.params.process" clearable placeholder="请选择状态">
|
||||
@@ -18,11 +14,7 @@
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="物联状态">
|
||||
<el-select
|
||||
v-model.trim="tableStore.table.params.connectStatus"
|
||||
clearable
|
||||
placeholder="请选择物联状态"
|
||||
>
|
||||
<el-select v-model.trim="tableStore.table.params.connectStatus" clearable placeholder="请选择物联状态">
|
||||
<el-option label="已连接" :value="1"></el-option>
|
||||
<el-option label="未连接" :value="0"></el-option>
|
||||
</el-select>
|
||||
@@ -85,107 +77,22 @@
|
||||
<el-button type="primary" @click="downLoadFile1" class="ml10" icon="el-icon-Download">
|
||||
模版下载
|
||||
</el-button>
|
||||
<el-upload
|
||||
style="display: inline-block"
|
||||
action=""
|
||||
accept=".xlsx"
|
||||
class="upload-demo"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="bulkImport"
|
||||
>
|
||||
<el-upload style="display: inline-block" action="" accept=".xlsx" class="upload-demo"
|
||||
:show-file-list="false" :auto-upload="false" :on-change="bulkImport">
|
||||
<el-button type="primary" class="ml10" icon="el-icon-Tickets">批量导入</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" class="ml10" @click="add" icon="el-icon-Plus">新增设备</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
class="ml10"
|
||||
icon="el-icon-Download"
|
||||
@click="downLoadQrCode"
|
||||
:disabled="!showQrCode"
|
||||
>
|
||||
<el-button type="primary" class="ml10" icon="el-icon-Download" @click="downLoadQrCode"
|
||||
:disabled="!showQrCode">
|
||||
批量下载二维码
|
||||
</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" :checkbox-config="checkboxConfig" :key="tableKey" @sort-change="handleSortChange"></Table>
|
||||
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model.trim="dialogFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="resetForm"
|
||||
draggable
|
||||
width="800px"
|
||||
>
|
||||
<el-form :model="form" label-width="auto" :rules="rules" ref="ruleFormRef" class="form-two">
|
||||
<el-form-item label="设备名称:" prop="name">
|
||||
<el-input maxlength="32" show-word-limit
|
||||
|
||||
|
||||
v-model.trim="form.name"
|
||||
autocomplete="off"
|
||||
clearable
|
||||
placeholder="请输入(项目名称+设备名称)"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="网络设备ID:" prop="ndid" class="top">
|
||||
<el-input maxlength="32" show-word-limit
|
||||
|
||||
|
||||
v-model.trim="form.ndid"
|
||||
autocomplete="off"
|
||||
placeholder="请输入"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型:" prop="devType" class="top">
|
||||
<el-select v-model.trim="form.devType" placeholder="请选择" @change="formDevTypeChange" clearable>
|
||||
<el-option
|
||||
v-for="item in formDevTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label || item.name"
|
||||
:value="item.value || item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号:" prop="devModel" class="top">
|
||||
<el-select v-model.trim="form.devModel" filterable placeholder="请选择" clearable>
|
||||
<el-option
|
||||
v-for="item in formDevModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议:" prop="devAccessMethod" class="top">
|
||||
<el-select v-model.trim="form.devAccessMethod" placeholder="请选择" clearable disabled>
|
||||
<el-option label="MQTT" value="MQTT"></el-option>
|
||||
<el-option label="CLD" value="CLD"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关联项目:" class="top">
|
||||
<el-cascader
|
||||
v-model.trim="form.association"
|
||||
filterable
|
||||
:options="engineeringList"
|
||||
:props="props"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序:" class="top" prop="sort">
|
||||
<el-input-number v-model.trim="form.sort" :min="0" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- <el-form-item label="合同号:" prop="cntractNo" class="top">
|
||||
<el-input maxlength="32" show-word-limit v-model.trim="form.cntractNo" autocomplete="off" placeholder="请输入"></el-input>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="resetForm">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<FactoryForm ref="factoryFormRef" :user-list="userList" :engineering-list="engineeringList"
|
||||
:dev-type-options="devTypeOptions" :dev-type-options2="devTypeOptions2" :dev-model-options="devModelOptions"
|
||||
:dev-model-options2="devModelOptions2" @success="onFormSuccess" />
|
||||
|
||||
<div class="qrcode-label">
|
||||
<div class="qrcode-label-title">{{ deivce.mac }}</div>
|
||||
@@ -200,35 +107,36 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, computed, reactive, nextTick } from 'vue'
|
||||
import { ref, onMounted, onActivated, provide, computed, reactive } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import FactoryForm from './components/factoryForm.vue'
|
||||
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user'
|
||||
import { downLoadFile } from '@/api/cs-system-boot/manage'
|
||||
import {
|
||||
addEquipmentDelivery,
|
||||
deleteEquipmentDelivery,
|
||||
editEquipmentDelivery,
|
||||
batchImportDevice,
|
||||
resetEquipmentDelivery,
|
||||
governDeviceRegister,
|
||||
portableDeviceRegister,
|
||||
portableDeviceAccess,
|
||||
getExcelTemplate,
|
||||
engineeringProject,
|
||||
onlineRegister,
|
||||
resetFactory
|
||||
resetFactory,
|
||||
portableDeviceRegister,
|
||||
portableDeviceAccess,
|
||||
} from '@/api/cs-system-boot/device'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { fullUrl } from '@/utils/common'
|
||||
import JSZip from 'jszip'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { getList } from '@/api/cs-harmonic-boot/recruitment'
|
||||
|
||||
defineOptions({
|
||||
name: 'govern/manage/factory'
|
||||
})
|
||||
const userList: any = ref([])
|
||||
const showQrCode = ref(false)
|
||||
const devTypeOptions: any = ref([])
|
||||
const devTypeOptions2: any = ref([])
|
||||
@@ -236,37 +144,9 @@ const devModelOptions2: any = ref([])
|
||||
const engineeringList: any = ref([])
|
||||
|
||||
const deivce: any = ref({})
|
||||
const ruleFormRef = ref()
|
||||
const form: any = reactive({
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'MQTT',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
ndid: '',
|
||||
associatedEngineering: '',
|
||||
associatedProject: '',
|
||||
association: [],
|
||||
sort: 0
|
||||
})
|
||||
const props = {
|
||||
label: 'projectName',
|
||||
value: 'projectId',
|
||||
children: 'projectInfoList'
|
||||
}
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '请输入设备名', trigger: 'blur' }],
|
||||
ndid: [{ required: true, message: '请输入网络设备id', trigger: 'blur' }],
|
||||
devType: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
||||
devModel: [{ required: true, message: '请选择设备型号', trigger: 'change' }],
|
||||
devAccessMethod: [{ required: true, message: '请输入接入方式', trigger: 'blur' }],
|
||||
cntractNo: [{ required: true, message: '请输入合同号', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
|
||||
})
|
||||
const factoryFormRef = ref<InstanceType<typeof FactoryForm>>()
|
||||
const qrcodeFlag = ref(false)
|
||||
const tableKey = ref(0)
|
||||
const dialogFormVisible = ref(false)
|
||||
const dialogTitle = ref('新增设备')
|
||||
const loading = ref<boolean>(false)
|
||||
const devModelOptions: any = ref([])
|
||||
const queryTheDictionary = () => {
|
||||
@@ -330,37 +210,6 @@ const devModelOptionsFilter = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const formDevModelOptionsFilter = computed(() => {
|
||||
if (form.devAccessMethod === 'CLD') {
|
||||
return devModelOptions2.value.filter((item: any) => {
|
||||
if (form.devType) {
|
||||
return item.pid == form.devType
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return devModelOptions.value.filter((item: any) => {
|
||||
if (form.devType) {
|
||||
return item.pid == form.devType
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const formDevTypeOptions = computed(() => {
|
||||
// 如果协议是CLD,使用devTypeOptions2,否则使用devTypeOptions
|
||||
if (form.devAccessMethod === 'CLD') {
|
||||
// 对于devTypeOptions2,使用id和name字段
|
||||
return [devTypeOptions2.value]
|
||||
} else {
|
||||
// 对于devTypeOptions,使用value和label字段
|
||||
return devTypeOptions.value
|
||||
}
|
||||
})
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-device-boot/EquipmentDelivery/list',
|
||||
method: 'POST',
|
||||
@@ -377,8 +226,8 @@ const tableStore = new TableStore({
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '设备名称', field: 'name', minWidth: 120 },
|
||||
{ title: '网络设备ID', field: 'ndid', minWidth: 120 },
|
||||
{ title: '设备名称', field: 'name', minWidth: 160 },
|
||||
{ title: '网络设备ID', field: 'ndid', minWidth: 130 },
|
||||
{
|
||||
title: '设备类型',
|
||||
field: 'devType',
|
||||
@@ -393,7 +242,7 @@ const tableStore = new TableStore({
|
||||
return item ? item.label : '/'
|
||||
}
|
||||
},
|
||||
minWidth: 120
|
||||
minWidth: 110
|
||||
},
|
||||
{
|
||||
title: '设备型号',
|
||||
@@ -405,13 +254,37 @@ const tableStore = new TableStore({
|
||||
},
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: '治理类型',
|
||||
field: 'governType',
|
||||
minWidth: 100,
|
||||
formatter: row => {
|
||||
return row.cellValue === 'event' ? '暂态' : row.cellValue === 'harmonic' ? '稳态' : (row.cellValue || '/')
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '治理方法',
|
||||
field: 'governMethod',
|
||||
minWidth: 100,
|
||||
formatter: row => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '敏感用户',
|
||||
field: 'monitorUser',
|
||||
minWidth: 120,
|
||||
formatter: row => {
|
||||
return userList.value.find((item: any) => item.id == row.cellValue)?.name || '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '通讯协议',
|
||||
field: 'devAccessMethod',
|
||||
formatter: row => {
|
||||
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'CLD' ? 'CLD' : row.cellValue
|
||||
},
|
||||
minWidth: 120
|
||||
minWidth: 100
|
||||
},
|
||||
{ title: '录入时间', field: 'createTime', sortable: true, minWidth: 150 },
|
||||
|
||||
@@ -425,7 +298,7 @@ const tableStore = new TableStore({
|
||||
inactiveValue: '0',
|
||||
activeValue: '1',
|
||||
onChangeField: (row: any, value: any) => {
|
||||
// console.log("🚀 ~ row:", row)
|
||||
// console.log("🚀 ~ row", row)
|
||||
ElMessageBox.prompt('二次校验密码确认', '', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
@@ -492,28 +365,28 @@ const tableStore = new TableStore({
|
||||
},
|
||||
minWidth: 80
|
||||
},
|
||||
{
|
||||
title: '流程阶段',
|
||||
field: 'process',
|
||||
width: 100,
|
||||
render: 'tag',
|
||||
custom: {
|
||||
2: 'warning',
|
||||
3: 'warning',
|
||||
4: 'success'
|
||||
},
|
||||
replaceValue: {
|
||||
2: '功能调试',
|
||||
3: '出厂调试',
|
||||
4: '正式投运'
|
||||
},
|
||||
minWidth: 80
|
||||
},
|
||||
// {
|
||||
// title: '流程阶段',
|
||||
// field: 'process',
|
||||
// width: 100,
|
||||
// render: 'tag',
|
||||
// custom: {
|
||||
// 2: 'warning',
|
||||
// 3: 'warning',
|
||||
// 4: 'success'
|
||||
// },
|
||||
// replaceValue: {
|
||||
// 2: '功能调试',
|
||||
// 3: '出厂调试',
|
||||
// 4: '正式投运'
|
||||
// },
|
||||
// minWidth: 80
|
||||
// },
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
width: 220,
|
||||
width: 180,
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
//直连设备注册
|
||||
@@ -758,16 +631,7 @@ const tableStore = new TableStore({
|
||||
render: 'basicButton',
|
||||
|
||||
click: async row => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '编辑设备'
|
||||
for (let key in form) {
|
||||
form[key] = row[key]
|
||||
}
|
||||
|
||||
form.association = row.associatedProject
|
||||
? [row.associatedEngineering, row.associatedProject]
|
||||
: []
|
||||
form.id = row.id
|
||||
factoryFormRef.value?.openEdit(row)
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -810,7 +674,7 @@ const tableStore = new TableStore({
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
.catch(e => { })
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -956,81 +820,35 @@ const handleSortChange = ({ column, order }: { column: TableColumn; order: 'asc'
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '新增设备'
|
||||
|
||||
factoryFormRef.value?.openAdd()
|
||||
}
|
||||
|
||||
// 确认
|
||||
const onSubmit = () => {
|
||||
ruleFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
form.associatedEngineering = form.association ? form.association[0] : ''
|
||||
form.associatedProject = form.association ? form.association[1] : ''
|
||||
|
||||
if (dialogTitle.value == '新增设备') {
|
||||
addEquipmentDelivery(form).then(res => {
|
||||
ElMessage.success('新增成功')
|
||||
if (devTypeOptions.value.filter((item: any) => item.value == form.devType)[0].code == 'Portable') {
|
||||
setTimeout(() => {
|
||||
ElMessage.warning('设备正在接入中,请稍等。')
|
||||
}, 3000)
|
||||
portableDeviceRegister({
|
||||
nDid: res.data.ndid
|
||||
})
|
||||
.then(pres => {
|
||||
ElMessage.success(pres.message)
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 1000)
|
||||
})
|
||||
.catch(err => {
|
||||
// clearTimeout (time)
|
||||
})
|
||||
}
|
||||
|
||||
resetForm()
|
||||
const onFormSuccess = () => {
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
} else {
|
||||
editEquipmentDelivery(form).then(res => {
|
||||
ElMessage.success('修改成功')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 清空表格
|
||||
const resetForm = () => {
|
||||
ruleFormRef.value.resetFields()
|
||||
dialogFormVisible.value = false
|
||||
nextTick(() => {
|
||||
// 模拟待编辑数据
|
||||
let user = {
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'MQTT',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
associatedEngineering: '',
|
||||
associatedProject: '',
|
||||
association: [],
|
||||
ndid: ''
|
||||
}
|
||||
Object.assign(form, user)
|
||||
|
||||
const getUserList = () => {
|
||||
return getList({
|
||||
pageNum: 1,
|
||||
pageSize: 2000
|
||||
}).then(res => {
|
||||
userList.value = res.data.records
|
||||
})
|
||||
}
|
||||
|
||||
const formDevTypeChange = (e: any) => {
|
||||
if (!e) {
|
||||
return
|
||||
// 页面被 keep-alive 缓存后,从敏感用户页返回时刷新下拉列表
|
||||
onActivated(() => {
|
||||
if (sessionStorage.getItem('factoryNeedRefreshUserList')) {
|
||||
sessionStorage.removeItem('factoryNeedRefreshUserList')
|
||||
getUserList()
|
||||
}
|
||||
form.devModel = ''
|
||||
}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
getUserList()
|
||||
queryTheDictionary()
|
||||
engineeringProject().then(res => {
|
||||
engineeringList.value = res.data.filter(item => {
|
||||
@@ -1041,10 +859,10 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
|
||||
setTimeout(() => {}, 100)
|
||||
setTimeout(() => { }, 100)
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => { }
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.qrcode-label {
|
||||
|
||||
@@ -89,24 +89,24 @@ const tableStore = new TableStore({
|
||||
}
|
||||
},
|
||||
{ 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: 'process',
|
||||
// width: 100,
|
||||
// fixed: 'right',
|
||||
// render: 'tag',
|
||||
// custom: {
|
||||
// 2: 'warning',
|
||||
// 3: 'warning',
|
||||
// 4: 'success'
|
||||
// },
|
||||
// replaceValue: {
|
||||
// 2: '功能调试',
|
||||
// 3: '出厂调试',
|
||||
// 4: '正式投运'
|
||||
// },
|
||||
// minWidth: 80
|
||||
// },
|
||||
{
|
||||
title: '运行状态',
|
||||
field: 'operationalStatus',
|
||||
|
||||
@@ -1,144 +1,126 @@
|
||||
<template>
|
||||
<div class="default-main report-zl-page" :style="height">
|
||||
<div class="report-zl-sidebar">
|
||||
<!-- <pointTreeWx :default-expand-all="false" template @node-click="handleNodeClick" @init="handleNodeClick"
|
||||
@Policy="stencil">
|
||||
</pointTreeWx> -->
|
||||
<CloudDeviceEntryTree ref="TerminalRef" template @Policy="stencil" @node-click="handleNodeClick"
|
||||
@init="handleNodeClick"></CloudDeviceEntryTree>
|
||||
</div>
|
||||
<div class="report-zl-main">
|
||||
<div class="statistics-wx-zl default-main" :style="height">
|
||||
<aside>
|
||||
<!-- <CloudDeviceEntryTree
|
||||
ref="TerminalRef"
|
||||
template
|
||||
@Policy="stencil"
|
||||
@init="handleNodeClick"
|
||||
/> -->
|
||||
<APFTree @node-click="handleNodeClick" template @init="handleNodeClick" @Policy="stencil"></APFTree>
|
||||
</aside>
|
||||
<main class="statistics-wx-zl__main ">
|
||||
<TableHeader datePicker ref="TableHeaderRef" :showReset="false">
|
||||
<template v-slot:select>
|
||||
<!-- <el-form-item label="时间:">
|
||||
<DatePicker ref="datePickerRef"></DatePicker>
|
||||
</el-form-item> -->
|
||||
<template #select>
|
||||
<el-form-item label="模板策略">
|
||||
<el-select v-model.trim="Template" @change="changetype" placeholder="请选择模版" value-key="id">
|
||||
<el-option v-for="item in templatePolicy" :key="item.id" :label="item.excelName"
|
||||
:value="item"></el-option>
|
||||
<el-select
|
||||
v-model="Template"
|
||||
@change="changetype"
|
||||
placeholder="请选择模版"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in templatePolicy"
|
||||
:key="item.id"
|
||||
:label="item.excelName"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="监测对象">
|
||||
<el-select
|
||||
filterable
|
||||
v-model="tableStore.table.params.sensitiveUserId"
|
||||
placeholder="请选择监测对象"
|
||||
clearable
|
||||
>
|
||||
<el-option v-for="item in idList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">报表生成</el-button>
|
||||
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<div class="box report-zl-box">
|
||||
<div class="report-zl-sheet-wrap">
|
||||
<div class="statistics-wx-zl__sheet-box pl0" v-loading="tableStore.table.loading">
|
||||
<div
|
||||
v-if="tableStore.table.data.length > 0"
|
||||
id="luckysheet"
|
||||
class="report-zl-sheet"
|
||||
v-loading="tableStore.table.loading"
|
||||
element-loading-background="rgba(255, 255, 255, 0.85)"
|
||||
></div>
|
||||
<el-empty
|
||||
v-show="!tableStore.table.loading && tableStore.table.data.length === 0"
|
||||
class="report-zl-empty"
|
||||
description="暂无数据"
|
||||
class="statistics-wx-zl__sheet"
|
||||
/>
|
||||
<el-empty v-else class="statistics-wx-zl__empty" description="暂无数据" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref, provide } from 'vue'
|
||||
import { onMounted, ref, provide, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import pointTreeWx from '@/components/tree/govern/pointTreeWx.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import APFTree from '@/components/tree/govern/APFTree.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { destroyLuckysheet, exportLuckysheetFile, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||
import { isLineTreeLeaf } from '@/components/tree/govern/lineTreeUtils'
|
||||
import DatePicker from '@/components/form/datePicker/time.vue'
|
||||
import { exportExcel } from '@/views/system/reportForms/export.js'
|
||||
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTreeZL.vue'
|
||||
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||
import { ElMessage } from 'element-plus'
|
||||
// import data from './123.json'
|
||||
|
||||
defineOptions({
|
||||
name: 'govern/reportCore/statisticsWx/indexZL'
|
||||
})
|
||||
|
||||
const height = mainHeight(20)
|
||||
const dictData = useDictData()
|
||||
const TableHeaderRef = ref()
|
||||
const dotList: any = ref({})
|
||||
const Template: any = ref({})
|
||||
const reportForm: any = ref('')
|
||||
const datePickerRef = ref()
|
||||
const templatePolicy: any = ref([])
|
||||
const dotList = ref<any>({})
|
||||
const Template = ref<any>({})
|
||||
const reportForm = ref('')
|
||||
const templatePolicy = ref<any[]>([])
|
||||
const name = ref('')
|
||||
const idList = ref<any[]>([])
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-harmonic-boot/customReport/getSensitiveUserReport',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
showPage: false,
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.tempId = Template.value.id
|
||||
tableStore.table.params.lineId = dotList.value.id
|
||||
tableStore.table.params.sensitiveUserId = dotList.value.id
|
||||
// ;(tableStore.table.params.startTime = datePickerRef.value.timeValue[0]),
|
||||
// (tableStore.table.params.endTime = datePickerRef.value.timeValue[1]),
|
||||
if (!tableStore.table.params.tempId) {
|
||||
ElMessage.warning('请选择模板')
|
||||
return false
|
||||
return ElMessage.warning('请选择模板')
|
||||
}
|
||||
if (!dotList.value?.id) {
|
||||
ElMessage.warning('请选择监测点')
|
||||
return false
|
||||
}
|
||||
destroyLuckysheet()
|
||||
delete tableStore.table.params.searchBeginTime
|
||||
delete tableStore.table.params.searchEndTime
|
||||
delete tableStore.table.params.timeFlag
|
||||
},
|
||||
loadCallback: () => {
|
||||
name.value = dotList.value.name
|
||||
if (tableStore.table.data.length > 0) {
|
||||
renderLuckysheetReport('luckysheet', tableStore.table.data, { allowEdit: false })
|
||||
} else {
|
||||
destroyLuckysheet()
|
||||
}
|
||||
setTimeout(() => {
|
||||
luckysheet.create({
|
||||
container: 'luckysheet',
|
||||
title: '',
|
||||
lang: 'zh',
|
||||
showtoolbar: false,
|
||||
showinfobar: false,
|
||||
showsheetbar: true,
|
||||
allowEdit: false,
|
||||
data: tableStore.table.data
|
||||
})
|
||||
}, 10)
|
||||
}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.resourceType = 1
|
||||
tableStore.table.params.customType = 1
|
||||
const flag = ref(true)
|
||||
|
||||
onMounted(() => {
|
||||
initListByIds()
|
||||
})
|
||||
onUnmounted(() => {
|
||||
destroyLuckysheet()
|
||||
})
|
||||
|
||||
const idList = ref([])
|
||||
// 监测对象
|
||||
const initListByIds = () => {
|
||||
function initListByIds() {
|
||||
getListByIds({}).then((res: any) => {
|
||||
if (res.data.length > 0) {
|
||||
if (res.data?.length > 0) {
|
||||
idList.value = res.data
|
||||
|
||||
if (!tableStore.table.params.sensitiveUserId && idList.value?.length > 0) {
|
||||
if (!tableStore.table.params.sensitiveUserId) {
|
||||
tableStore.table.params.sensitiveUserId = idList.value[0].id
|
||||
}
|
||||
// templateListData()
|
||||
}
|
||||
})
|
||||
}
|
||||
const stencil = (val: any) => {
|
||||
templatePolicy.value = val.filter((item: any) => item.excelType == '4')
|
||||
|
||||
const stencil = (val: any[]) => {
|
||||
templatePolicy.value = val.filter(item => item.excelType == '4')
|
||||
Template.value = templatePolicy.value[0]
|
||||
reportForm.value = templatePolicy.value[0]?.excelType
|
||||
}
|
||||
@@ -147,12 +129,10 @@ const changetype = (val: any) => {
|
||||
reportForm.value = val.excelType
|
||||
}
|
||||
|
||||
const handleNodeClick = (data: any, node: any) => {
|
||||
if (isLineTreeLeaf(data) || data?.level == 3) {
|
||||
const handleNodeClick = (data: any) => {
|
||||
if (data?.level == 3||data?.level == 2) {
|
||||
dotList.value = data
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 500)
|
||||
nextTick(() => tableStore.index())
|
||||
} else {
|
||||
tableStore.table.loading = false
|
||||
}
|
||||
@@ -160,64 +140,76 @@ const handleNodeClick = (data: any, node: any) => {
|
||||
|
||||
const exportEvent = () => {
|
||||
const now = new Date()
|
||||
const year = now.getFullYear() // 4位年份
|
||||
const month = now.getMonth() + 1 // 月份0-11,需+1
|
||||
const day = now.getDate() // 日期1-31
|
||||
|
||||
// 格式化YYYY - MM - DD(补零)
|
||||
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
||||
exportLuckysheetFile(name.value + formattedDate, tableStore.table.data.length > 0)
|
||||
const formattedDate = [
|
||||
now.getFullYear(),
|
||||
String(now.getMonth() + 1).padStart(2, '0'),
|
||||
String(now.getDate()).padStart(2, '0')
|
||||
].join('')
|
||||
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.report-zl-page {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.statistics-wx-zl {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
gap: 0;
|
||||
|
||||
.report-zl-sidebar {
|
||||
width: 280px;
|
||||
&__sidebar {
|
||||
flex-shrink: 0;
|
||||
min-height: 0;
|
||||
width: 280px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
background: var(--el-bg-color);
|
||||
border-right: 1px solid var(--el-border-color-lighter);
|
||||
box-sizing: border-box;
|
||||
padding: 10px 8px 10px 10px;
|
||||
|
||||
.report-zl-main {
|
||||
:deep(.cn-tree) {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.el-tree) {
|
||||
height: calc(100% - 42px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
|
||||
.box {
|
||||
&__template-select {
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
&__sheet-box {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
padding: 10px 0;
|
||||
padding: 0 12px 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&__sheet,
|
||||
&__empty {
|
||||
height: 100%;
|
||||
min-height: 240px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
background: var(--el-fill-color-blank);
|
||||
}
|
||||
|
||||
.report-zl-box {
|
||||
&__empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.report-zl-sheet-wrap {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.report-zl-sheet {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.report-zl-empty {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
style="width: 240px"
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
placeholder="请输入敏感负荷名称"
|
||||
placeholder="请输入敏感用户名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -51,16 +51,17 @@ const tableStore: any = new TableStore({
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '所属厂站名称', field: 'substationName', minWidth: 180 },
|
||||
{ title: '敏感用户名称', field: 'name', minWidth: 180 },
|
||||
{
|
||||
title: '敏感负荷类型',
|
||||
title: '敏感用户类型',
|
||||
field: 'loadType',
|
||||
minWidth: 120,
|
||||
formatter: row => {
|
||||
return interferenceType.filter(item => item.id == row.cellValue)[0]?.name
|
||||
}
|
||||
},
|
||||
{ title: '所属厂站名称', field: 'substationName', minWidth: 180 },
|
||||
|
||||
{ title: '用户协议容量(MVA)', field: 'userAgreementCapacity', minWidth: 100 },
|
||||
{ title: '装机容量(MW)', field: 'installedCapacity', minWidth: 100 },
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<Icon class="ba-icon-dark" :name="row.icon || ''" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="startTime" title="是否激活">
|
||||
<vxe-column field="startTime" title="是否激活" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.state"
|
||||
@@ -35,7 +35,7 @@
|
||||
/>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="startTime" title="是否全局" v-if="hasAdmin">
|
||||
<vxe-column field="startTime" title="是否全局" v-if="hasAdmin" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.scope"
|
||||
@@ -49,18 +49,21 @@
|
||||
/>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="sort" title="排序">
|
||||
<vxe-column field="sort" width="80" title="排序">
|
||||
|
||||
</vxe-column>
|
||||
<vxe-column field="startTime" title="操作">
|
||||
<vxe-column field="startTime" title="操作" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="edit(row)" v-if="!(!hasAdmin && row.scope)">
|
||||
<el-button type="primary" link size="small" @click="edit(row)" v-if="!(!hasAdmin && row.scope)">
|
||||
编辑
|
||||
</el-button>
|
||||
|
||||
<el-button type="danger" link @click="deletes(row)" v-if="!(!hasAdmin && row.scope)">
|
||||
<el-button type="danger" link size="small" @click="deletes(row)" v-if="!(!hasAdmin && row.scope)">
|
||||
删除
|
||||
</el-button>
|
||||
<el-button type="info" link size="small" v-if="(!hasAdmin && row.scope)">
|
||||
管理员分配页面
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
<div class="tableBox" v-if="show">
|
||||
<vxe-table border auto-resize height="230px" :data="tableData" ref="tableRef">
|
||||
<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>
|
||||
<vxe-column field="date" align="center" sortable title="发生时间" width="200px"></vxe-column>
|
||||
<vxe-column field="name" align="center" title="监测点名称" width="200px"></vxe-column>
|
||||
<vxe-column field="address" align="center" title="事件描述"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
|
||||
@@ -52,11 +52,26 @@ const tableStore = new TableStore({
|
||||
column: [
|
||||
{ title: '名称', field: 'name' },
|
||||
{ title: '编码', field: 'code' },
|
||||
{ title: '排序', field: 'sort' },
|
||||
|
||||
{ title: '计算值', field: 'value' },
|
||||
{ title: '事件等级', field: 'levelName' },
|
||||
{ title: '算法描述', field: 'algoDescribe' },
|
||||
{ title: '状态', field: 'stateName' },
|
||||
|
||||
{
|
||||
title: '状态',
|
||||
field: 'state',
|
||||
width: '80',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
0: 'danger',
|
||||
1: 'success'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '删除',
|
||||
1: '正常'
|
||||
}
|
||||
},
|
||||
{ title: '排序', field: 'sort', width: '80', },
|
||||
{
|
||||
title: '操作', fixed: 'right',
|
||||
width: '180',
|
||||
|
||||
@@ -50,13 +50,17 @@ const tableStore = new TableStore({
|
||||
{ title: '更新时间', field: 'updateTime', sortable: true},
|
||||
{
|
||||
title: '状态',
|
||||
field: 'stateName',
|
||||
field: 'state',
|
||||
width: '80',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
'正常': 'success',
|
||||
'删除': 'danger'
|
||||
0: 'danger',
|
||||
1: 'success'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '删除',
|
||||
1: '正常'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作', fixed: 'right',
|
||||
|
||||
@@ -32,22 +32,22 @@ const tableStore = new TableStore({
|
||||
// { title: '排序', field: 'sort',width:'80' },
|
||||
{ title: '编码', field: 'code' },
|
||||
{ title: '描述', field: 'remark' },
|
||||
{
|
||||
title: '状态',
|
||||
field: 'status',
|
||||
width: '80',
|
||||
render: 'tag',
|
||||
custom: {
|
||||
0: 'success',
|
||||
1: 'warning',
|
||||
2: 'danger'
|
||||
},
|
||||
replaceValue: {
|
||||
0: '正常',
|
||||
1: '禁用',
|
||||
2: '删除'
|
||||
}
|
||||
},
|
||||
// {
|
||||
// title: '状态',
|
||||
// field: 'status',
|
||||
// width: '80',
|
||||
// render: 'tag',
|
||||
// custom: {
|
||||
// 0: 'success',
|
||||
// 1: 'warning',
|
||||
// 2: 'danger'
|
||||
// },
|
||||
// replaceValue: {
|
||||
// 0: '正常',
|
||||
// 1: '禁用',
|
||||
// 2: '删除'
|
||||
// }
|
||||
// },
|
||||
{
|
||||
title: '操作', fixed: 'right',
|
||||
width: '180',
|
||||
|
||||
Reference in New Issue
Block a user