添加工程树

This commit is contained in:
guanj
2026-03-06 09:36:42 +08:00
parent 3fdb41c468
commit 1171d37a86
22 changed files with 1757 additions and 1249 deletions

View File

@@ -1,144 +1,152 @@
import createAxios from '@/utils/request'
// 装置基础数据和模板数据
export function getDeviceData(deviceId: string, type: string, lineId: string) {
let form = new FormData()
form.append('deviceId', deviceId)
form.append('lineId', lineId)
form.append('type', type)
return createAxios({
url: '/cs-device-boot/EquipmentDelivery/deviceData',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: form
})
}
//获取趋势数据、暂态数据、实时数据
export function getTabsDataByType(data: any) {
return createAxios({
url: '/cs-device-boot/csGroup/deviceDataByType',
method: 'POST',
data
})
}
/**** 获取基础实施数据 ****/
export function getBasicRealData(id: any) {
return createAxios({
url: `/cs-harmonic-boot/realData/getBaseRealData?lineId=${id}`,
method: 'POST'
})
}
/**** 获取谐波实时数据 ****/
export function getHarmRealData(id: any, target: any) {
return createAxios({
url: `/cs-harmonic-boot/realData/getHarmRealData?lineId=${id}&target=${target}`,
method: 'POST'
})
}
/**** 获取国标限值 ****/
export function getOverLimitData(id: any) {
return createAxios({
url: `/cs-device-boot/csline/getOverLimitData?id=${id}`,
method: 'POST'
})
}
//获取实时数据列表数据
export function getRealTimeTableList() {
return createAxios({
url: '/cs-device-boot/csGroup/getGroupPortableStatistical',
method: 'GET'
})
}
//离线数据导入
export function uploadOffLineDataFile(data: any) {
return createAxios({
headers: {
'Content-Type': 'multipart/form-data'
},
url: '/cs-device-boot/portableOfflLog/importEquipment',
method: 'POST',
data
})
}
//查询实时数据中实时趋势中指标分组
export function getDeviceTrendDataGroup() {
return createAxios({
url: '/cs-device-boot/csGroup/getDeviceTrendDataGroup',
method: 'GET'
})
}
//根据指标分组查询实时数据中实时趋势
export function getDeviceTrendData(query: any) {
return createAxios({
url: '/cs-device-boot/csGroup/getDeviceTrendData',
method: 'GET',
params: query
})
}
//查询实时数据-谐波频谱-稳态指标
export function getGroupPortableStatistical() {
return createAxios({
url: '/cs-device-boot/csGroup/getGroupPortableStatistical',
method: 'GET'
})
}
//查询实时数据-谐波频谱
export function getDeviceHarmonicSpectrumData(data: any) {
return createAxios({
url: '/cs-device-boot/csGroup/getDeviceHarmonicSpectrumData',
method: 'POST',
data: data
})
}
//获取指标类型-谐波频谱
export function queryDictType(data?: any) {
return createAxios({
url: '/system-boot/dictTree/queryDictType',
method: 'GET',
params: data
})
}
//根据监测点id获取监测点详情
export function getById(data?: any) {
return createAxios({
url: '/cs-device-boot/csline/getById',
method: 'POST',
params: data
})
}
//测试项日志修改
export function updateRecordData(data?: any) {
return createAxios({
url: '/cs-device-boot/wlRecord/updateRecordData',
method: 'POST',
data
})
}
//模块数据
export function allModelData(data?: any) {
return createAxios({
url: '/cs-harmonic-boot/data/allModelData',
method: 'POST',
data
})
}
//刷新状态
export function getModuleState(data?: any) {
return createAxios({
url: '/cs-harmonic-boot/data/getModuleState',
method: 'POST',
params: data
})
}
import createAxios from '@/utils/request'
// 装置基础数据和模板数据
export function getDeviceData(deviceId: string, type: string, lineId: string) {
let form = new FormData()
form.append('deviceId', deviceId)
form.append('lineId', lineId)
form.append('type', type)
return createAxios({
url: '/cs-device-boot/EquipmentDelivery/deviceData',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: form
})
}
//获取趋势数据、暂态数据、实时数据
export function getTabsDataByType(data: any) {
return createAxios({
url: '/cs-device-boot/csGroup/deviceDataByType',
method: 'POST',
data
})
}
/**** 获取基础实施数据 ****/
export function getBasicRealData(id: any) {
return createAxios({
url: `/cs-harmonic-boot/realData/getBaseRealData?lineId=${id}`,
method: 'POST'
})
}
/**** 获取谐波实时数据 ****/
export function getHarmRealData(id: any, target: any) {
return createAxios({
url: `/cs-harmonic-boot/realData/getHarmRealData?lineId=${id}&target=${target}`,
method: 'POST'
})
}
/**** 获取国标限值 ****/
export function getOverLimitData(id: any) {
return createAxios({
url: `/cs-device-boot/csline/getOverLimitData?id=${id}`,
method: 'POST'
})
}
//获取实时数据列表数据
export function getRealTimeTableList() {
return createAxios({
url: '/cs-device-boot/csGroup/getGroupPortableStatistical',
method: 'GET'
})
}
//离线数据导入
export function uploadOffLineDataFile(data: any) {
return createAxios({
headers: {
'Content-Type': 'multipart/form-data'
},
url: '/cs-device-boot/portableOfflLog/importEquipment',
method: 'POST',
data
})
}
//查询实时数据中实时趋势中指标分组
export function getDeviceTrendDataGroup() {
return createAxios({
url: '/cs-device-boot/csGroup/getDeviceTrendDataGroup',
method: 'GET'
})
}
//根据指标分组查询实时数据中实时趋势
export function getDeviceTrendData(query: any) {
return createAxios({
url: '/cs-device-boot/csGroup/getDeviceTrendData',
method: 'GET',
params: query
})
}
//查询实时数据-谐波频谱-稳态指标
export function getGroupPortableStatistical() {
return createAxios({
url: '/cs-device-boot/csGroup/getGroupPortableStatistical',
method: 'GET'
})
}
//查询实时数据-谐波频谱
export function getDeviceHarmonicSpectrumData(data: any) {
return createAxios({
url: '/cs-device-boot/csGroup/getDeviceHarmonicSpectrumData',
method: 'POST',
data: data
})
}
//获取指标类型-谐波频谱
export function queryDictType(data?: any) {
return createAxios({
url: '/system-boot/dictTree/queryDictType',
method: 'GET',
params: data
})
}
//根据监测点id获取监测点详情
export function getById(data?: any) {
return createAxios({
url: '/cs-device-boot/csline/getById',
method: 'POST',
params: data
})
}
//测试项日志修改
export function updateRecordData(data?: any) {
return createAxios({
url: '/cs-device-boot/wlRecord/updateRecordData',
method: 'POST',
data
})
}
//模块数据
export function allModelData(data?: any) {
return createAxios({
url: '/cs-harmonic-boot/data/allModelData',
method: 'POST',
data
})
}
//刷新状态
export function getModuleState(data?: any) {
return createAxios({
url: '/cs-harmonic-boot/data/getModuleState',
method: 'POST',
params: data
})
}
//获取运行取数
export function getRawData(data?: any) {
return createAxios({
url: '/cs-device-boot/pqsCommunicate/getRawData',
method: 'POST',
data
})
}

View File

