修改测试问题

This commit is contained in:
guanj
2026-01-15 15:59:13 +08:00
parent 054d84778b
commit 5ceb9be9e2
20 changed files with 535 additions and 471 deletions

View File

@@ -1,7 +1,14 @@
<template>
<div>
<!--F47曲线 -->
<TableHeader ref="TableHeaderRef" :showReset="false" :timeKeyList="prop.timeKey" @selectChange="selectChange" datePicker v-if="fullscreen"></TableHeader>
<TableHeader
ref="TableHeaderRef"
:showReset="false"
:timeKeyList="prop.timeKey"
@selectChange="selectChange"
datePicker
v-if="fullscreen"
></TableHeader>
<el-descriptions class="mt2" direction="vertical" :column="4" border>
<el-descriptions-item align="center" label="名称">{{ data.name }}</el-descriptions-item>
<el-descriptions-item align="center" label="事件总数">{{ data.gs }}</el-descriptions-item>
@@ -44,7 +51,7 @@ const prop = defineProps({
h: { type: [String, Number] },
width: { type: [String, Number] },
height: { type: [String, Number] },
timeKey: { type: Array as () => string[] },
timeKey: { type: Array as () => string[] },
timeValue: { type: Object },
interval: { type: Number }
})
@@ -162,11 +169,16 @@ const tableStore: any = new TableStore({
yAxis: [
{
type: 'value',
max: function (value: any) {
return value.max + 20
// max: function (value: any) {
// return value.max + 20
// },
max: function (value) {
// 先取原始最大值+20再向上取整到最近的10的倍数确保刻度够用且规整
return Math.ceil((value.max + 20) / 10) * 10
},
splitNumber: 10,
minInterval: 0.1,
// splitNumber: 10,
// interval: 10,
// minInterval: 10,
name: '%'
}
],
@@ -449,7 +461,7 @@ const handleTolerableEventClick = async (row: any) => {
// waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
}
})
const messageInstance = ElMessage.info(`正在加载,请稍等...`)
const messageInstance = ElMessage.info(`正在加载,请稍等...`)
await analyseWave(row.value[3]) //eventId
.then(res => {
row.loading1 = false
@@ -474,7 +486,7 @@ const handleTolerableEventClick = async (row: any) => {
})
nextTick(() => {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(999, 130, 1.6666666)
waveFormAnalysisRef.value && waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
})
}

View File

@@ -66,7 +66,7 @@
<el-option
v-for="vv in item.countOptions"
:key="vv"
:label="vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:value="vv"
></el-option>
</el-select>

View File

@@ -12,7 +12,7 @@
multiple
:multiple-limit="2"
collapse-tags
collapse-tags-tooltip
collapse-tags-tooltip
v-model="searchForm.index"
placeholder="请选择统计指标"
@change="onIndexChange($event)"
@@ -66,7 +66,7 @@
<el-option
v-for="vv in item.countOptions"
:key="vv"
:label="vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:value="vv"
></el-option>
</el-select>

View File

@@ -66,7 +66,7 @@
<el-option
v-for="vv in item.countOptions"
:key="vv"
:label="vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:value="vv"
></el-option>
</el-select>

View File

@@ -214,8 +214,8 @@ onMounted(() => {
overflow-x: auto;
overflow-y: hidden;
margin-right: var(--ba-main-space);
scrollbar-width: none;
// scrollbar-width: none;
// overflow-x: auto;
&::-webkit-scrollbar {
height: 5px;
}

View File

@@ -1,47 +1,47 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import staticRoutes from '@/router/static'
import { useAdminInfo } from '@/stores/adminInfo'
import NProgress from 'nprogress'
import { loading } from '@/utils/loading'
import { ElMessage } from 'element-plus'
const router = createRouter({
history: createWebHashHistory(),
routes: staticRoutes
})
router.beforeEach((to, from, next) => {
NProgress.configure({ showSpinner: false })
NProgress.start()
if (!window.existLoading) {
loading.show()
window.existLoading = true
}
if (to.path == '/login' || to.path == '/404'|| to.path == '/policy'|| to.path == '/agreement') {
// 登录或者注册才可以往下进行
next()
} else {
// 获取 token
const adminInfo = useAdminInfo()
const token = adminInfo.getToken()
// token 不存在
if (token === null || token === '') {
ElMessage.error('您还没有登录,请先登录')
next('/login')
} else {
next()
}
}
// next()
})
// 路由加载后
router.afterEach(() => {
if (window.existLoading) {
loading.hide()
}
NProgress.done()
})
export default router
import { createRouter, createWebHashHistory } from 'vue-router'
import staticRoutes from '@/router/static'
import { useAdminInfo } from '@/stores/adminInfo'
import NProgress from 'nprogress'
import { loading } from '@/utils/loading'
import { ElMessage } from 'element-plus'
const router = createRouter({
history: createWebHashHistory(),
routes: staticRoutes
})
router.beforeEach((to, from, next) => {
NProgress.configure({ showSpinner: false })
NProgress.start()
if (!window.existLoading) {
loading.show()
window.existLoading = true
}
if (to.path == '/login' || to.path == '/404'|| to.path == '/policy'|| to.path == '/agreement') {
// 登录或者注册才可以往下进行
next()
} else {
// 获取 token
const adminInfo = useAdminInfo()
const token = adminInfo.getToken()
// token 不存在
if (token === null || token === '') {
// ElMessage.error('您还没有登录,请先登录')
next('/login')
} else {
next()
}
}
// next()
})
// 路由加载后
router.afterEach(() => {
if (window.existLoading) {
loading.hide()
}
NProgress.done()
})
export default router

View File

@@ -44,7 +44,8 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
}
if (base === 0.1) {
return parseFloat(calculatedValue.toFixed(1))
// return parseFloat(calculatedValue.toFixed(1))
return Math.ceil(calculatedValue * 10) / 10
} else if (isMin) {
return Math.floor(calculatedValue / base) * base
} else {

View File

@@ -1,5 +1,5 @@
<template>
<div ref="refheader" v-if="!isWaveCharts">
<div ref="refheader" v-show="!isWaveCharts" style="width: 100%;">
<TableHeader datePicker showExport>
<template v-slot:select>
<el-form-item label="数据来源">

View File

@@ -7,15 +7,15 @@
<el-tab-pane label="前置告警" name="2">
<Front v-if="activeName == '2'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="稳态越限告警" name="3">
<!-- <el-tab-pane label="稳态越限告警" name="3">
<Steady v-if="activeName == '3'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
</el-tab-pane> -->
<el-tab-pane label="暂态事件" name="4">
<Transient v-if="activeName == '4'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="异常事件" name="5">
<!-- <el-tab-pane label="异常事件" name="5">
<Abnormal v-if="activeName == '5'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
</el-tab-pane> -->
</el-tabs>
</div>
</template>
@@ -31,7 +31,7 @@ defineOptions({
name: 'govern/alarm/index'
})
const deviceTree = ref([])
const activeName = ref('1')
const activeName = ref('0')
const key = ref(0)
getDeviceTree().then(res => {
// res.data.forEach((item: any) => {
@@ -49,6 +49,7 @@ getDeviceTree().then(res => {
// })
deviceTree.value = res.data
key.value += 1
activeName.value = '1'
})
onMounted(() => { })

View File

@@ -14,7 +14,7 @@
v-model.trim="formInline.statisticalId"
filterable
@change="frequencyFlag"
placeholder="请选择"
placeholder="请选择"
>
<el-option
v-for="item in zblist"

View File

@@ -781,7 +781,7 @@
</el-form-item>
<el-form-item
class="form-item"
label="设备容量(MW):"
label="设备容量(MVA):"
:prop="'lineInfoList[' + lIndex + '].devCapacity'"
:rules="{ required: true, message: '请输入设备容量', trigger: 'blur' }"
>
@@ -803,7 +803,7 @@
</el-form-item>
<el-form-item
class="form-item"
label="协议容量(MW):"
label="协议容量(MVA):"
:prop="'lineInfoList[' + lIndex + '].protocolCapacity'"
:rules="{ required: true, message: '请输入协议容量', trigger: 'blur' }"
>
@@ -820,7 +820,7 @@
pageStatus == 2)
)
"
placeholder="请输入协议容量(MW)"
placeholder="请输入协议容量(MVA)"
></el-input>
</el-form-item>

View File

@@ -4,8 +4,8 @@
<div class="harmonic_select" v-if="!loading">
<el-form :model="searchForm" id="history_select">
<el-form-item label="稳态指标">
<el-select multiple collapse-tags collapse-tags-tooltip v-model.trim="searchForm.index"
placeholder="请选择统计指标" :multiple-limit="3" value-key="id">
<el-select multiple collapse-tags collapse-tags-tooltip filterable v-model.trim="searchForm.index"
placeholder="请选择统计指标" :multiple-limit="3" value-key="id">
<el-option v-for="(item, index) in indexOptions" :label="item.name" :key="index"
:value="item"></el-option>
</el-select>
@@ -347,7 +347,7 @@ const init = () => {
// }
// },
boundaryGap: false,
data: xAixsTimeList.value
// data: xAixsTimeList.value
},
yAxis: {
// type: 'value',

View File

@@ -1,7 +1,9 @@
<template>
<div class="view">
<TableHeader datePicker ref="headerRef" v-if="!isWaveCharts" :showReset="false"></TableHeader>
<Table ref="tableRef" v-if="!isWaveCharts" />
<div v-show="!isWaveCharts">
<TableHeader datePicker ref="headerRef" :showReset="false"></TableHeader>
<Table ref="tableRef" />
</div>
<waveFormAnalysis
v-loading="loading"
v-if="isWaveCharts"
@@ -62,8 +64,7 @@ const tableStore: any = new TableStore({
title: '相别',
minWidth: 80,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue : '/'
return row.cellValue
return row.cellValue || '/'
}
},
{
@@ -71,9 +72,9 @@ const tableStore: any = new TableStore({
title: '持续时间(s)',
minWidth: 110,
formatter: (row: any) => {
console.log('row.cellValue', row.cellValue)
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue
console.log('🚀 ~ row.cellValue:', row.cellValue)
return row.cellValue ? (row.cellValue - 0).toFixed(2) : '/'
},
sortable: true
},
@@ -91,10 +92,11 @@ const tableStore: any = new TableStore({
}
},
{
title: '操作', fixed: 'right',
title: '操作',
fixed: 'right',
width: 180,
render: 'buttons',
buttons: [
{
name: 'edit',
@@ -196,7 +198,6 @@ const tableStore: any = new TableStore({
tableStore.table.params.devId = tableParams.value.devId
tableStore.table.params.lineId = tableParams.value.lineId
tableStore.table.params.list = tableParams.value.list
console.log('🚀 ~ ableParams.value:', tableParams.value)
tableStore.table.params.type = 3
},
loadCallback: () => {}

View File

@@ -69,8 +69,8 @@
<br />
<vxe-table border height="" :data="realList" :column-config="{ resizable: true, tooltip: true }"
:tooltip-config="{ enterable: true }">
<vxe-column align="center" field="freqDev" width="140" title="频率(Hz)"></vxe-column>
<vxe-column align="center" field="freq" width="120" title="频率偏差(Hz)"></vxe-column>
<vxe-column align="center" field="freq" width="140" title="频率(Hz)"></vxe-column>
<vxe-column align="center" field="freqDev" width="120" title="频率偏差(Hz)"></vxe-column>
<vxe-column align="center" width="180" field="vUnbalance" title="电压不平衡度(%)"></vxe-column>
<vxe-column align="center" width="180" field="iUnbalance" title="电流不平衡度(%)"></vxe-column>
<vxe-colgroup align="center" :title="`基波电压幅值(${voltageUnit})`">
@@ -128,13 +128,13 @@
<vxe-column align="center" field="sC" title="C相"></vxe-column>
<vxe-column align="center" field="sTot" title="总"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="功率因数">
<vxe-colgroup align="center" title="视在功率因数">
<vxe-column align="center" field="pfA" title="A相"></vxe-column>
<vxe-column align="center" field="pfB" title="B相"></vxe-column>
<vxe-column align="center" field="pfC" title="C相"></vxe-column>
<vxe-column align="center" field="pfTot" title="总"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" title="基波功率因数">
<vxe-colgroup align="center" title="位移功率因数">
<vxe-column align="center" field="dpfA" title="A相"></vxe-column>
<vxe-column align="center" field="dpfB" title="B相"></vxe-column>
<vxe-column align="center" field="dpfC" title="C相"></vxe-column>

View File

@@ -12,6 +12,7 @@
multiple
:multiple-limit="3"
collapse-tags
filterable
collapse-tags-tooltip
v-model="searchForm.index"
placeholder="请选择统计指标"
@@ -67,7 +68,7 @@
<el-option
v-for="vv in item.countOptions"
:key="vv"
:label="vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:value="vv"
></el-option>
</el-select>
@@ -157,7 +158,13 @@ const countOptions: any = ref([])
// Harmonic_Type
// portable-harmonic
const legendDictList: any = ref([])
queryByCode(props?.TrendList?.lineType == 0 ? 'apf-harmonic' : 'portable-harmonic').then(res => {
queryByCode(
props?.TrendList?.lineType == 0
? 'apf-harmonic'
: props?.TrendList?.conType == 1
? 'portable-harmonic-jx'
: 'portable-harmonic'
).then(res => {
queryCsDictTree(res.data.id).then(item => {
//排序
indexOptions.value = item.data.sort((a: any, b: any) => {
@@ -185,15 +192,15 @@ queryByCode(props?.TrendList?.lineType == 0 ? 'apf-harmonic' : 'portable-harmoni
if (kk.harmStart && kk.harmEnd) {
range(0, 0, 0)
if (kk.showName == '间谐波电压含有率') {
countDataCopy.value[index].countOptions = range(kk.harmStart, kk.harmEnd, 1).map(
(item: any) => {
return item - 0.5
}
)
} else {
// if (kk.showName == '间谐波电压含有率') {
// countDataCopy.value[index].countOptions = range(kk.harmStart, kk.harmEnd, 1).map(
// (item: any) => {
// return item - 0.5
// }
// )
// } else {
countDataCopy.value[index].countOptions = range(kk.harmStart, kk.harmEnd, 1)
}
// }
if (!countDataCopy.value[index].count || countDataCopy.value[index].count.length == 0) {
countDataCopy.value[index].count = countDataCopy.value[index].countOptions[0]
}
@@ -232,7 +239,7 @@ const init = async () => {
loading.value = true
// 选择指标的时候切换legend内容和data数据
let list: any = []
echartsData.value={}
echartsData.value = {}
legendDictList.value?.selectedList?.map((item: any) => {
searchForm.value.index.map((vv: any) => {
if (item.dataType == vv) {
@@ -260,7 +267,7 @@ const init = async () => {
let frequencys: any = null
countData.value.map((item: any, index: any) => {
if (item.name.includes('间谐波电压')) {
frequencys = item.count + 0.5
frequencys = item.count //+ 0.5
} else {
frequencys = item.count
}

View File

@@ -1,315 +1,338 @@
<!-- 设备管理 -->
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
<div class="device-manage-right" v-if="deviceData">
<el-descriptions title="基础信息" class="mb10" :column="3" border>
<template #extra>
<!-- <el-button
type="primary"
icon="el-icon-Share"
@click="openGroup"
:loading="getGroupLoading"
>
模版数据分组
</el-button> -->
<el-button icon="el-icon-Refresh" v-if="showButtom" @click="handleRestartDevice" type="primary"
:loading="deviceRestartLoading">
装置重启
</el-button>
</template>
<el-descriptions-item label="名称">
{{ deviceData.name }}
</el-descriptions-item>
<el-descriptions-item label="类型">
{{ echoName(deviceData.devType, devTypeOptions) }}
</el-descriptions-item>
<el-descriptions-item label="接入方式">
{{ deviceData.devAccessMethod }}
</el-descriptions-item>
<el-descriptions-item label="网络设备ID">
{{ deviceData.ndid }}
</el-descriptions-item>
<el-descriptions-item label="型号">
{{ echoName(deviceData.devModel, devModelOptions) }}
</el-descriptions-item>
<el-descriptions-item label="首次接入日期">
{{ deviceData.time }}
</el-descriptions-item>
<el-descriptions-item label="应用程序版本号">
{{ deviceData.appVersion }}
</el-descriptions-item>
<el-descriptions-item label="应用程序发布日期">
{{ deviceData.appDate }}
</el-descriptions-item>
<el-descriptions-item label="应用程序校验码">
{{ deviceData.appCheck }}
</el-descriptions-item>
</el-descriptions>
<div style="position: relative">
<el-tabs v-model.trim="dataSet" type="border-card" class="device-manage-box-card"
@tab-click="handleClick">
<el-tab-pane lazy :label="item.name" :name="item.id" v-for="(item, index) in deviceData.dataSetList"
:key="index"></el-tab-pane>
<div :style="{ height: tableHeight }" v-loading="tableLoading">
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" ref="xTableRef"
style="width: 100%">
<vxe-column type="seq" title="序号" width="80"></vxe-column>
<vxe-column field="name" title="数据名称"></vxe-column>
<vxe-column field="phasic" title="相别"></vxe-column>
<vxe-column field="type" title="数据类型"></vxe-column>
<vxe-column field="unit" title="单位"></vxe-column>
<vxe-column field="startTimes" title="开始次数"></vxe-column>
<vxe-column field="endTimes" title="结束次数"></vxe-column>
</vxe-table>
</div>
</el-tabs>
<el-button icon="el-icon-Download" type="primary" @click="exportData" class="export-btn">导出</el-button>
</div>
</div>
<el-empty v-else description="请选择设备" class="device-manage-right" />
<MangePopup ref="mangePopup" />
</div>
</template>
<script setup lang="ts">
defineOptions({
name: 'govern/device/manage'
})
import MangePopup from './popup.vue'
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { mainHeight } from '@/utils/layout'
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
import { getDeviceData } from '@/api/cs-device-boot/EquipmentDelivery'
import { getTargetById } from '@/api/cs-device-boot/csDataArray'
import { getGroup } from '@/api/cs-device-boot/csGroup'
import { ref } from 'vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { passwordConfirm } from '@/api/user-boot/user'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
reStartDevice,
} from '@/api/cs-device-boot/fileService'
import { defaultAttribute } from '@/components/table/defaultAttribute'
const pageHeight = mainHeight(20)
const adminInfo = useAdminInfo()
const showButtom = ref(adminInfo.roleCode.includes('operation_manager') || adminInfo.roleCode.includes('root'))
const loading = ref(true)
const nDid = ref<string>('')
const tableLoading = ref(false)
const getGroupLoading = ref(false)
const deviceData = ref<any>(null)
const dataSet = ref('')
const devTypeOptions = ref([])
const devModelOptions = ref([])
const tableData = ref([])
const tableHeight = mainHeight(260).height
const mangePopup = ref()
const activeName = ref(0)
const xTableRef = ref()
//治理设备和便携式设备切换判断
const deviceType = ref('0')
const deviceTypeChange = (val: any, obj: any) => {
deviceType.value = val
nodeClick(obj)
}
// 树节点点击
const nodeClick = (e: anyObj) => {
if (!e) {
loading.value = false
return
}
if (e.level == 2) {
nDid.value = e.ndid
loading.value = true
getDeviceData(e.id, 'rt', '').then((res: any) => {
deviceData.value = res.data
loading.value = false
if (!res.data.dataSetList) {
dataSet.value = ''
tableData.value = []
} else {
if (res.data.dataSetList && res.data.dataSetList[0]?.id) {
dataSet.value = res.data.dataSetList[0]?.id
} else {
dataSet.value = ''
tableData.value = []
}
handleClick()
}
})
}
}
//tab点击事件
const handleClick = () => {
tableLoading.value = true
tableData.value = []
setTimeout(() => {
getTargetById(dataSet.value).then(res => {
tableData.value = res.data
tableLoading.value = false
})
}, 100)
}
queryByCode('Device_Type').then(res => {
queryCsDictTree(res.data.id).then(res => {
devTypeOptions.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
})
queryByid(res.data.id).then(res => {
devModelOptions.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
})
})
const echoName = (value: any, arr: any[]) => {
return arr.find(item => item.value == value)?.label
}
const openGroup = () => {
if (!dataSet.value) {
return ElMessage.warning('暂无数据')
}
getGroupLoading.value = true
getGroup(dataSet.value).then((res: any) => {
const call = (data: any[]) => {
data.forEach(item => {
item.label = item.name
item.isShow = item.isShow == 1
if (item.children && item.children.length > 0) {
call(item.children)
}
})
}
call(res.data)
getGroupLoading.value = false
mangePopup.value.open({
deviceData: deviceData.value,
dataSetName: deviceData.value.dataSetList.filter((item: any) => item.id == dataSet.value)[0]?.name,
dataSet: dataSet.value,
tree: res.data
})
})
}
//装置重启
const deviceRestartLoading = ref<boolean>(false)
const handleRestartDevice = () => {
deviceRestartLoading.value = true
ElMessageBox.prompt('二次校验密码确认', '装置重启', {
confirmButtonText: '确认',
cancelButtonText: '取消',
customClass: 'customInput',
inputType: 'text',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
if (instance.inputValue == null) {
return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else {
done();
}
} else {
done();
}
}
})
.then(({ value }) => {
if (!value) {
ElMessage.warning('请输入密码')
deviceRestartLoading.value = false
} else {
passwordConfirm(value)
.then((resp: any) => {
if (resp.code == 'A0000') {
reStartDevice({ nDid: nDid.value }).then((res: any) => {
deviceRestartLoading.value = false
ElMessage({ message: res.message, type: 'success', duration: 3000 })
}).catch(e => {
deviceRestartLoading.value = false
})
}
})
.catch(e => {
deviceRestartLoading.value = false
})
}
})
.catch(() => {
deviceRestartLoading.value = false
})
}
const exportData = () => {
xTableRef.value.exportData({
filename: deviceData.value.dataSetList.filter((item: any) => item.id == dataSet.value)[0]?.name, // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
download: false,
data: tableData.value, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column, $columnIndex) {
return !(column.$columnIndex === 0)
}
})
}
</script>
<style lang="scss">
.device-manage {
display: flex;
&-left {
width: 280px;
}
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;
display: flex;
align-items: center;
}
}
}
.customInput {
.el-input__inner {
-webkit-text-security: disc !important;
}
}
.export-btn {
position: absolute;
top: 4px;
right: 10px;
z-index: 10;
}
</style>
<!-- 设备管理 -->
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
<div class="device-manage-right" v-if="deviceData">
<el-descriptions title="基础信息" class="mb10" :column="3" border>
<template #extra>
<!-- <el-button
type="primary"
icon="el-icon-Share"
@click="openGroup"
:loading="getGroupLoading"
>
模版数据分组
</el-button> -->
<el-button
icon="el-icon-Refresh"
v-if="showButtom"
@click="handleRestartDevice"
type="primary"
:loading="deviceRestartLoading"
>
装置重启
</el-button>
</template>
<el-descriptions-item label="名称">
{{ deviceData.name || '/' }}
</el-descriptions-item>
<el-descriptions-item label="类型">
{{ echoName(deviceData.devType, devTypeOptions) || '/' }}
</el-descriptions-item>
<el-descriptions-item label="接入方式">
{{ deviceData.devAccessMethod || '/' }}
</el-descriptions-item>
<el-descriptions-item label="网络设备ID">
{{ deviceData.ndid || '/' }}
</el-descriptions-item>
<el-descriptions-item label="型号">
{{ echoName(deviceData.devModel, devModelOptions) || '/' }}
</el-descriptions-item>
<el-descriptions-item label="首次接入日期">
{{ deviceData.time || '/' }}
</el-descriptions-item>
<el-descriptions-item label="应用程序版本号">
{{ deviceData.appVersion || '/' }}
</el-descriptions-item>
<el-descriptions-item label="应用程序发布日期">
{{ deviceData.appDate || '/' }}
</el-descriptions-item>
<el-descriptions-item label="应用程序校验码">
{{ deviceData.appCheck || '/' }}
</el-descriptions-item>
</el-descriptions>
<div style="position: relative">
<el-tabs
v-model.trim="dataSet"
type="border-card"
class="device-manage-box-card"
@tab-click="handleClick"
>
<el-tab-pane
lazy
:label="item.name"
:name="item.id"
v-for="(item, index) in deviceData.dataSetList"
:key="index"
></el-tab-pane>
<div :style="{ height: tableHeight }" v-loading="tableLoading">
<vxe-table
v-bind="defaultAttribute"
:data="tableData"
height="auto"
ref="xTableRef"
style="width: 100%"
>
<vxe-column type="seq" title="序号" width="80"></vxe-column>
<vxe-column field="name" title="数据名称"></vxe-column>
<vxe-column field="phasic" title="相别"></vxe-column>
<vxe-column field="type" title="数据类型"></vxe-column>
<vxe-column field="unit" title="单位"></vxe-column>
<vxe-column field="startTimes" title="开始次数"></vxe-column>
<vxe-column field="endTimes" title="结束次数"></vxe-column>
</vxe-table>
</div>
</el-tabs>
<el-button icon="el-icon-Download" type="primary" @click="exportData" class="export-btn">
导出
</el-button>
</div>
</div>
<el-empty v-else description="请选择设备" class="device-manage-right" />
<MangePopup ref="mangePopup" />
</div>
</template>
<script setup lang="ts">
defineOptions({
name: 'govern/device/manage'
})
import MangePopup from './popup.vue'
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { mainHeight } from '@/utils/layout'
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
import { getDeviceData } from '@/api/cs-device-boot/EquipmentDelivery'
import { getTargetById } from '@/api/cs-device-boot/csDataArray'
import { getGroup } from '@/api/cs-device-boot/csGroup'
import { ref } from 'vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { passwordConfirm } from '@/api/user-boot/user'
import { ElMessage, ElMessageBox } from 'element-plus'
import { reStartDevice } from '@/api/cs-device-boot/fileService'
import { defaultAttribute } from '@/components/table/defaultAttribute'
const pageHeight = mainHeight(20)
const adminInfo = useAdminInfo()
const showButtom = ref(adminInfo.roleCode.includes('operation_manager') || adminInfo.roleCode.includes('root'))
const loading = ref(true)
const nDid = ref<string>('')
const tableLoading = ref(false)
const getGroupLoading = ref(false)
const deviceData = ref<any>(null)
const dataSet = ref('')
const devTypeOptions: any = ref([])
const devModelOptions = ref([])
const tableData = ref([])
const tableHeight = mainHeight(260).height
const mangePopup = ref()
const activeName = ref(0)
const xTableRef = ref()
//治理设备和便携式设备切换判断
const deviceType = ref('0')
const deviceTypeChange = (val: any, obj: any) => {
deviceType.value = val
nodeClick(obj)
}
// 树节点点击
const nodeClick = (e: anyObj) => {
if (!e) {
loading.value = false
return
}
if (e.level == 2) {
nDid.value = e.ndid
loading.value = true
getDeviceData(e.id, 'rt', '').then((res: any) => {
deviceData.value = res.data
loading.value = false
if (!res.data.dataSetList) {
dataSet.value = ''
tableData.value = []
} else {
if (res.data.dataSetList && res.data.dataSetList[0]?.id) {
dataSet.value = res.data.dataSetList[0]?.id
} else {
dataSet.value = ''
tableData.value = []
}
handleClick()
}
})
}
}
//tab点击事件
const handleClick = () => {
tableLoading.value = true
tableData.value = []
setTimeout(() => {
getTargetById(dataSet.value).then(res => {
tableData.value = res.data
tableLoading.value = false
})
}, 100)
}
queryByCode('Device_Type').then(async res => {
await queryCsDictTree(res.data.id).then(res => {
devTypeOptions.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
})
await queryByid(res.data.id).then(res => {
devModelOptions.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
})
await queryByCode('DEV_CLD').then(k => {
devTypeOptions.value.push(k.data)
return queryCsDictTree(k.data.id).then(s => {
let list = s.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
devModelOptions.value.push(...list)
})
})
})
const echoName = (value: any, arr: any[]) => {
return arr.find(item => item.id == value)?.name
}
const openGroup = () => {
if (!dataSet.value) {
return ElMessage.warning('暂无数据')
}
getGroupLoading.value = true
getGroup(dataSet.value).then((res: any) => {
const call = (data: any[]) => {
data.forEach(item => {
item.label = item.name
item.isShow = item.isShow == 1
if (item.children && item.children.length > 0) {
call(item.children)
}
})
}
call(res.data)
getGroupLoading.value = false
mangePopup.value.open({
deviceData: deviceData.value,
dataSetName: deviceData.value.dataSetList.filter((item: any) => item.id == dataSet.value)[0]?.name,
dataSet: dataSet.value,
tree: res.data
})
})
}
//装置重启
const deviceRestartLoading = ref<boolean>(false)
const handleRestartDevice = () => {
deviceRestartLoading.value = true
ElMessageBox.prompt('二次校验密码确认', '装置重启', {
confirmButtonText: '确认',
cancelButtonText: '取消',
customClass: 'customInput',
inputType: 'text',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
if (instance.inputValue == null) {
return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else {
done()
}
} else {
done()
}
}
})
.then(({ value }) => {
if (!value) {
ElMessage.warning('请输入密码')
deviceRestartLoading.value = false
} else {
passwordConfirm(value)
.then((resp: any) => {
if (resp.code == 'A0000') {
reStartDevice({ nDid: nDid.value })
.then((res: any) => {
deviceRestartLoading.value = false
ElMessage({ message: res.message, type: 'success', duration: 3000 })
})
.catch(e => {
deviceRestartLoading.value = false
})
}
})
.catch(e => {
deviceRestartLoading.value = false
})
}
})
.catch(() => {
deviceRestartLoading.value = false
})
}
const exportData = () => {
xTableRef.value.exportData({
filename: deviceData.value.dataSetList.filter((item: any) => item.id == dataSet.value)[0]?.name, // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
download: false,
data: tableData.value, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column, $columnIndex) {
return !(column.$columnIndex === 0)
}
})
}
</script>
<style lang="scss">
.device-manage {
display: flex;
&-left {
width: 280px;
}
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;
display: flex;
align-items: center;
}
}
}
.customInput {
.el-input__inner {
-webkit-text-security: disc !important;
}
}
.export-btn {
position: absolute;
top: 4px;
right: 10px;
z-index: 10;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<Table ref="tableRef" v-if="!isWaveCharts" />
<Table ref="tableRef" v-show="!isWaveCharts" />
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
</div>

View File

@@ -83,12 +83,12 @@
</el-descriptions-item>
<el-descriptions-item label="起始时间" width="160">
<span style="width: 140px; overflow: hidden; display: block">
{{ item.startTime }}
{{ item.startTime ||'/' }}
</span>
</el-descriptions-item>
<el-descriptions-item label="结束时间" width="160">
<span style="width: 140px; overflow: hidden; display: block">
{{ item.endTime }}
{{ item.endTime||'/' }}
</span>
</el-descriptions-item>
<el-descriptions-item label="监测位置" width="160">
@@ -121,6 +121,7 @@
<el-form-item for="-" label="统计指标">
<el-select
style="min-width: 200px"
filterable
collapse-tags
collapse-tags-tooltip
v-model.trim="searchForm.index"
@@ -266,6 +267,11 @@ const dictData = useDictData()
defineOptions({
// name: 'govern/device/planData/index'
})
const props = defineProps({
TrendList: {
type: Array
}
})
const childTab = ref('0')
const num = ref(0)
const config = useConfig()
@@ -313,53 +319,60 @@ const countOptions: any = ref([])
// Harmonic_Type
// portable-harmonic
const legendDictList: any = ref([])
queryByCode('portable-harmonic').then(res => {
queryCsDictTree(res.data.id).then(item => {
indexOptions.value = item.data.sort((a: any, b: any) => {
return a.sort - b.sort
// queryByCode('portable-harmonic').then(res => {
const getCode = (conType: string) => {
let code = volConTypeList.find(vv => {
return vv.id == conType
})?.code
queryByCode(code == 'Star_Triangle' ? 'portable-harmonic-jx' : 'portable-harmonic').then(res => {
queryCsDictTree(res.data.id).then(item => {
indexOptions.value = item.data.sort((a: any, b: any) => {
return a.sort - b.sort
})
searchForm.value.index[0] = indexOptions.value[0].id
// searchForm.value.index = indexOptions.value[0].id
})
searchForm.value.index[0] = indexOptions.value[0].id
// searchForm.value.index = indexOptions.value[0].id
})
queryStatistical(res.data.id).then(vv => {
legendDictList.value = vv.data
indexOptions.value.map((item: any, index: any) => {
if (!countDataCopy.value[index]) {
countDataCopy.value[index] = {
index: item.id,
countOptions: [],
count: [],
name: indexOptions.value.find((vv: any) => {
return vv.id == item.id
})?.name
queryStatistical(res.data.id).then(vv => {
legendDictList.value = vv.data
indexOptions.value.map((item: any, index: any) => {
if (!countDataCopy.value[index]) {
countDataCopy.value[index] = {
index: item.id,
countOptions: [],
count: [],
name: indexOptions.value.find((vv: any) => {
return vv.id == item.id
})?.name
}
}
}
legendDictList.value?.selectedList?.map((vv: any, vvs: any) => {
//查找相等的指标
if (item.id == vv.dataType) {
vv.eleEpdPqdVOS.map((kk: any, kks: any) => {
if (kk.harmStart && kk.harmEnd) {
range(0, 0, 0)
legendDictList.value?.selectedList?.map((vv: any, vvs: any) => {
//查找相等的指标
if (item.id == vv.dataType) {
vv.eleEpdPqdVOS.map((kk: any, kks: any) => {
if (kk.harmStart && kk.harmEnd) {
range(0, 0, 0)
if (kk.showName == '间谐波电压含有率') {
countDataCopy.value[index].countOptions = range(kk.harmStart, kk.harmEnd, 1).map(
(item: any) => {
return item - 0.5
}
)
} else {
// if (kk.showName == '间谐波电压含有率') {
// countDataCopy.value[index].countOptions = range(kk.harmStart, kk.harmEnd, 1).map(
// (item: any) => {
// return item - 0.5
// }
// )
// } else {
countDataCopy.value[index].countOptions = range(kk.harmStart, kk.harmEnd, 1)
// }
if (!countDataCopy.value[index].count || countDataCopy.value[index].count.length == 0) {
countDataCopy.value[index].count = countDataCopy.value[index].countOptions[0]
}
}
if (!countDataCopy.value[index].count || countDataCopy.value[index].count.length == 0) {
countDataCopy.value[index].count = countDataCopy.value[index].countOptions[0]
}
}
})
}
})
}
})
})
})
})
})
}
// getCode(1)
const activeName: any = ref()
const activeColName: any = ref('0')
const deviceData: any = ref([])
@@ -368,11 +381,15 @@ const schemeTreeRef = ref()
const historyDevId: any = ref('')
const chartTitle: any = ref('')
//点击测试项切换树节点
const handleClickTabs = () => {
searchForm.value.index = [indexOptions.value[0].id]
historyDevId.value = activeName.value
schemeTreeRef.value.setCheckedNode(activeName.value)
setTimeout(() => {
const handleClickTabs = async () => {
await getCode(deviceData.value.records.filter(item => item.id == activeName.value)[0].volConType)
await setTimeout(() => {
searchForm.value.index = [indexOptions.value[0].id]
historyDevId.value = activeName.value
schemeTreeRef.value.setCheckedNode(activeName.value)
}, 100)
await setTimeout(() => {
init(true)
transientRef.value && transientRef.value.init()
}, 100)
@@ -391,6 +408,7 @@ const nodeClick = async (e: anyObj) => {
await getTestRecordInfo(id)
.then(async res => {
deviceData.value = res.data
if (res.data.records.length == 1) {
activeName.value = res.data.records[0].id
} else {
@@ -406,6 +424,7 @@ const nodeClick = async (e: anyObj) => {
activeName.value = res.data.records[0].id
}
}
getCode(deviceData.value.records.filter(item => item.id == activeName.value)[0].volConType)
// if (searchForm.value.index.length == 0) {
// searchForm.value.index = [indexOptions.value[0].id]
@@ -547,7 +566,7 @@ const init = (flag: boolean) => {
let frequencys: any = null
countData.value.map((item: any, index: any) => {
if (item.name.includes('间谐波电压')) {
frequencys = item.count + 0.5
frequencys = item.count //+ 0.5
} else {
frequencys = item.count
}
@@ -574,8 +593,8 @@ const init = (flag: boolean) => {
}).then(res => {
if (res.data.length == 0) {
titleList.value = '(未绑定数据)'
}else{
titleList.value = ''
} else {
titleList.value = ''
}
chartTitle.value = chartTitle.value + titleList.value
})

View File

@@ -109,10 +109,10 @@
:title="dialogTitle"
v-model="dialogFormVisible"
:close-on-click-modal="false"
width="700px"
width="500px"
:before-close="resetForm"
>
<el-form :model="formData" label-width="120px" :rules="rules" ref="ruleFormRef">
<el-form :model="formData" label-width="120px" :rules="rules" ref="ruleFormRef" class="form-one">
<el-form-item label="名称:" prop="name">
<el-input
v-model="formData.name"
@@ -178,8 +178,8 @@
</el-dialog>
<!-- 绑定进程号 -->
<el-dialog draggable title="绑定进程号" v-model="popUps" :close-on-click-modal="false" width="400px">
<el-form :model="bindProcessForm" ref="bindProcessFormRef" label-width="80px" :rules="rules2">
<el-dialog draggable title="绑定进程号" v-model="popUps" :close-on-click-modal="false" width="400px" >
<el-form :model="bindProcessForm" ref="bindProcessFormRef" label-width="80px" :rules="rules2" class="form-one">
<el-form-item label="前置机" prop="nodeId">
<el-select
v-model="bindProcessForm.nodeId"

View File

@@ -44,7 +44,7 @@
<div class="tableBox" v-if="show">
<vxe-table border auto-resize height="230px" :data="tableData" ref="tableRef">
<vxe-column type="seq" title="序号" align="center" width="80px"></vxe-column>
<vxe-column field="date" align="center" title="时间" width="200px"></vxe-column>
<vxe-column field="date" align="center" sortable title="时间" width="200px"></vxe-column>
<vxe-column field="name" align="center" title="监测点名" width="200px"></vxe-column>
<vxe-column field="address" align="center" title="事件描述"></vxe-column>
</vxe-table>