在线补召

This commit is contained in:
sjl
2025-10-21 16:27:49 +08:00
parent 177e50de75
commit 43b5e4e497
9 changed files with 820 additions and 38 deletions

View File

@@ -10,15 +10,6 @@
<div class="device-control-right" v-if="deviceData">
<el-descriptions title="监测点信息" class="mb10" width="180" :column="3" border>
<template #extra>
<!-- <el-button v-if="deviceType == '1'" type="primary" @click="handleDownLoadTemplate">
模版下载
</el-button> -->
<!-- <el-button v-if="deviceType == '1'" type="primary" icon="el-icon-Connection" @click="handleImport">
离线补召
</el-button>
<el-button v-if="deviceType == '1'" type="primary" icon="el-icon-Monitor" @click="handleaddDevice">
在线补召
</el-button> -->
<el-button
v-if="deviceType == '1'"
type="primary"
@@ -45,9 +36,6 @@
}}
</el-descriptions-item>
<!-- <el-descriptions-item label="安装位置" width="160">
{{ devData.position || '/' }}
</el-descriptions-item> -->
<el-descriptions-item label="PT变比" width="160">
{{ devData.ptRatio || '/' }}
@@ -56,27 +44,9 @@
{{ devData.ctRatio || '/' }}
</el-descriptions-item>
<!-- <el-descriptions-item label="名称">
{{ devData.name ? devData.name : '/' }}
</el-descriptions-item>
<el-descriptions-item label="类型">
{{ echoName(devData.devType, devTypeOptions) }}
</el-descriptions-item>
<el-descriptions-item label="接入方式">
{{ devData.devAccessMethod ? devData.devAccessMethod : '/' }}
</el-descriptions-item>
<el-descriptions-item label="网络设备ID">
{{ devData.ndid ? devData.ndid : '/' }}
</el-descriptions-item>
<el-descriptions-item label="型号">
{{ echoName(devData.devModel, devModelOptions) }}
</el-descriptions-item>
<el-descriptions-item label="接入日期">
{{ devData.time ? devData.time : '/' }}
</el-descriptions-item> -->
</el-descriptions>
<el-tabs v-model.trim="dataSet" type="border-card" class="device-control-box-card" @tab-click="handleClick">
<el-tabs v-model.trim="dataSet" type="border-card" class="mb10" @tab-click="handleClick">
<el-tab-pane
lazy
:label="item.name"
@@ -498,7 +468,7 @@
v-if="dataSet.indexOf('_event') != -1"
v-loading="tableLoading"
>
<Event ref="eventRef"></Event>
<Event ref="eventRef" :device-type="deviceType"></Event>
</div>
<!-- 测试项记录 -->
<div
@@ -928,6 +898,7 @@ const nodeClick = async (e: anyObj) => {
const deviceType = ref('0')
const pointTypeChange = (val: any, obj: any) => {
deviceType.value = val
console.log('pointTypeChange', val)
nodeClick(obj)
}
const realTimeRef: any = ref()

View File

@@ -15,7 +15,7 @@ import TableHeader from '@/components/table/header/index.vue'
import waveFormAnalysis from './components/waveFormAnalysis.vue'
import { ArrowLeft } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { analyseWave } from '@/api/common'
import { analyseWave,getFileByEventId } from '@/api/common'
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
const tableParams: any = ref({})
const refheader = ref()
@@ -29,6 +29,15 @@ const wp = ref({})
const value = ref(1)
const waveFormAnalysisRef = ref()
const headerRef = ref()
const props = defineProps({
deviceType: {
type: String,
default: '0'
}
});
const tableStore: any = new TableStore({
url: '/cs-device-boot/csGroup/deviceDataByType',
publicHeight: 215,
@@ -125,7 +134,7 @@ const tableStore: any = new TableStore({
icon: 'el-icon-DataLine',
render: 'basicButton',
disabled: row => {
return row.wavePath
return props.deviceType === '2' || row.wavePath;
}
},
{
@@ -151,10 +160,22 @@ const tableStore: any = new TableStore({
document.body.removeChild(link) //释放标签
})
}
},
{
name: 'edit',
title: '波形补召',
type: 'primary',
icon: 'el-icon-Check',
render: 'basicButton',
disabled: row => {
return props.deviceType != '2' || row.wavePath;
},
click: row => {
getFileByEventId(row.id).then(res => {
tableStore.index()
})
}
}
]
}

View File

@@ -0,0 +1,151 @@
<template>
<div class="view" style="height: 100%">
<TableHeader datePicker ref="TableHeaderRef" :showReset="false">
<template #operation>
<el-button type="primary" :icon="Setting" @click="recall1">事件补召</el-button>
<el-button type="primary" :icon="Setting" @click="recall2">波形补召</el-button>
</template>
</TableHeader>
<Table ref="tableRef" style="height: calc(100% - 120px)" />
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, provide, nextTick, defineEmits, watch } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { Setting } from '@element-plus/icons-vue'
import {eventRecall,fileRecall} from '@/api/cs-device-boot/recall'
import { ElMessage } from 'element-plus'
import DatePicker from '@/components/form/datePicker/time.vue'
const props = defineProps({
checkedNodes: {
type: Array,
default: () => []
}
});
const headerRef = ref()
const datePickerRef = ref()
const tableStore: any = new TableStore({
url: '/cs-device-boot/portableOfflLog/queryMainLogPage',
publicHeight: 0,
method: 'POST',
column: [
{
title: '序号', width: 80, formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
field: 'projectName',
title: '工程名称',
minWidth: 170,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
{ field: 'successCount', title: '成功解析数', minWidth: 150 },
{ field: 'startTime', title: '导入开始时间', minWidth: 170, sortable: true },
{ field: 'endTime', title: '导入结束时间', minWidth: 170 , sortable: true},
{
title: '解析状态',
field: 'status',
width: 100,
render: 'tag',
custom: {
0: 'warning',
1: 'success',
2: 'danger',
3: 'primary'
},
replaceValue: {
0: '未解析',
1: '解析成功',
2: '解析失败',
3: '文件不存在'
}
},
{
title: '操作',
width: '100',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '详情',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
}
}
]
}
],
beforeSearchFun: () => {
},
loadCallback: () => {
}
})
provide('tableStore', tableStore)
const recall1 = async () => {
if (!props.checkedNodes || props.checkedNodes.length === 0) {
ElMessage.warning('请先勾选监测点')
return
}
await eventRecall({
startTime: tableStore.table.params.startTime,
endTime: tableStore.table.params.endTime,
lineList: props.checkedNodes.map((node: any) => node.id)
}).then((res: any) => {
ElMessage.success('补召事件成功')
})
}
const recall2 = async () => {
if (!props.checkedNodes || props.checkedNodes.length === 0) {
ElMessage.warning('请先勾选监测点')
return
}
await fileRecall({
startTime: tableStore.table.params.startTime,
endTime: tableStore.table.params.endTime,
lineList: props.checkedNodes.map((node: any) => node.id)
}).then((res: any) => {
ElMessage.success('补召波形成功')
})
}
onMounted(() => {
tableStore.index()
})
</script>
<style lang="scss" scoped>
.header_btn {
width: 100%;
height: 30px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.view {
display: flex;
flex-direction: column;
height: 100%;
}
.view :deep(.el-table) {
height: calc(100% - 56px);
}
</style>

View File

@@ -0,0 +1,186 @@
<template>
<div
class="default-main device-control"
:style="{ height: pageHeight.height }"
v-loading="loading"
style="position: relative"
>
<!-- @init="nodeClick" -->
<PointTree @node-click="nodeClick" @pointTypeChange="pointTypeChange" @checkChange="handleCheckedNodesChange"></PointTree>
<div class="device-control-right" >
<el-tabs type="border-card" class="mb10" @tab-click="handleClick" v-model="activeTab">
<el-tab-pane label="稳态补召" name="deviceInfo1">
<div style="height: calc(100vh - 205px)">
<SteadyRecall ref="steadyRef" :checked-nodes="checkedNodes"></SteadyRecall>
</div>
</el-tab-pane>
<el-tab-pane label="暂态补召" name="deviceInfo2">
<div style="height: calc(100vh - 205px)">
<Event ref="eventRef" :checked-nodes="checkedNodes"></Event>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import PointTree from '@/components/tree/govern/selectTree.vue'
import { ref, reactive, onMounted, onUnmounted, inject, nextTick, onBeforeUnmount } from 'vue'
import DatePicker from '@/components/form/datePicker/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { mainHeight } from '@/utils/layout'
import Event from './eventRecall.vue'
import SteadyRecall from './steadyRecall.vue'
const pageHeight = mainHeight(20)
const steadyRef = ref()
const eventRef = ref()
const loading = ref(false)
const activeTab = ref('deviceInfo1')
const checkedNodes = ref<any[]>([]) // 存储左侧树勾选的节点
defineOptions({
name: 'govern/monitorRecall/index'
})
// 处理子组件传递的勾选节点变化
const handleCheckedNodesChange = (nodes: any[]) => {
checkedNodes.value = nodes
// 将勾选的节点传递给当前激活的tab组件
if (activeTab.value === 'deviceInfo1' && steadyRef.value) {
// 如果steadyRecall组件有接收勾选节点的方法可以调用
if (steadyRef.value.setCheckedNodes) {
steadyRef.value.setCheckedNodes(nodes)
}
} else if (activeTab.value === 'deviceInfo2' && eventRef.value) {
// 如果eventRecall组件有接收勾选节点的方法可以调用
if (eventRef.value.setCheckedNodes) {
eventRef.value.setCheckedNodes(nodes)
}
}
}
// tab切换时的处理
const handleClick = (tab: any) => {
activeTab.value = tab.props.name
// tab切换时刷新对应组件的数据
nextTick(() => {
if (tab.props.name === 'deviceInfo1' && steadyRef.value) {
// 刷新稳态补召数据
if (steadyRef.value.refreshData) {
steadyRef.value.refreshData(checkedNodes.value)
} else if (steadyRef.value.getTableParams) {
// 如果有getTableParams方法调用它
steadyRef.value.getTableParams({ nodes: checkedNodes.value })
}
} else if (tab.props.name === 'deviceInfo2' && eventRef.value) {
// 刷新暂态补召数据
if (eventRef.value.refreshData) {
eventRef.value.refreshData(checkedNodes.value)
} else if (eventRef.value.getTableParams) {
// 如果有getTableParams方法调用它
eventRef.value.getTableParams({ nodes: checkedNodes.value })
}
}
})
}
const nodeClick = (node: any) => {
}
const pointTypeChange = (type: any, node: any) => {
}
</script>
<style lang="scss">
.device-control {
display: flex;
height: 100%;
&-left {
// width: 280px;
}
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
height: 100%;
.el-tabs {
height: 100%;
}
.el-tabs__content {
height: calc(100% - 55px);
}
.el-tab-pane {
height: 100%;
}
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;
display: flex;
align-items: center;
}
.content {
box-sizing: border-box;
overflow: auto;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
grid-gap: 10px;
justify-content: center;
.box-card {
display: flex;
flex-direction: column;
justify-content: space-between;
color: var(--el-color-white);
min-height: 80px;
font-size: 13px;
.el-card__header {
padding: 0;
.clearfix {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
height: 35px;
padding: 0 10px;
background: var(--el-color-primary);
}
}
.el-card__body {
flex: 1;
padding: 10px;
margin-bottom: 0;
background-image: linear-gradient(var(--el-color-primary), var(--el-color-primary-light-3));
.box-card-content {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
}
}
}
}
.device-control-right > div {
height: 100%;
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<div class="view" style="height: 100%">
<TableHeader
datePicker
ref="headerRef"
>
<template v-slot:operation>
<el-button type="primary" :icon="Setting" @click="exportTab">补召</el-button>
</template>
</TableHeader>
<Table ref="tableRef" style="height: calc(100% - 120px)" />
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, provide, nextTick, defineEmits, watch } from 'vue'
import { getTabsDataByType } from '@/api/cs-device-boot/EquipmentDelivery'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { Setting } from '@element-plus/icons-vue'
const props = defineProps({
checkedNodes: {
type: Array,
default: () => []
}
});
const tableParams: any = ref({})
const headerRef = ref()
const tableStore: any = new TableStore({
url: '/cs-device-boot/portableOfflLog/queryMainLogPage',
publicHeight: 0,
method: 'POST',
column: [
{
title: '序号', width: 80, formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
field: 'projectName',
title: '工程名称',
minWidth: 170,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
{ field: 'successCount', title: '成功解析数', minWidth: 150 },
{ field: 'startTime', title: '导入开始时间', minWidth: 170, sortable: true },
{ field: 'endTime', title: '导入结束时间', minWidth: 170 , sortable: true},
{
title: '解析状态',
field: 'status',
width: 100,
render: 'tag',
custom: {
0: 'warning',
1: 'success',
2: 'danger',
3: 'primary'
},
replaceValue: {
0: '未解析',
1: '解析成功',
2: '解析失败',
3: '文件不存在'
}
},
{
title: '操作',
width: '100',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '详情',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
}
}
]
}
],
beforeSearchFun: () => {
},
loadCallback: () => {
}
})
provide('tableStore', tableStore)
//获取请求参数
const getTableParams = (val: any) => {
tableParams.value = val
tableStore.index()
}
defineExpose({
getTableParams
})
onMounted(() => {
tableStore.index()
})
</script>
<style lang="scss" scoped>
.header_btn {
width: 100%;
height: 30px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.view {
display: flex;
flex-direction: column;
height: 100%;
}
.view :deep(.el-table) {
height: calc(100% - 56px);
}
</style>