@@ -1,18 +1,20 @@
import createAxios from '@/utils/request'
// 设备列表
export function getDeviceTree() {
export function getDeviceTree(params?: any) {
return createAxios({
url: '/cs-device-boot/csLedger/deviceTree',
method: 'POST'
method: 'POST',
params
})
}
// 监测点列表
export function getLineTree() {
export function getLineTree(params?: any) {
return createAxios({
url: '/cs-device-boot/csLedger/lineTree',
method: 'POST'
method: 'POST',
params
})
}
// 监测点列表治理

View File

@@ -147,8 +147,9 @@ const tableStore: any = new TableStore({
backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0,
formatter: function (a: any) {
var relVal = ''
relVal = "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
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:" + "'>特征幅值:" + a.value[1].toFixed(2) + '%</font>'
return relVal
@@ -214,18 +215,18 @@ const tableStore: any = new TableStore({
// [0.2, 10, '2023-01-01 10:00:00'],
// [0.4, 50, '2023-01-01 11:00:00']
// ],
legendSymbol: 'circle',
tooltip: {
show: true,
trigger: 'item',
formatter: function (params: any) {
return `<strong>可容忍事件</strong><br/>
持续时间: ${params.value[0]}s<br/>
特征幅值: ${params.value[1].toFixed(2)}%<br/>
发生时间: ${params.value[2] || 'N/A'}`
}
}
legendSymbol: 'circle'
// tooltip: {
// show: true,
// trigger: 'item',
// formatter: function (params: any) {
// return `<strong>可容忍事件</strong><br/>
// 持续时间: ${params.value[0]}s<br/>
// 特征幅值: ${params.value[1].toFixed(2)}%<br/>
// 发生时间: ${params.value[2] || 'N/A'}`
// }
// }
},
{
name: '不可容忍事件',

View File

@@ -186,7 +186,7 @@ const initProbabilityData = () => {
var tips = ''
tips += '指标类型: ' + yAxisData[yIndex] + '</br>'
tips += '越限程度: ' + params.seriesName + '</br>'
tips += '越限数: ' + params.value[2] + '</br>'
tips += '越限数: ' + params.value[2] + '</br>'
return tips
}
},
@@ -228,7 +228,7 @@ const initProbabilityData = () => {
},
zAxis3D: {
type: 'value',
name: '越限数',
name: '越限数',
nameLocation: 'middle',
nameGap: 30,
minInterval: 10

View File

@@ -185,7 +185,7 @@ const initProbabilityData = () => {
var tips = ''
tips += '指标类型: ' + yAxisData[yIndex] + '</br>'
tips += '越限程度: ' + params.seriesName + '</br>'
tips += '越限数: ' + params.value[2] + '</br>'
tips += '越限数: ' + params.value[2] + '</br>'
return tips
}
},
@@ -227,7 +227,7 @@ const initProbabilityData = () => {
},
zAxis3D: {
type: 'value',
name: '越限数',
name: '越限数',
nameLocation: 'middle',
nameGap: 30,
minInterval: 10

View File

@@ -106,13 +106,15 @@ const initChart = () => {
start: 0,
bottom: '20px',
end: 100
end: 100,
filterMode: 'none'
},
{
start: 0,
height: 13,
bottom: '20px',
end: 100
end: 100,
filterMode: 'none'
}
// {
// show: true,

View File

@@ -14,7 +14,7 @@
/>
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
<div style="display: flex; align-items: center" class="mb10">
<el-input maxlength="32" show-word-limit v-model.trim="filterText" placeholder="请输入内容" clearable>
<el-input maxlength="32" v-model.trim="filterText" placeholder="请输入内容" clearable>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>

View File

@@ -5,7 +5,7 @@
style='cursor: pointer' />
<div class='cn-tree' :style='{ opacity: menuCollapse ? 0 : 1 }'>
<div style='display: flex; align-items: center' class='mb10'>
<el-input maxlength="32" show-word-limit v-model.trim='filterText' placeholder='请输入内容' clearable>
<el-input maxlength="32" v-model.trim='filterText' placeholder='请输入内容' clearable>
<template #prefix>
<Icon name='el-icon-Search' style='font-size: 16px' />
</template>

View File

@@ -13,18 +13,29 @@
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
<div style="display: flex; align-items: center" class="mb10">
<!-- <el-form-item> -->
<el-input
maxlength="32"
show-word-limit
v-model.trim="filterText"
autocomplete="off"
placeholder="请输入内容"
clearable
>
<template #prepend>
<el-select v-model="treeType" @change="changeTreeType" style="min-width: 75px">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
<!-- </el-form-item> -->
<Icon
@click="onMenuCollapse"
@@ -42,6 +53,8 @@
v-model.trim="activeName"
style="flex: 1; height: 100%"
@change="changeDevice"
v-if="treeType == '1'"
v-loading="loading"
>
<el-collapse-item title="治理设备" name="0" v-if="zlDeviceData.length != 0">
<el-select v-model.trim="process" clearable placeholder="请选择状态" class="mb10">
@@ -142,6 +155,32 @@
</el-tree>
</el-collapse-item>
</el-collapse>
<div v-if="treeType == '2'" v-loading="loading">
<el-tree
:style="{ height: 'calc(100vh - 188px)' }"
ref="treeRef4"
:props="defaultProps"
highlight-current
:filter-node-method="filterNode"
node-key="id"
v-bind="$attrs"
:data="data"
style="overflow: auto"
:default-expand-all="false"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<Icon
:name="data.icon"
style="font-size: 16px"
:style="{ color: data.color }"
v-if="data.icon"
/>
<span style="margin-left: 4px">{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
</div>
</div>
</template>
@@ -154,7 +193,7 @@ import { ref, watch, defineEmits, onMounted, nextTick } from 'vue'
defineOptions({
name: 'govern/tree'
})
const emit = defineEmits(['changeDeviceType'])
const emit = defineEmits(['changeDeviceType', 'changeTreeType'])
interface Props {
width?: string
canExpand?: boolean
@@ -170,6 +209,17 @@ const props = withDefaults(defineProps<Props>(), {
data: [],
height: 0
})
const treeType = ref('1')
const options = [
{
label: '设备',
value: '1'
},
{
label: '工程',
value: '2'
}
]
const { proxy } = useCurrentInstance()
const menuCollapse = ref(false)
const activeName = ref('0')
@@ -219,7 +269,9 @@ watch(
)
watch(filterText, val => {
if (activeName.value == '0') {
if (treeType.value == '2') {
treeRef4.value!.filter(val)
} else if (activeName.value == '0') {
treeRef1.value!.filter(val)
} else if (activeName.value == '1') {
treeRef2.value!.filter(val)
@@ -362,27 +414,43 @@ const treeRef1 = ref<InstanceType<typeof ElTree>>()
const treeRef2 = ref<InstanceType<typeof ElTree>>()
//前置
const treeRef3 = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef1, treeRef2, treeRef3 })
const treeRef4 = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef1, treeRef2, treeRef3, treeRef4 })
onMounted(() => {
setTimeout(() => {
if (zlDeviceData.value.length != 0) {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
activeName.value = '0'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
activeName.value = '1'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length === 0) {
activeName.value = '2'
}
if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = ''
}
nextTick(() => {
changeDevice(activeName.value)
})
setActiveName()
}, 500)
})
const setActiveName = () => {
if (zlDeviceData.value.length != 0) {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
activeName.value = '0'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
activeName.value = '1'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length === 0) {
activeName.value = '2'
}
if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = ''
}
nextTick(() => {
changeDevice(activeName.value)
})
}
const loading = ref(false)
const changeTreeType = (val: string) => {
loading.value = true
emit('changeTreeType', val)
if (val == '1') {
setActiveName()
}
setTimeout(() => {
loading.value = false
}, 1000)
}
</script>
<style lang="scss" scoped>
@@ -412,4 +480,7 @@ onMounted(() => {
display: flex;
align-items: center;
}
:deep(.el-input-group__prepend) {
background-color: var(--el-fill-color-blank);
}
</style>

View File

@@ -7,6 +7,7 @@
:data="tree"
:height="props.height"
@changeDeviceType="changeDeviceType"
@changeTreeType="info"
/>
</template>
@@ -16,6 +17,7 @@ import Tree from '../device.vue'
import { getDeviceTree } from '@/api/cs-device-boot/csLedger'
import { useConfig } from '@/stores/config'
import { throttle } from 'lodash'
import { on } from 'events'
defineOptions({
name: 'govern/deviceTree'
})
@@ -38,112 +40,149 @@ const treRef = ref()
const changeDeviceType = (val: any, obj: any) => {
emit('deviceTypeChange', val, obj)
}
getDeviceTree().then(res => {
let arr: any[] = []
let arr2: any[] = []
let arr3: any[] = []
//治理设备
res.data.map((item: any) => {
if (item.name == '治理设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
const info = (type?: string) => {
getDeviceTree({ type: type == '2' ? 'engineering' : '' }).then(res => {
let arr: any[] = []
let arr2: any[] = []
let arr3: any[] = []
let arr4: any[] = []
//治理设备
res.data.map((item: any) => {
if (type == '2') {
item.icon = 'el-icon-Menu'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.pName = '治理设备'
item3.icon = 'el-icon-Platform'
item3.level = 2
item3.color = config.getColorVal('elementUiPrimary')
if (item3.comFlag === 1) {
item3.color = '#e26257 !important'
}
arr.push(item3)
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.color =
item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
arr4.push(item2)
})
})
})
} else if (item.name == '便携式设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-Platform'
item.color = config.getColorVal('elementUiPrimary')
item.color = '#e26257 !important'
item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
// item.disabled =true
item.pName = '便携式设备'
if (item.type == 'device') {
arr2.push(item)
}
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
item2.color = item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item2.pName = '便携式设备'
// item2.children.forEach((item3: any) => {
// item3.icon = 'el-icon-Platform'
// item3.color = config.getColorVal('elementUiPrimary')
// if (item3.comFlag === 1) {
// item3.color = '#e26257 !important'
// }
// arr.push(item3)
// })
})
})
} else if (item.name == '监测设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.pName = '监测设备'
item3.icon = 'el-icon-Platform'
item3.color = config.getColorVal('elementUiPrimary')
if (item3.comFlag === 1) {
item3.color = '#e26257 !important'
}
arr3.push(item3)
})
})
})
}
})
tree.value = res.data
nextTick(() => {
setTimeout(() => {
if (arr.length > 0) {
treRef.value.treeRef1.setCurrentKey(arr[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr[0]
})
return
} else if (arr2.length > 0) {
treRef.value.treeRef2.setCurrentKey(arr2[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr2[0]
})
return
} else if (arr3.length > 0) {
console.log('🚀 ~ arr3:', arr3)
treRef.value.treeRef3.setCurrentKey(arr3[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr3[0]
})
return
} else {
emit('init')
return
if (item.name == '治理设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.pName = '治理设备'
item3.icon = 'el-icon-Platform'
item3.level = 2
item3.color = config.getColorVal('elementUiPrimary')
if (item3.comFlag === 1) {
item3.color = '#e26257 !important'
}
arr.push(item3)
})
})
})
} else if (item.name == '便携式设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-Platform'
item.color = config.getColorVal('elementUiPrimary')
item.color = '#e26257 !important'
item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
// item.disabled =true
item.pName = '便携式设备'
if (item.type == 'device') {
arr2.push(item)
}
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
item2.color =
item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item2.pName = '便携式设备'
// item2.children.forEach((item3: any) => {
// item3.icon = 'el-icon-Platform'
// item3.color = config.getColorVal('elementUiPrimary')
// if (item3.comFlag === 1) {
// item3.color = '#e26257 !important'
// }
// arr.push(item3)
// })
})
})
} else if (item.name == '监测设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.pName = '监测设备'
item3.icon = 'el-icon-Platform'
item3.color = config.getColorVal('elementUiPrimary')
if (item3.comFlag === 1) {
item3.color = '#e26257 !important'
}
arr3.push(item3)
})
})
})
}
}
}, 500)
})
tree.value = res.data
nextTick(() => {
setTimeout(() => {
if (type == '2') {
//初始化选中
treRef.value?.treeRef4.setCurrentKey(arr4[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr4[0]
})
// changePointType('4', arr4[0])
return
}
if (arr.length > 0) {
treRef.value.treeRef1.setCurrentKey(arr[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr[0]
})
return
} else if (arr2.length > 0) {
treRef.value.treeRef2.setCurrentKey(arr2[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr2[0]
})
return
} else if (arr3.length > 0) {
console.log('🚀 ~ arr3:', arr3)
treRef.value.treeRef3.setCurrentKey(arr3[0].id)
// 注册父组件事件
emit('init', {
level: 2,
...arr3[0]
})
return
} else {
emit('init')
return
}
}, 500)
})
})
}
onMounted(() => {
info('1')
})
throttle(

View File

@@ -1,5 +1,12 @@
<template>
<Tree ref="treRef" :width="width" :data="tree" default-expand-all @changePointType="changePointType" />
<Tree
ref="treRef"
:width="width"
:data="tree"
default-expand-all
@changePointType="changePointType"
@changeTreeType="info"
/>
</template>
<script lang="ts" setup>
@@ -27,80 +34,124 @@ const dictData = useDictData()
const treRef = ref()
const width = ref('')
const info = () => {
const info = (type?: string) => {
tree.value = []
let arr1: any[] = []
let arr2: any[] = []
let arr3: any[] = []
getLineTree().then(res => {
let arr4: any[] = []
getLineTree({ type: type == '2' ? 'engineering' : '' }).then(res => {
//治理设备
res.data.map((item: any) => {
if (item.name == '治理设备') {
if (type == '2') {
item.icon = 'el-icon-Menu'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.level = 1
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.level = 1
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.level = 2
item3.color =
item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-Platform'
item4.color =
item4.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
// item4.color = '#e26257 !important'
arr1.push(item4)
})
arr4.push(item3)
// item3.children.forEach((item4: any) => {
// item4.icon = 'el-icon-Platform'
// item4.color =
// item4.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
// })
})
})
})
} else if (item.name == '便携式设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-Platform'
item.color = config.getColorVal('elementUiPrimary')
item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
item2.color =
item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
arr2.push(item2)
})
})
} else if (item.name == '监测设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.level = 1
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.level = 1
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.level = 1
item3.color =
item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-Platform'
item4.color =
item4.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
// item4.color = '#e26257 !important'
arr3.push(item4)
} else {
if (item.name == '治理设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.level = 1
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.level = 1
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.level = 2
item3.color =
item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-Platform'
item4.color =
item4.comFlag === 2
? config.getColorVal('elementUiPrimary')
: '#e26257 !important'
// item4.color = '#e26257 !important'
arr1.push(item4)
})
})
})
})
})
} else if (item.name == '便携式设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-Platform'
item.color = config.getColorVal('elementUiPrimary')
item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
item2.color =
item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
arr2.push(item2)
})
})
} else if (item.name == '监测设备') {
item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.level = 1
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List'
item2.level = 1
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.level = 1
item3.color =
item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-Platform'
item4.color =
item4.comFlag === 2
? config.getColorVal('elementUiPrimary')
: '#e26257 !important'
// item4.color = '#e26257 !important'
arr3.push(item4)
})
})
})
})
}
}
})
tree.value = res.data
nextTick(() => {
setTimeout(() => {
if (arr1.length > 0) {
if (type == '2') {
//初始化选中
treRef.value?.treeRef4.setCurrentKey(arr4[0].id)
// 注册父组件事件
emit('init', {
level: 3,
...arr4[0]
})
changePointType('4', arr4[0])
return
} else if (arr1.length > 0) {
//初始化选中
treRef.value?.treeRef1.setCurrentKey(arr1[0].id)
// 注册父组件事件
@@ -119,7 +170,6 @@ const info = () => {
})
return
} else if (arr3.length > 0) {
treRef.value?.treeRef3?.setCurrentKey(arr3[0].id)
emit('init', {
level: 2,

View File

@@ -5,7 +5,7 @@
<div style="display: flex; align-items: center" class="mb10">
<el-input
maxlength="32"
show-word-limit
v-model.trim="filterText"
placeholder="请输入内容"
clearable

View File

@@ -5,7 +5,7 @@
style='cursor: pointer' />
<div class='cn-tree' :style='{ opacity: menuCollapse ? 0 : 1 }'>
<div style='display: flex; align-items: center' class='mb10'>
<el-input maxlength="32" show-word-limit v-model.trim='filterText' placeholder='请输入内容' clearable>
<el-input maxlength="32" v-model.trim='filterText' placeholder='请输入内容' clearable>
<template #prefix>
<Icon name='el-icon-Search' style='font-size: 16px' />
</template>

View File

@@ -13,11 +13,27 @@
/>
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1, display: menuCollapse ? 'none' : '' }">
<div style="display: flex; align-items: center" class="mb10">
<el-input maxlength="32" show-word-limit v-model.trim="filterText" placeholder="请输入内容" clearable>
<!-- <el-input maxlength="32" v-model.trim="filterText" placeholder="请输入内容" clearable>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input> -->
<el-input maxlength="32" v-model.trim="filterText" placeholder="请输入内容" clearable>
<template #prepend>
<el-select v-model="treeType" @change="changeTreeType" style="min-width: 75px">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
<!-- -->
<Icon
@click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
@@ -34,6 +50,8 @@
v-model.trim="activeName"
style="flex: 1; height: 100%"
@change="changeDevice"
v-if="treeType == '1'"
v-loading="loading"
>
<el-collapse-item title="治理设备" name="0" v-if="zlDeviceData.length != 0">
<el-select v-model.trim="process" clearable placeholder="请选择状态" class="mb10">
@@ -120,6 +138,33 @@
</el-tree>
</el-collapse-item>
</el-collapse>
<div v-if="treeType == '2'" v-loading="loading">
<el-tree
:style="{ height: 'calc(100vh - 188px)' }"
class="pt10"
ref="treeRef4"
:props="defaultProps"
highlight-current
:filter-node-method="filterNode"
node-key="id"
v-bind="$attrs"
:data="data"
style="overflow: auto"
:default-expand-all="false"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<Icon
:name="data.icon"
style="font-size: 16px"
:style="{ color: data.color }"
v-if="data.icon"
/>
<span style="margin-left: 4px">{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
</div>
</div>
</template>
@@ -133,7 +178,7 @@ import { useRoute } from 'vue-router'
defineOptions({
name: 'govern/tree'
})
const emit = defineEmits(['changePointType'])
const emit = defineEmits(['changePointType', 'changeTreeType'])
interface Props {
width?: string
canExpand?: boolean
@@ -157,6 +202,17 @@ const defaultProps = {
label: 'name',
value: 'id'
}
const treeType = ref('1')
const options = [
{
label: '设备',
value: '1'
},
{
label: '工程',
value: '2'
}
]
//治理设备数据
const zlDeviceData = ref<any>([])
const zlDevList = ref<any>([])
@@ -196,7 +252,9 @@ watch(
)
watch(filterText, val => {
if (activeName.value == '0') {
if (treeType.value == '2') {
treeRef4.value!.filter(val)
} else if (activeName.value == '0') {
treeRef1.value!.filter(val)
} else if (activeName.value == '1') {
treeRef2.value!.filter(val)
@@ -217,8 +275,6 @@ watch(process, val => {
})
const changeDevice = (val: any) => {
console.log('🚀 ~ changeDevice ~ val:', val)
let arr1: any = []
//zlDeviceData
zlDevList.value.forEach((item: any) => {
@@ -381,27 +437,43 @@ const treeRef1 = ref<InstanceType<typeof ElTree>>()
const treeRef2 = ref<InstanceType<typeof ElTree>>()
//在线
const treeRef3 = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef1, treeRef2, treeRef3 })
// 工程
const treeRef4 = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef1, treeRef2, treeRef3, treeRef4 })
onMounted(() => {
setTimeout(() => {
if (zlDeviceData.value.length != 0) {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
activeName.value = '0'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
activeName.value = '1'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length === 0) {
activeName.value = '2'
}
if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = '2'
}
nextTick(() => {
changeDevice(activeName.value)
})
setActiveName()
}, 500)
})
const setActiveName = () => {
if (zlDeviceData.value.length != 0) {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
activeName.value = '0'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
activeName.value = '1'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length === 0) {
activeName.value = '2'
}
if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = '2'
}
nextTick(() => {
changeDevice(activeName.value)
})
}
const loading = ref(false)
const changeTreeType = (val: string) => {
loading.value = true
emit('changeTreeType', val)
if (val == '1') {
setActiveName()
}
setTimeout(() => {
loading.value = false
}, 1000)
}
</script>
<style lang="scss" scoped>
@@ -432,4 +504,7 @@ onMounted(() => {
display: flex;
align-items: center;
}
:deep(.el-input-group__prepend) {
background-color: var(--el-fill-color-blank);
}
</style>

View File

@@ -5,7 +5,7 @@
style='cursor: pointer' />
<div class='cn-tree' :style='{ opacity: menuCollapse ? 0 : 1 }'>
<div style='display: flex; align-items: center' class='mb10'>
<el-input maxlength="32" show-word-limit v-model.trim='filterText' placeholder='请输入内容' clearable>
<el-input maxlength="32" v-model.trim='filterText' placeholder='请输入内容' clearable>
<template #prefix>
<Icon name='el-icon-Search' style='font-size: 16px' />
</template>

View File

@@ -4,7 +4,7 @@ import { ElLoading, ElMessage, ElNotification, type LoadingOptions } from 'eleme
import { refreshToken } from '@/api/user-boot/user'
import router from '@/router/index'
import { useAdminInfo } from '@/stores/adminInfo'
import { useNavTabs } from '@/stores/navTabs'
window.requests = []
window.tokenRefreshing = false
let loginExpireTimer: any = null
@@ -13,7 +13,7 @@ const loadingInstance: LoadingInstance = {
target: null,
count: 0
}
const navTabs = useNavTabs()
/**
* 根据运行环境获取基础请求URL
*/
@@ -164,6 +164,9 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
message: response.data.message
})
adminInfo.removeToken()
navTabs.closeTabs()
window.localStorage.clear()
adminInfo.reset()
router.push({ name: 'login' })
loginExpireTimer = null // 执行后清空定时器
}, 100) // 可根据实际情况调整延迟时间

View File

@@ -100,6 +100,7 @@ const tableStore = new TableStore({
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center', width: 120 },
{ title: '监测点名称', field: 'lineName', align: 'center', width: 140 },
{ title: '工程名称', field: 'engineeringName', align: 'center', width: 120 },
{ title: '项目名称', field: 'projectName', align: 'center', width: 120 },
{ title: '发生时刻', field: 'startTime', align: 'center', width: 180, sortable: true },

View File

@@ -12,7 +12,7 @@
</pane>
<pane style="background: #fff">
<div class="device-manage-right">
<el-form :inline="true" class="demo-form-inline" style="height: 42px">
<el-form :inline="true" class="demo-form-inline" style="height: 42px">
<el-form-item style="position: relative; z-index: 2">
<el-button icon="el-icon-Plus" type="primary" @click="add" v-if="nodeLevel != 4">
{{
@@ -77,7 +77,7 @@
<el-form
class="main-form overview_scroll"
:label-position="'right'"
label-width="120px"
label-width="130px"
:inline="true"
ref="mainForm"
:model="formData"
@@ -965,7 +965,11 @@
class="form-item"
label="是否治理:"
:prop="'lineInfoList[' + lIndex + '].govern'"
:rules="{ required: true, message: '请选择是否治理', trigger: 'change' }"
:rules="{
required: true,
message: '请选择是否治理',
trigger: 'change'
}"
>
<el-select
clearable
@@ -1015,7 +1019,11 @@
class="form-item"
label="日志等级:"
:prop="'lineInfoList[' + lIndex + '].lineLogLevel'"
:rules="{ required: true, message: '请选择日志等级', trigger: 'change' }"
:rules="{
required: true,
message: '请选择日志等级',
trigger: 'change'
}"
>
<!-- 0运行1检修2停运3调试4退运 -->
<el-select
@@ -1031,7 +1039,7 @@
)
"
>
<el-option
<el-option
v-for="value in logList"
:key="value.value"
:label="value.label"
@@ -1039,7 +1047,34 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item
class="form-item"
label="是否主要监测点:"
:prop="'lineInfoList[' + lIndex + '].isImportant'"
:rules="{
required: true,
message: '请选择是否主要监测点',
trigger: 'change'
}"
>
<!-- 0运行1检修2停运3调试4退运 -->
<el-select
clearable
filterable
v-model="lineItem.isImportant"
placeholder="请选择是否主要监测点"
:disabled="
!(
(nodeLevel == 4 && pageStatus == 3) ||
((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) &&
pageStatus == 2)
)
"
>
<el-option label="是" :value="1"></el-option>
<el-option label="否" :value="0"></el-option>
</el-select>
</el-form-item>
</div>
</el-tab-pane>
</el-tabs>
@@ -1277,7 +1312,8 @@ interface LineInfo {
monitorObj: string
position: string
govern: string | number
lineLogLevel: string
lineLogLevel: string
isImportant: string | number
runStatus: string | number
basicCapacity: number
shortCircuitCapacity: number
@@ -1660,6 +1696,7 @@ const add = () => {
position: '',
govern: 0,
lineLogLevel: 'WARN',
isImportant: 0,
runStatus: 0,
basicCapacity: 0,
shortCircuitCapacity: 0,
@@ -1772,7 +1809,7 @@ const updateEquipmentFunc = (id: any) => {
id: id, // 设备ID用于修改
name: currentDevice.name,
devModel: currentDevice.devModel,
devType: currentDevice.devType,
devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod,
devLogLevel: currentDevice.devLogLevel,
mac: currentDevice.mac,
@@ -1839,6 +1876,7 @@ const updateLineFunc = (id: any) => {
position: currentLine.position || '',
govern: currentLine.govern,
lineLogLevel: currentLine.lineLogLevel,
isImportant: currentLine.isImportant,
runStatus: currentLine.runStatus,
basicCapacity: currentLine.basicCapacity || 0,
shortCircuitCapacity: currentLine.shortCircuitCapacity || 0,
@@ -2004,7 +2042,7 @@ const next = async () => {
devModel: '',
devType: '',
devAccessMethod: 'CLD',
devLogLevel: 'WARN',
devLogLevel: 'WARN',
mac: '',
ndid: '',
nodeId: '',
@@ -2037,7 +2075,8 @@ const next = async () => {
monitorObj: '',
position: '',
govern: 0,
lineLogLevel:'WARN',
lineLogLevel: 'WARN',
isImportant: 0,
runStatus: 0,
basicCapacity: 0,
shortCircuitCapacity: 0,
@@ -2443,7 +2482,7 @@ const resetAllForms = () => {
device.devType = ''
device.devAccessMethod = 'CLD'
device.devLogLevel = 'WARN'
device.mac = ''
device.nodeId = ''
device.cntractNo = ''
@@ -2466,6 +2505,7 @@ const resetAllForms = () => {
line.position = ''
line.govern = 0
line.lineLogLevel = 'WARN'
line.isImportant = 0
line.runStatus = 0
line.basicCapacity = 0
line.shortCircuitCapacity = 0
@@ -2636,6 +2676,7 @@ const submitData = () => {
position: currentLine.position,
govern: currentLine.govern,
lineLogLevel: currentLine.lineLogLevel,
isImportant: currentLine.isImportant,
runStatus: currentLine.runStatus,
basicCapacity: currentLine.basicCapacity,
shortCircuitCapacity: currentLine.shortCircuitCapacity,
@@ -2750,7 +2791,7 @@ const handleBusBarTabsEdit = (targetName: any, action: any) => {
devModel: '',
devType: '',
devAccessMethod: 'CLD',
devLogLevel: 'WARN',
devLogLevel: 'WARN',
mac: '',
ndid: '',
nodeId: '',
@@ -2828,6 +2869,7 @@ const handleLineTabsEdit = (targetName: any, action: any) => {
position: '',
govern: 0,
lineLogLevel: 'WARN',
isImportant: 0,
runStatus: 0,
basicCapacity: 0,
shortCircuitCapacity: 0,

View File

@@ -141,7 +141,8 @@
v-show="
dataSet.includes('_items') ||
dataSet.indexOf('_history') != -1 ||
dataSet.indexOf('_moduleData') != -1
dataSet.indexOf('_moduleData') != -1||
dataSet.indexOf('_devRunTrend') != -1
"
>
<DatePicker ref="datePickerRef"></DatePicker>
@@ -165,7 +166,7 @@
</el-select> -->
<el-radio-group
v-model.trim="formInline.dataLevel"
v-if="!dataSet.includes('_moduleData') && TrendList?.lineType == 1"
v-if="!dataSet.includes('_devRunTrend') &&!dataSet.includes('_moduleData') && TrendList?.lineType == 1"
:disabled="TrendList?.lineType != 1"
@change="handleClick"
>
@@ -525,6 +526,14 @@
>
<moduleData ref="moduleDataRef" @onSubmit="handleClick" />
</div>
<!-- 运行趋势 -->
<div
style="height: calc(100vh - 395px)"
v-if="dataSet.indexOf('_devRunTrend') != -1"
v-loading="tableLoading"
>
<operatingTrend ref="operatingTrendRef" @onSubmit="handleClick" />
</div>
<div v-if="!tableData" style="height: 42px"></div>
</el-tabs>
</div>
@@ -548,7 +557,8 @@ import {
getOverLimitData,
queryDictType,
getById,
allModelData
allModelData,
getRawData
} from '@/api/cs-device-boot/EquipmentDelivery'
import { deviceHisData, deviceRtData, realTimeData, getTestData } from '@/api/cs-device-boot/csGroup'
import { ref, reactive, onMounted, onUnmounted, inject, nextTick, onBeforeUnmount } from 'vue'
@@ -557,6 +567,7 @@ import DatePicker from '@/components/form/datePicker/index.vue'
import Trend from './tabs/trend.vue' //趋势数据
import realTime from './tabs/realtime.vue' //实时数据-主界面
import realTrend from './tabs/components/realtrend.vue' //实时数据-实时趋势
import operatingTrend from './tabs/operatingTrend.vue' //运行趋势
import harmonicSpectrum from './tabs/components/harmonicSpectrum.vue' //实时数据-谐波频谱子页面
import recordWoves from './tabs/components/recordwoves.vue' //实时数据-实时录波子页面
import offLineDataImport from './offLineDataImport/index.vue'
@@ -660,6 +671,7 @@ const volConTypeList = dictData.getBasicData('Dev_Connect')
// }
//谐波频谱
const realTrendRef = ref()
const operatingTrendRef = ref()
const changeTrendType = (val: any) => {
trendDataTime.value = ''
activeTrendName.value = val * 1
@@ -920,6 +932,10 @@ const nodeClick = async (e: anyObj, node: any) => {
if (item.type === 'moduleData') {
item.id = item.id + '_moduleData'
}
// 模块数据
if (item.type === 'devRunTrend') {
item.id = item.id + '_devRunTrend'
}
})
res.data.dataSetList = res.data.dataSetList.filter((item: any) => item.name != '历史统计数据')
//便携式设备默认二次值
@@ -1316,6 +1332,39 @@ const handleClick = async (tab?: any) => {
}, 0)
}, 0)
}
//运行趋势
if (dataSet.value.includes('_devRunTrend')) {
setTimeout(async () => {
if (tab.props != undefined) await (datePickerRef.value && datePickerRef.value?.setInterval(5))
let obj = {
// devId: deviceId.value, //e.id
lineId: [deviceId.value], //e.pid
startTime: datePickerRef.value && datePickerRef.value.timeValue[0],
endTime: datePickerRef.value && datePickerRef.value.timeValue[1]
}
await setTimeout(() => {
getRawData(obj)
.then((res: any) => {
tableLoading.value = false
setTimeout(() => {
operatingTrendRef.value?.setData(res.data)
}, 500)
setTimeout(() => {
loading.value = false
}, 1500)
})
.catch(e => {
setTimeout(() => {
tableLoading.value = false
}, 1500)
})
}, 0)
}, 0)
}
//查询当前指标
if (!dataSet.value.includes('_')) {

View File

@@ -0,0 +1,165 @@
<template>
<div :style="height">
<MyEchart v-if="list.length != 0" :options="options1" style="height: 100%; width: 100%" class="pt10" />
<el-empty description="暂无数据" style="width: 100%; height: 100%" v-else></el-empty>
</div>
</template>
<script setup lang="ts">
import MyEchart from '@/components/echarts/MyEchart.vue'
import { ref, reactive } from 'vue'
import { mainHeight } from '@/utils/layout'
import { max } from 'lodash'
const height = ref(mainHeight(290))
const list = ref([])
const options1 = ref({})
const setData = (data: any) => {
// list.value = [...fillDataFromFirstTime(data),...data]
list.value = data
init()
}
/**
* 补全离散数据严格从数组第一个time开始最后一个time结束
* @param {Array} data 原始离散数据数组
* @param {number} interval 补全时间间隔默认10秒
* @returns {Array} 补全后的连续数据
*/
function fillDataFromFirstTime(data, interval = 10) {
// 1. 基础校验
if (!Array.isArray(data) || data.length === 0) {
console.error('原始数据必须是非空数组')
return []
}
// 2. 锁定起始时间直接取数组第一个元素的time不做任何偏移
const firstItem = data[0]
const startTime = new Date(firstItem.time)
const startTimestamp = startTime.getTime()
// 3. 锁定结束时间取数组最后一个元素的time
const lastItem = data[data.length - 1]
const endTime = new Date(lastItem.time)
const endTimestamp = endTime.getTime()
// 4. 预处理:按时间排序(防止原始数据乱序)
const sortedData = [...data].sort((a, b) => new Date(a.time) - new Date(b.time))
// 5. 初始化状态继承第一个数据的type
let currentType = firstItem.type
let currentDesc = firstItem.description
let nextStatusIndex = 1 // 指向待切换的下一个状态点
const filledData = []
// 6. 核心循环从第一个time开始按间隔补全到最后一个time
for (let ts = startTimestamp; ts <= endTimestamp; ts += interval * 1000) {
const currentDate = new Date(ts)
// 格式化时间为和原始数据一致的 "YYYY-MM-DD HH:mm:ss" 格式
const formattedTime = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(
2,
'0'
)}-${String(currentDate.getDate()).padStart(2, '0')} ${String(currentDate.getHours()).padStart(
2,
'0'
)}:${String(currentDate.getMinutes()).padStart(2, '0')}:${String(currentDate.getSeconds()).padStart(2, '0')}`
// 7. 检查是否到达下一个状态切换点
if (nextStatusIndex < sortedData.length) {
const nextStatusTime = new Date(sortedData[nextStatusIndex].time).getTime()
if (ts >= nextStatusTime) {
currentType = sortedData[nextStatusIndex].type
currentDesc = sortedData[nextStatusIndex].description
nextStatusIndex++
}
}
// 8. 生成补全数据项(结构与原始数据完全一致)
filledData.push({
time: formattedTime,
devId: firstItem.devId,
description: currentDesc,
type: currentType
})
}
return filledData
}
const init = () => {
options1.value = {
title: {
text: '运行状态'
},
legend: {
show: false
},
tooltip: {
formatter: function (params: any) {
var res = params[0].data[0] + '<br/>运行状态:'
var texts = ''
if (params[0].data[1] === 1 || params[0].data[1] === '1') {
texts = '中断'
} else if (params[0].data[1] === 10 || params[0].data[1] === '10') {
texts = '正常'
}
res = res + texts
return res
}
},
xAxis: {
// type: 'category',
// data: data.updateTime
type: 'time',
name: '时间',
//
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
},
yAxis: {
name: '',
type: 'value',
max: 11,
interval: 1,
splitLine: {
lineStyle: {
// 使用深浅的间隔色
color: ['#ccc'],
type: 'dashed',
opacity: 0
}
},
axisLabel: {
// 这里重新定义就可以
formatter: function (value: number) {
var texts = []
if (value === 1) {
texts.push('中断')
} else if (value === 10) {
texts.push('正常')
}
return texts
}
}
},
series: [
{
name: '运行状态',
data: list.value.map((item: any, index: number) => [item.time, item.type == 0 ? 1 : 10]),
type: 'line',
showSymbol: false,
step: 'end'
}
]
}
}
defineExpose({
setData
})
</script>
<style lang="scss" scoped></style>

View File

@@ -1,399 +1,399 @@
<template>
<div>
<div :style="{ width: menuCollapse ? '40px' : '280px' }" style=" overflow: hidden; height: 100%">
<Icon v-show="menuCollapse" @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 mt20 menu-collapse"
style="cursor: pointer" />
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1, display: menuCollapse ? 'none' : '' }">
<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>
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span>新增方案</span>
</template>
<Icon name="el-icon-Plus" size="18" class="fold ml10 menu-collapse" style="cursor: pointer"
@click="onAdd" />
</el-tooltip>
<Icon @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 menu-collapse"
style="cursor: pointer" />
</div>
<el-tree style="flex: 1; overflow: auto" :props="defaultProps" highlight-current
:filter-node-method="filterNode" node-key="id" v-bind="$attrs" default-expand-all :data="tree"
ref="treRef" @node-click="clickNode" :expand-on-click-node="false">
<template #default="{ node, data }">
<span class="custom-tree-node">
<div class="left">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }"
v-if="data.icon" />
<span>{{ node.label }}</span>
</div>
<div class="right">
<a :style="{ marginRight: '0.5rem' }" v-if="data?.children">
<el-icon :style="{ color: '#0000FF' }">
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span>新增测试项</span>
</template>
<Plus @click.stop="add(node, data)" />
</el-tooltip>
</el-icon>
</a>
<a :style="{ marginRight: '0.5rem' }" v-else>
<el-icon :style="{ color: '#0000FF' }">
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span>数据绑定</span>
</template>
<SetUp @click.stop="bind(node, data)" />
</el-tooltip>
</el-icon>
</a>
<a :style="{ marginRight: '0.5rem' }">
<el-icon :style="{ color: '#0000FF' }">
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span> {{ data.pid ? '修改测试项' : ' 修改测试方案' }}</span>
</template>
<Edit @click.stop="edit(node, data)" />
</el-tooltip>
</el-icon>
</a>
<a :style="{ marginRight: '0.5rem' }">
<el-icon :style="{ color: '#DA3434' }">
<Delete @click.stop="del(node, data)" />
</el-icon>
</a>
</div>
</span>
</template>
</el-tree>
</div>
</div>
<popup ref="dialogRef" @onSubmit="getTreeList"></popup>
</div>
</template>
<script lang="ts" setup>
import { ref, nextTick, watch, defineProps, defineEmits } from 'vue'
import { getSchemeTree, getTestRecordInfo } from '@/api/cs-device-boot/planData'
import { useConfig } from '@/stores/config'
import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree } from 'element-plus'
import { Plus, Edit, Delete, SetUp } from '@element-plus/icons-vue'
import { delRecord } from '@/api/cs-device-boot/planData'
import popup from './popup.vue'
import { getDeviceList } from '@/api/cs-device-boot/planData'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'govern/schemeTree'
})
interface Props {
width?: string
canExpand?: boolean
}
const visible1 = ref(false)
const visible2 = ref(false)
const visible3 = ref(false)
const visible4 = ref(false)
const { proxy } = useCurrentInstance()
const menuCollapse = ref(false)
const filterText = ref('')
const treeRef = ref<InstanceType<typeof ElTree>>()
watch(filterText, val => {
treRef.value!.filter(val)
})
const onMenuCollapse = () => {
menuCollapse.value = !menuCollapse.value
proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
}
const filterNode = (value: string, data: any, node: any) => {
if (!value) return true
// return data.name.includes(value)
if (data.name) {
return chooseNode(value, data, node)
}
}
const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤
if (parentData.data.name.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
}
// 新增方案
const onAdd = () => {
emit('onAdd')
}
// 绑定数据
const bind = (node: any, data: any) => {
emit('bind', data)
}
/** 树形结构数据 */
const defaultProps = {
children: 'children',
label: 'name',
value: 'id'
}
const props = withDefaults(
defineProps<{
showCheckbox?: boolean
defaultCheckedKeys?: any
}>(),
{
showCheckbox: false,
defaultCheckedKeys: []
}
)
const emit = defineEmits(['init', 'checkChange', 'nodeChange', 'editNode', 'getChart', 'onAdd', 'bind'])
const config = useConfig()
const tree = ref()
const treRef = ref()
const id: any = ref(null)
const treeData = ref({})
//获取方案树形数据
const getTreeList = () => {
getSchemeTree().then(res => {
let arr: any[] = []
res.data.forEach((item: any) => {
item.icon = 'el-icon-Menu'
item.color = config.getColorVal('elementUiPrimary')
item?.children.forEach((item2: any) => {
item2.icon = 'el-icon-Document'
item2.color = config.getColorVal('elementUiPrimary')
arr.push(item2)
})
})
tree.value = res.data
nextTick(() => {
if (arr.length) {
treRef.value.setCurrentKey(id.value || arr[0].id)
let list = id.value ? arr.find((item: any) => item.id == id.value) : arr[0]
// 注册父组件事件
emit('init', {
level: 2,
...list
})
} else {
emit('init')
}
})
})
}
getTreeList()
const dialogRef = ref()
const handleOpen = (val: any, id: any) => {
dialogRef.value.open(val, id)
}
//方案id
const planId: any = ref('')
//测试项id
const monitorId: any = ref('')
const planData: any = ref({})
const getPlanData = (row: any) => {
planData.value = {}
planData.value = JSON.parse(JSON.stringify(row))
}
/** 添加树节点 */
// 0 新增方案 1 修改方案 2 新增测试项 3 修改测试项 4 设备信息
const add = (node: any, data: any) => {
planId.value = data.id
//添加测试项
if (data?.children) {
dialogRef.value.detailsType('tree')
handleOpen(2, planId.value)
}
}
/** 编辑树节点 */
const edit = async (node: Node, data: any) => {
planId.value = data.id
await getTestRecordInfo(planId.value)
.then(res => {
//修改方案
if (data?.children) {
dialogRef.value.detailsType('')
dialogRef.value.details(res.data)
handleOpen(1, planId.value)
}
//修改测试项
else {
monitorId.value = data.id
dialogRef.value.detailsType('tree')
dialogRef.value.details(res.data.records[0])
handleOpen(3, planId.value)
}
})
.catch(e => { })
}
/** 删除树节点 */
const del = async (node: Node, data: any) => {
let titleList = ''
planId.value = data.id
await getDeviceList({
id: data.id,
isTrueFlag: 1
}).then(res => {
if (res.data.length > 0) {
titleList = '已绑定数据_'
}
})
//删除方案/测试项
ElMessageBox.confirm(titleList + '是否确认删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
delRecord({ id: data.id }).then((res: any) => {
if (res.code == 'A0000') {
ElMessage.success('删除成功')
id.value = null
getTreeList()
}
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消'
})
})
}
//取消删除
const cancelDel = () => { }
const clickNode = (e: anyObj) => {
e?.children ? (planId.value = e.id) : (planId.value = e.pid)
id.value = e.id
emit('nodeChange', e)
}
const setCheckedNode = (e: anyObj) => {
// console.log('🚀 ~ setCheckedNode ~ e:', e)
id.value = e
treRef.value.setCurrentKey(e)
}
watch(
() => planData.value,
(val, oldVal) => {
if (val && dialogRef.value) {
const obj = JSON.parse(JSON.stringify(val))
obj.records = [
val.records.find(item => {
return item.id == monitorId.value
})
]
dialogRef.value.details(obj)
}
},
{
immediate: true,
deep: true
}
)
defineExpose({ treeRef, getPlanData, getTreeList, setCheckedNode })
</script>
<style lang="scss" scoped>
.cn-tree {
flex-shrink: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
height: 100%;
width: 100%;
: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);
}
.menu-collapse {
color: var(--el-color-primary);
}
}
.ml10 {
margin-bottom: 0 !important;
}
.add_plan {
width: 100%;
height: 40px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.custom-tree-node {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.left,
.right {
display: flex;
align-items: center;
}
.left {
span {
margin-left: 2px;
}
}
.right {
a {
margin-left: 2px;
}
}
}
</style>
<template>
<div>
<div :style="{ width: menuCollapse ? '40px' : '280px' }" style=" overflow: hidden; height: 100%">
<Icon v-show="menuCollapse" @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 mt20 menu-collapse"
style="cursor: pointer" />
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1, display: menuCollapse ? 'none' : '' }">
<div style="display: flex; align-items: center" class="mb10">
<el-input maxlength="32" v-model.trim="filterText" placeholder="请输入内容" clearable>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span>新增方案</span>
</template>
<Icon name="el-icon-Plus" size="18" class="fold ml10 menu-collapse" style="cursor: pointer"
@click="onAdd" />
</el-tooltip>
<Icon @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 menu-collapse"
style="cursor: pointer" />
</div>
<el-tree style="flex: 1; overflow: auto" :props="defaultProps" highlight-current
:filter-node-method="filterNode" node-key="id" v-bind="$attrs" default-expand-all :data="tree"
ref="treRef" @node-click="clickNode" :expand-on-click-node="false">
<template #default="{ node, data }">
<span class="custom-tree-node">
<div class="left">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }"
v-if="data.icon" />
<span>{{ node.label }}</span>
</div>
<div class="right">
<a :style="{ marginRight: '0.5rem' }" v-if="data?.children">
<el-icon :style="{ color: '#0000FF' }">
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span>新增测试项</span>
</template>
<Plus @click.stop="add(node, data)" />
</el-tooltip>
</el-icon>
</a>
<a :style="{ marginRight: '0.5rem' }" v-else>
<el-icon :style="{ color: '#0000FF' }">
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span>数据绑定</span>
</template>
<SetUp @click.stop="bind(node, data)" />
</el-tooltip>
</el-icon>
</a>
<a :style="{ marginRight: '0.5rem' }">
<el-icon :style="{ color: '#0000FF' }">
<el-tooltip placement="bottom" :hide-after="0">
<template #content>
<span> {{ data.pid ? '修改测试项' : ' 修改测试方案' }}</span>
</template>
<Edit @click.stop="edit(node, data)" />
</el-tooltip>
</el-icon>
</a>
<a :style="{ marginRight: '0.5rem' }">
<el-icon :style="{ color: '#DA3434' }">
<Delete @click.stop="del(node, data)" />
</el-icon>
</a>
</div>
</span>
</template>
</el-tree>
</div>
</div>
<popup ref="dialogRef" @onSubmit="getTreeList"></popup>
</div>
</template>
<script lang="ts" setup>
import { ref, nextTick, watch, defineProps, defineEmits } from 'vue'
import { getSchemeTree, getTestRecordInfo } from '@/api/cs-device-boot/planData'
import { useConfig } from '@/stores/config'
import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree } from 'element-plus'
import { Plus, Edit, Delete, SetUp } from '@element-plus/icons-vue'
import { delRecord } from '@/api/cs-device-boot/planData'
import popup from './popup.vue'
import { getDeviceList } from '@/api/cs-device-boot/planData'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'govern/schemeTree'
})
interface Props {
width?: string
canExpand?: boolean
}
const visible1 = ref(false)
const visible2 = ref(false)
const visible3 = ref(false)
const visible4 = ref(false)
const { proxy } = useCurrentInstance()
const menuCollapse = ref(false)
const filterText = ref('')
const treeRef = ref<InstanceType<typeof ElTree>>()
watch(filterText, val => {
treRef.value!.filter(val)
})
const onMenuCollapse = () => {
menuCollapse.value = !menuCollapse.value
proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
}
const filterNode = (value: string, data: any, node: any) => {
if (!value) return true
// return data.name.includes(value)
if (data.name) {
return chooseNode(value, data, node)
}
}
const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤
if (parentData.data.name.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
}
// 新增方案
const onAdd = () => {
emit('onAdd')
}
// 绑定数据
const bind = (node: any, data: any) => {
emit('bind', data)
}
/** 树形结构数据 */
const defaultProps = {
children: 'children',
label: 'name',
value: 'id'
}
const props = withDefaults(
defineProps<{
showCheckbox?: boolean
defaultCheckedKeys?: any
}>(),
{
showCheckbox: false,
defaultCheckedKeys: []
}
)
const emit = defineEmits(['init', 'checkChange', 'nodeChange', 'editNode', 'getChart', 'onAdd', 'bind'])
const config = useConfig()
const tree = ref()
const treRef = ref()
const id: any = ref(null)
const treeData = ref({})
//获取方案树形数据
const getTreeList = () => {
getSchemeTree().then(res => {
let arr: any[] = []
res.data.forEach((item: any) => {
item.icon = 'el-icon-Menu'
item.color = config.getColorVal('elementUiPrimary')
item?.children.forEach((item2: any) => {
item2.icon = 'el-icon-Document'
item2.color = config.getColorVal('elementUiPrimary')
arr.push(item2)
})
})
tree.value = res.data
nextTick(() => {
if (arr.length) {
treRef.value.setCurrentKey(id.value || arr[0].id)
let list = id.value ? arr.find((item: any) => item.id == id.value) : arr[0]
// 注册父组件事件
emit('init', {
level: 2,
...list
})
} else {
emit('init')
}
})
})
}
getTreeList()
const dialogRef = ref()
const handleOpen = (val: any, id: any) => {
dialogRef.value.open(val, id)
}
//方案id
const planId: any = ref('')
//测试项id
const monitorId: any = ref('')
const planData: any = ref({})
const getPlanData = (row: any) => {
planData.value = {}
planData.value = JSON.parse(JSON.stringify(row))
}
/** 添加树节点 */
// 0 新增方案 1 修改方案 2 新增测试项 3 修改测试项 4 设备信息
const add = (node: any, data: any) => {
planId.value = data.id
//添加测试项
if (data?.children) {
dialogRef.value.detailsType('tree')
handleOpen(2, planId.value)
}
}
/** 编辑树节点 */
const edit = async (node: Node, data: any) => {
planId.value = data.id
await getTestRecordInfo(planId.value)
.then(res => {
//修改方案
if (data?.children) {
dialogRef.value.detailsType('')
dialogRef.value.details(res.data)
handleOpen(1, planId.value)
}
//修改测试项
else {
monitorId.value = data.id
dialogRef.value.detailsType('tree')
dialogRef.value.details(res.data.records[0])
handleOpen(3, planId.value)
}
})
.catch(e => { })
}
/** 删除树节点 */
const del = async (node: Node, data: any) => {
let titleList = ''
planId.value = data.id
await getDeviceList({
id: data.id,
isTrueFlag: 1
}).then(res => {
if (res.data.length > 0) {
titleList = '已绑定数据_'
}
})
//删除方案/测试项
ElMessageBox.confirm(titleList + '是否确认删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
delRecord({ id: data.id }).then((res: any) => {
if (res.code == 'A0000') {
ElMessage.success('删除成功')
id.value = null
getTreeList()
}
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消'
})
})
}
//取消删除
const cancelDel = () => { }
const clickNode = (e: anyObj) => {
e?.children ? (planId.value = e.id) : (planId.value = e.pid)
id.value = e.id
emit('nodeChange', e)
}
const setCheckedNode = (e: anyObj) => {
// console.log('🚀 ~ setCheckedNode ~ e:', e)
id.value = e
treRef.value.setCurrentKey(e)
}
watch(
() => planData.value,
(val, oldVal) => {
if (val && dialogRef.value) {
const obj = JSON.parse(JSON.stringify(val))
obj.records = [
val.records.find(item => {
return item.id == monitorId.value
})
]
dialogRef.value.details(obj)
}
},
{
immediate: true,
deep: true
}
)
defineExpose({ treeRef, getPlanData, getTreeList, setCheckedNode })
</script>
<style lang="scss" scoped>
.cn-tree {
flex-shrink: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
height: 100%;
width: 100%;
: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);
}
.menu-collapse {
color: var(--el-color-primary);
}
}
.ml10 {
margin-bottom: 0 !important;
}
.add_plan {
width: 100%;
height: 40px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.custom-tree-node {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.left,
.right {
display: flex;
align-items: center;
}
.left {
span {
margin-left: 2px;
}
}
.right {
a {
margin-left: 2px;
}
}
}
</style>

View File

@@ -1,469 +1,469 @@
<template>
<div class="flex" style="margin: 15px 0">
<span style="width: 100px; margin-top: 3px">电压等级:</span>
<el-checkbox :indeterminate="isIndeterminate" v-model.trim="checkAll" @change="handleCheckAllChange"
style="margin-right: 28px">
全选
</el-checkbox>
<el-checkbox-group v-model.trim="checkedVoltage" @change="handleCheckedVoltageChange"
style="height: 72px; overflow-y: auto">
<el-checkbox v-for="(item, index) in grade" :label="item" :key="index">{{ item.name }}</el-checkbox>
</el-checkbox-group>
</div>
<div class="flex" style="margin: 15px 0">
<span style="width: 100px; margin-top: 3px">干扰源类型:</span>
<el-checkbox :indeterminate="isIndeterminate1" v-model.trim="checkAll1" @change="handleCheckAllChange1"
style="margin-right: 28px">
全选
</el-checkbox>
<el-checkbox-group v-model.trim="checkedSource" @change="handleCheckedSourceChange"
style="height: 72px; overflow-y: auto">
<el-checkbox v-for="(item, index) in type" :label="item" :key="index">{{ item.name }}</el-checkbox>
</el-checkbox-group>
</div>
<div class="flex" style="margin: 15px 0">
<span style="width: 100px; line-height: 32px">兼容曲线:</span>
<el-radio-group v-model.trim="radio" @change="radioChange">
<el-radio label="ITIC">ITIC</el-radio>
<el-radio label="F47">F47</el-radio>
</el-radio-group>
</div>
<my-echart class="bars_w" :options="echartList" />
<vxe-table class="dw" :data="TableData" height="50px" v-bind="defaultAttribute">
<vxe-column field="name" title="名称" width="100px"></vxe-column>
<vxe-column field="totalEvents" title="事件总数" width="100px"></vxe-column>
<vxe-column field="tolerable" title="可容忍" width="100px"></vxe-column>
<vxe-column field="Intolerable" title="不可容忍" width="100px"></vxe-column>
</vxe-table>
</template>
<script setup lang="ts">
import { useDictData } from '@/stores/dictData'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { mainHeight } from '@/utils/layout'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ref, reactive } from 'vue'
const dictData = useDictData()
const isIndeterminate = ref(false)
const isIndeterminate1 = ref(false)
const checkAll = ref(true)
const checkAll1 = ref(true)
const radio = ref('ITIC')
const echartList = ref({})
const ITIC = ref({})
const F47 = ref({})
const pointI: any = ref([])
const pointIun: any = ref([])
const pointF: any = ref([])
const pointFun: any = ref([])
const datalist: any = ref([])
const TableData = ref([
{
name: '事件个数',
totalEvents: '',
tolerable: '',
Intolerable: ''
}
])
const checkedVoltage: any = ref(ref(dictData.getBasicData('Dev_Voltage_Stand')))
const checkedSource: any = ref(dictData.getBasicData('Interference_Source'))
const grade = ref(dictData.getBasicData('Dev_Voltage_Stand'))
const type = ref(dictData.getBasicData('Interference_Source'))
// 电压等级多选
const handleCheckedVoltageChange = (val: any) => {
const checkedCount = val.length
checkAll.value = checkedCount === grade.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < grade.value.length
}
const handleCheckAllChange = (val: any) => {
checkedVoltage.value = val ? grade.value : []
isIndeterminate.value = false
}
// 干扰源类型多选
const handleCheckAllChange1 = (val: any) => {
checkedSource.value = val ? type.value : []
isIndeterminate.value = false
}
const handleCheckedSourceChange = (val: any) => {
const checkedCount = val.length
checkAll1.value = checkedCount === type.value.length
isIndeterminate1.value = checkedCount > 0 && checkedCount < type.value.length
}
const info = async (list: any) => {
datalist.value = []
list.forEach((item: any) => {
if (item.eventValue < 2 && item.eventValue > 0) {
datalist.value.push(item)
}
})
await gongfunction()
ITIC.value = {
title: {
text: 'ITIC曲线'
},
tooltip: {
formatter: function (a: any) {
if (a[0].value[4] == undefined) {
return
}
let relVal = ''
relVal = "<font style='color:" + "'>供电公司:" + '&nbsp' + '&nbsp' + a[0].value[3] + '</font><br/>'
relVal += "<font style='color:" + "'>变电站:" + '&nbsp' + '&nbsp' + a[0].value[4] + '</font><br/>'
relVal += "<font style='color:" + "'>发生时刻:" + '&nbsp' + '&nbsp' + a[0].value[2] + '</font><br/>'
relVal +=
"<font style='color:" +
"'>持续时间:" +
'&nbsp' +
'&nbsp' +
a[0].value[0].toFixed(3) +
's</font><br/>'
relVal +=
"<font style='color:" + "'>特征幅值:" + '&nbsp' + '&nbsp' + a[0].value[1].toFixed(3) + '%</font>'
return relVal
}
},
legend: {
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
// selectedMode: false,
left: '10px'
},
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
xAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
splitLine: { show: false }
},
yAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
name: '%'
},
dataZoom: {
type: null,
show: false
},
options: {
series: [
{
name: '上限',
type: 'line',
data: [
[0.001, 200],
[0.003, 140],
[0.003, 120],
[0.5, 120],
[0.5, 110],
[10, 110],
[1000, 110]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '下限',
type: 'line',
data: [
[0.02, 0],
[0.02, 70],
[0.5, 70],
[0.5, 80],
[10, 80],
[10, 90],
[1000, 90]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointI.value
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointIun.value
}
]
}
}
F47.value = {
title: {
text: 'F47曲线'
},
tooltip: {
formatter: function (a: any) {
if (a[0].value[4] == undefined) {
return
}
let relVal = ''
relVal = "<font style='color:" + "'>供电公司:" + '&nbsp' + '&nbsp' + a[0].value[3] + '</font><br/>'
relVal += "<font style='color:" + "'>变电站:" + '&nbsp' + '&nbsp' + a[0].value[4] + '</font><br/>'
relVal += "<font style='color:" + "'>发生时刻:" + '&nbsp' + '&nbsp' + a[0].value[2] + '</font><br/>'
relVal +=
"<font style='color:" +
"'>持续时间:" +
'&nbsp' +
'&nbsp' +
a[0].value[0].toFixed(3) +
's</font><br/>'
relVal +=
"<font style='color:" + "'>特征幅值:" + '&nbsp' + '&nbsp' + a[0].value[1].toFixed(3) + '%</font>'
return relVal
}
},
legend: {
data: ['分割线', '可容忍事件', '不可容忍事件'],
// selectedMode: false,
left: '10px'
},
color: ['yellow', 'green', 'red'],
xAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
splitLine: { show: false }
},
yAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
name: '%'
},
dataZoom: {
type: null,
show: false
},
options: {
series: [
{
name: '分割线',
type: 'line',
data: [
[0.05, 0],
[0.05, 50],
[0.2, 50],
[0.2, 70],
[0.5, 70],
[0.5, 80],
[10, 80],
[1000, 80]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointF.value
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointFun.value
}
]
}
}
radioChange(radio.value)
}
const radioChange = (e: any) => {
if (e == 'ITIC') {
echartList.value = ITIC.value
TableData.value[0].totalEvents = pointI.value.length + pointIun.value.length
TableData.value[0].tolerable = pointI.value.length
TableData.value[0].Intolerable = pointIun.value.length
} else if (e == 'F47') {
echartList.value = F47.value
TableData.value[0].totalEvents = pointF.value.length + pointFun.value.length
TableData.value[0].tolerable = pointF.value.length
TableData.value[0].Intolerable = pointFun.value.length
}
}
const gongfunction = () => {
var standI = 0
var unstandI = 0
var standF = 0
var unstandF = 0
pointI.value = []
pointIun.value = []
pointF.value = []
pointFun.value = []
var total = 0
total = datalist.value.length
if (total == 0) {
} else {
for (var i = 0; i < datalist.value.length; i++) {
var point = []
var xx = datalist.value[i].persistTime
var yy = datalist.value[i].eventValue * 100
var time = datalist.value[i].time.replace('T', ' ')
var company = datalist.value[i].gdName
var substation = datalist.value[i].subName
var index = datalist.value[i].lineId
var eventId = datalist.value[i].eventId
point = [xx, yy, time, company, substation, index, eventId]
if (xx <= 0.003) {
var line = 0
line = 230 - 30000 * xx
if (yy > line) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else if (xx <= 0.02) {
if (yy > 120) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else if (xx <= 0.5) {
if (yy > 120 || yy < 70) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else if (xx <= 10) {
if (yy > 110 || yy < 80) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else {
if (yy > 110 || yy < 90) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
}
if (xx < 0.05) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else if (xx < 0.2) {
if (yy > 50) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else {
unstandF++
pointFun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
}
} else if (xx < 0.5) {
if (yy > 70) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else {
unstandF++
pointFun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
}
} else {
if (yy > 80) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else {
unstandF++
pointFun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
}
}
}
}
}
defineExpose({ checkedVoltage, checkedSource, info })
const layout = mainHeight(390) as any
</script>
<style lang="scss" scoped>
.flex {
display: flex;
}
.bars_w {
height: calc(v-bind('layout.height'));
}
.dw {
position: absolute;
top: 210px;
right: 70px;
}
</style>
<template>
<div class="flex" style="margin: 15px 0">
<span style="width: 100px; margin-top: 3px">电压等级:</span>
<el-checkbox :indeterminate="isIndeterminate" v-model.trim="checkAll" @change="handleCheckAllChange"
style="margin-right: 28px">
全选
</el-checkbox>
<el-checkbox-group v-model.trim="checkedVoltage" @change="handleCheckedVoltageChange"
style="height: 72px; overflow-y: auto">
<el-checkbox v-for="(item, index) in grade" :label="item" :key="index">{{ item.name }}</el-checkbox>
</el-checkbox-group>
</div>
<div class="flex" style="margin: 15px 0">
<span style="width: 100px; margin-top: 3px">干扰源类型:</span>
<el-checkbox :indeterminate="isIndeterminate1" v-model.trim="checkAll1" @change="handleCheckAllChange1"
style="margin-right: 28px">
全选
</el-checkbox>
<el-checkbox-group v-model.trim="checkedSource" @change="handleCheckedSourceChange"
style="height: 72px; overflow-y: auto">
<el-checkbox v-for="(item, index) in type" :label="item" :key="index">{{ item.name }}</el-checkbox>
</el-checkbox-group>
</div>
<div class="flex" style="margin: 15px 0">
<span style="width: 100px; line-height: 32px">兼容曲线:</span>
<el-radio-group v-model.trim="radio" @change="radioChange">
<el-radio label="ITIC">ITIC</el-radio>
<el-radio label="F47">F47</el-radio>
</el-radio-group>
</div>
<my-echart class="bars_w" :options="echartList" />
<vxe-table class="dw" :data="TableData" height="50px" v-bind="defaultAttribute">
<vxe-column field="name" title="名称" width="100px"></vxe-column>
<vxe-column field="totalEvents" title="事件总数" width="100px"></vxe-column>
<vxe-column field="tolerable" title="可容忍" width="100px"></vxe-column>
<vxe-column field="Intolerable" title="不可容忍" width="100px"></vxe-column>
</vxe-table>
</template>
<script setup lang="ts">
import { useDictData } from '@/stores/dictData'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { mainHeight } from '@/utils/layout'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ref, reactive } from 'vue'
const dictData = useDictData()
const isIndeterminate = ref(false)
const isIndeterminate1 = ref(false)
const checkAll = ref(true)
const checkAll1 = ref(true)
const radio = ref('ITIC')
const echartList = ref({})
const ITIC = ref({})
const F47 = ref({})
const pointI: any = ref([])
const pointIun: any = ref([])
const pointF: any = ref([])
const pointFun: any = ref([])
const datalist: any = ref([])
const TableData = ref([
{
name: '事件个数',
totalEvents: '',
tolerable: '',
Intolerable: ''
}
])
const checkedVoltage: any = ref(ref(dictData.getBasicData('Dev_Voltage_Stand')))
const checkedSource: any = ref(dictData.getBasicData('Interference_Source'))
const grade = ref(dictData.getBasicData('Dev_Voltage_Stand'))
const type = ref(dictData.getBasicData('Interference_Source'))
// 电压等级多选
const handleCheckedVoltageChange = (val: any) => {
const checkedCount = val.length
checkAll.value = checkedCount === grade.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < grade.value.length
}
const handleCheckAllChange = (val: any) => {
checkedVoltage.value = val ? grade.value : []
isIndeterminate.value = false
}
// 干扰源类型多选
const handleCheckAllChange1 = (val: any) => {
checkedSource.value = val ? type.value : []
isIndeterminate.value = false
}
const handleCheckedSourceChange = (val: any) => {
const checkedCount = val.length
checkAll1.value = checkedCount === type.value.length
isIndeterminate1.value = checkedCount > 0 && checkedCount < type.value.length
}
const info = async (list: any) => {
datalist.value = []
list.forEach((item: any) => {
if (item.eventValue < 2 && item.eventValue > 0) {
datalist.value.push(item)
}
})
await gongfunction()
ITIC.value = {
title: {
text: 'ITIC曲线'
},
tooltip: {
formatter: function (a: any) {
if (a[0].value[4] == undefined) {
return
}
var relVal = `<strong>${a.seriesName}</strong><br/>`
relVal += "<font style='color:" + "'>供电公司:" + '&nbsp' + '&nbsp' + a[0].value[3] + '</font><br/>'
relVal += "<font style='color:" + "'>变电站:" + '&nbsp' + '&nbsp' + a[0].value[4] + '</font><br/>'
relVal += "<font style='color:" + "'>发生时刻:" + '&nbsp' + '&nbsp' + a[0].value[2] + '</font><br/>'
relVal +=
"<font style='color:" +
"'>持续时间:" +
'&nbsp' +
'&nbsp' +
a[0].value[0].toFixed(3) +
's</font><br/>'
relVal +=
"<font style='color:" + "'>特征幅值:" + '&nbsp' + '&nbsp' + a[0].value[1].toFixed(3) + '%</font>'
return relVal
}
},
legend: {
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
// selectedMode: false,
left: '10px'
},
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
xAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
splitLine: { show: false }
},
yAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
name: '%'
},
dataZoom: {
type: null,
show: false
},
options: {
series: [
{
name: '上限',
type: 'line',
data: [
[0.001, 200],
[0.003, 140],
[0.003, 120],
[0.5, 120],
[0.5, 110],
[10, 110],
[1000, 110]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '下限',
type: 'line',
data: [
[0.02, 0],
[0.02, 70],
[0.5, 70],
[0.5, 80],
[10, 80],
[10, 90],
[1000, 90]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointI.value
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointIun.value
}
]
}
}
F47.value = {
title: {
text: 'F47曲线'
},
tooltip: {
formatter: function (a: any) {
if (a[0].value[4] == undefined) {
return
}
let relVal = ''
relVal = "<font style='color:" + "'>供电公司:" + '&nbsp' + '&nbsp' + a[0].value[3] + '</font><br/>'
relVal += "<font style='color:" + "'>变电站:" + '&nbsp' + '&nbsp' + a[0].value[4] + '</font><br/>'
relVal += "<font style='color:" + "'>发生时刻:" + '&nbsp' + '&nbsp' + a[0].value[2] + '</font><br/>'
relVal +=
"<font style='color:" +
"'>持续时间:" +
'&nbsp' +
'&nbsp' +
a[0].value[0].toFixed(3) +
's</font><br/>'
relVal +=
"<font style='color:" + "'>特征幅值:" + '&nbsp' + '&nbsp' + a[0].value[1].toFixed(3) + '%</font>'
return relVal
}
},
legend: {
data: ['分割线', '可容忍事件', '不可容忍事件'],
// selectedMode: false,
left: '10px'
},
color: ['yellow', 'green', 'red'],
xAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
splitLine: { show: false }
},
yAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
name: '%'
},
dataZoom: {
type: null,
show: false
},
options: {
series: [
{
name: '分割线',
type: 'line',
data: [
[0.05, 0],
[0.05, 50],
[0.2, 50],
[0.2, 70],
[0.5, 70],
[0.5, 80],
[10, 80],
[1000, 80]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointF.value
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
data: pointFun.value
}
]
}
}
radioChange(radio.value)
}
const radioChange = (e: any) => {
if (e == 'ITIC') {
echartList.value = ITIC.value
TableData.value[0].totalEvents = pointI.value.length + pointIun.value.length
TableData.value[0].tolerable = pointI.value.length
TableData.value[0].Intolerable = pointIun.value.length
} else if (e == 'F47') {
echartList.value = F47.value
TableData.value[0].totalEvents = pointF.value.length + pointFun.value.length
TableData.value[0].tolerable = pointF.value.length
TableData.value[0].Intolerable = pointFun.value.length
}
}
const gongfunction = () => {
var standI = 0
var unstandI = 0
var standF = 0
var unstandF = 0
pointI.value = []
pointIun.value = []
pointF.value = []
pointFun.value = []
var total = 0
total = datalist.value.length
if (total == 0) {
} else {
for (var i = 0; i < datalist.value.length; i++) {
var point = []
var xx = datalist.value[i].persistTime
var yy = datalist.value[i].eventValue * 100
var time = datalist.value[i].time.replace('T', ' ')
var company = datalist.value[i].gdName
var substation = datalist.value[i].subName
var index = datalist.value[i].lineId
var eventId = datalist.value[i].eventId
point = [xx, yy, time, company, substation, index, eventId]
if (xx <= 0.003) {
var line = 0
line = 230 - 30000 * xx
if (yy > line) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else if (xx <= 0.02) {
if (yy > 120) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else if (xx <= 0.5) {
if (yy > 120 || yy < 70) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else if (xx <= 10) {
if (yy > 110 || yy < 80) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
} else {
if (yy > 110 || yy < 90) {
unstandI++
pointIun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
} else {
standI++
pointI.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
}
}
if (xx < 0.05) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else if (xx < 0.2) {
if (yy > 50) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else {
unstandF++
pointFun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
}
} else if (xx < 0.5) {
if (yy > 70) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else {
unstandF++
pointFun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
}
} else {
if (yy > 80) {
standF++
pointF.value.push({
value: point,
itemStyle: { normal: { color: 'green' } }
})
} else {
unstandF++
pointFun.value.push({
value: point,
itemStyle: { normal: { color: 'red' } }
})
}
}
}
}
}
defineExpose({ checkedVoltage, checkedSource, info })
const layout = mainHeight(390) as any
</script>
<style lang="scss" scoped>
.flex {
display: flex;
}
.bars_w {
height: calc(v-bind('layout.height'));
}
.dw {
position: absolute;
top: 210px;
right: 70px;
}
</style>