实时数据:实时曲线取消保存暂停,修改显示逻辑

日志级别配置:新增页面
This commit is contained in:
高云鹏 2024-12-30 15:48:25 +08:00
parent cfb432280a
commit 0070e94bfa
4 changed files with 288 additions and 42 deletions

View File

@ -0,0 +1,24 @@
import createAxios from '/@/utils/axios'
export function getLogConfigurationListReq() {
return createAxios({
url: '/api/logger/list',
method: 'POST',
})
}
export function updateLogConfigurationListReq(params: any) {
return createAxios({
url: '/api/logger/update',
method: 'POST',
data: params,
})
}
export function delLogConfigurationListReq(params: any) {
return createAxios({
url: '/api/logger/delete',
method: 'POST',
data: params,
})
}

View File

@ -198,18 +198,24 @@
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="realDataLineChartVisible" title="实时曲线" @close="closeLineChart" width="1200"> <el-dialog v-model="realDataLineChartVisible" title="实时曲线" @close="closeLineChart" width="1200">
<RealDataChart <!-- <RealDataChart
ref="realDataChartRef" ref="realDataChartRef"
:visible="realDataLineChartVisible" :visible="realDataLineChartVisible"
:id="clickRow!.irn" :id="clickRow!.irn"
:iot-model-id="selectPointModelId" :iot-model-id="selectPointModelId"
@clearChart="() => (linePause = false)" @clearChart="() => (linePause = false)"
></RealDataChart> -->
<RealDataChart
ref="realDataChartRef"
:visible="realDataLineChartVisible"
:id="clickRow!.irn"
:iot-model-id="selectPointModelId"
></RealDataChart> ></RealDataChart>
<template #header> <template #header>
<div> <div>
<span style="font-size: 18px">实时曲线</span> <span style="font-size: 18px">实时曲线</span>
<el-button class="saveBtn" @click="saveLineChart" type="primary" plain>保存</el-button> <el-button class="saveBtn" @click="saveLineChart" type="primary" plain>保存</el-button>
<el-button v-if="linePause" class="continueBtn" @click="continueLineChart" type="primary" plain>继续</el-button> <!-- <el-button v-if="linePause" class="continueBtn" @click="continueLineChart" type="primary" plain>继续</el-button> -->
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -796,16 +802,16 @@ const openLineChart = (row: TableDataObjType) => {
clickRow.value = row clickRow.value = row
realDataLineChartVisible.value = true realDataLineChartVisible.value = true
autoUpdate.value = false autoUpdate.value = false
linePause.value = false // linePause.value = false
} }
const closeLineChart = () => { const closeLineChart = () => {
autoUpdate.value = true autoUpdate.value = true
} }
const linePause = ref(false) // const linePause = ref(false)
const saveLineChart = () => { const saveLineChart = () => {
const data = realDataChartRef.value?.saveChart() const data = realDataChartRef.value?.saveChart()
linePause.value = true // linePause.value = true
const info = 'deviceCode:' + clickRow.value?.deviceCode + '\n' + 'deviceName:' + clickRow.value?.name + '\n' const info = 'deviceCode:' + clickRow.value?.deviceCode + '\n' + 'deviceName:' + clickRow.value?.name + '\n'
let title = 'TimeStamp;' let title = 'TimeStamp;'
let columns = '' let columns = ''
@ -824,16 +830,17 @@ const saveLineChart = () => {
let uri = 'data:text/plain;charset=utf-8,' + encodeURIComponent(str) let uri = 'data:text/plain;charset=utf-8,' + encodeURIComponent(str)
let link = document.createElement('a') let link = document.createElement('a')
link.href = uri link.href = uri
link.download = clickRow.value?.deviceCode + 'ChartData' + '.txt' const titleTime = data.time[0] + '-' + data.time[data.time.length - 1]
link.download = 'deviceCode' + clickRow.value?.deviceCode + ';' + titleTime + '.txt'
document.body.appendChild(link) document.body.appendChild(link)
link.click() link.click()
document.body.removeChild(link) document.body.removeChild(link)
} }
const continueLineChart = () => { // const continueLineChart = () => {
realDataChartRef.value?.continueChart() // realDataChartRef.value?.continueChart()
linePause.value = false // linePause.value = false
} // }
onUnmounted(() => { onUnmounted(() => {
autoUpdateInterval.value && clearInterval(autoUpdateInterval.value) autoUpdateInterval.value && clearInterval(autoUpdateInterval.value)

View File

@ -157,12 +157,18 @@ let realDataXAxis: any = []
let realDataSeries: any = [] let realDataSeries: any = []
let realDataYAxis: any = [] let realDataYAxis: any = []
let realDataLegend: any = [] let realDataLegend: any = []
const getRandomDarkColor = () => {
let r = Math.floor(Math.random() * 200) // 0127
let g = Math.floor(Math.random() * 200)
let b = Math.floor(Math.random() * 200)
let color = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}` const colorList = ['#ee1289', '#b8860b', '#ff00ff', '#ff0000', '#ff9912', '#8a2be2', '#000000', '#03a89e']
const getRandomDarkColor = () => {
// if (index >= colorList.length) {
// let r = Math.floor(Math.random() * 200) // 0127
// let g = Math.floor(Math.random() * 200)
// let b = Math.floor(Math.random() * 200)
// let color = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
// return color
// }
const color = colorList.shift() as string
colorList.push(color)
return color return color
} }
@ -176,14 +182,13 @@ const createChartData = (data: { [k: string]: number }, time: string) => {
const attrCode = Object.keys(data) const attrCode = Object.keys(data)
realDataXAxis.push(time) realDataXAxis.push(time)
const lastSeriesId = realDataSeries.map((item: any) => item.id) const lastSeriesId = realDataSeries.map((item: any) => item.id)
const color = getRandomDarkColor()
let clearState = null let clearState = null
lastSeriesId.forEach((item: any) => { lastSeriesId.forEach((item: any) => {
if (!attrCode.includes(item)) { if (!attrCode.includes(item)) {
const cur = realDataSeries.findIndex((val: any) => val.id === item) const cur = realDataSeries.findIndex((val: any) => val.id === item)
realDataSeries.splice(cur, 1) realDataSeries.splice(cur, 1)
const curLegendIndex = realDataLegend.findIndex((val:any)=>val.customKey===item) const curLegendIndex = realDataLegend.findIndex((val: any) => val.customKey === item)
realDataLegend.splice(curLegendIndex,1) realDataLegend.splice(curLegendIndex, 1)
clearState = true clearState = true
} }
}) })
@ -194,7 +199,7 @@ const createChartData = (data: { [k: string]: number }, time: string) => {
legend: realDataLegend, legend: realDataLegend,
}, },
{ {
replaceMerge: ['series','legend'], replaceMerge: ['series', 'legend'],
} }
) )
} }
@ -205,18 +210,19 @@ const createChartData = (data: { [k: string]: number }, time: string) => {
cur.data.push(curVal) cur.data.push(curVal)
return cur return cur
} else { } else {
const color = getRandomDarkColor()
const info = realDataList.value.find((val) => val.prop === item) const info = realDataList.value.find((val) => val.prop === item)
const list = realDataSeries?.[0]?.data ?? [] const list = realDataSeries?.[0]?.data ?? []
const len = list.length const len = list.length
const fillData = new Array(len).fill('') const fillData = new Array(len).fill('')
fillData.push(curVal) fillData.push(curVal)
realDataLegend.push({ realDataLegend.push({
name:info.name, name: info.name,
icon: 'rect', icon: 'rect',
textStyle: { textStyle: {
color: color, color: color,
}, },
customKey:item customKey: item,
}) })
return { return {
id: item, id: item,
@ -253,7 +259,7 @@ const createChart = () => {
}) })
const nameMapKeys = Object.keys(nameMap) const nameMapKeys = Object.keys(nameMap)
if (realDataSeries.length >= 4 && nameMapKeys.length === 4) { if (nameMapKeys.length === 4) {
selectPointNum.value = realDataSeries.length selectPointNum.value = realDataSeries.length
} }
const yAxisData = nameMapKeys.map((item, index) => { const yAxisData = nameMapKeys.map((item, index) => {
@ -308,7 +314,7 @@ const createChart = () => {
}, },
yAxis: realDataYAxis, yAxis: realDataYAxis,
series: realDataSeries, series: realDataSeries,
legend:realDataLegend legend: realDataLegend,
} }
} else { } else {
option = { option = {
@ -398,14 +404,11 @@ const createChart = () => {
], ],
legend: { legend: {
data: realDataLegend, data: realDataLegend,
textStyle: {
color: '#73767a',
},
}, },
series: realDataSeries, series: realDataSeries,
} }
} }
chart.setOption(option, { replaceMerge: ['series', 'yAxis','legend'] }) chart.setOption(option, { replaceMerge: ['series', 'yAxis', 'legend'] })
chartInstance = chart chartInstance = chart
} }
@ -463,31 +466,31 @@ const clearTimer = () => {
realDataSeries = [] realDataSeries = []
realDataXAxis = [] realDataXAxis = []
realDataYAxis = [] realDataYAxis = []
pauseState.value = false // pauseState.value = false
emits('clearChart') // emits('clearChart')
} }
const pauseState = ref(false) // const pauseState = ref(false)
const saveChart = () => { const saveChart = () => {
timer && clearInterval(timer) // timer && clearInterval(timer)
pauseState.value = true // pauseState.value = true
return { return {
time: realDataXAxis, time: realDataXAxis,
chartData: realDataSeries, chartData: realDataSeries,
} }
} }
const continueChart = () => { // const continueChart = () => {
pauseState.value = false // pauseState.value = false
const fillVal = new Array(5).fill('') // const fillVal = new Array(5).fill('')
realDataXAxis.push(...fillVal) // realDataXAxis.push(...fillVal)
realDataSeries.forEach((item: any) => { // realDataSeries.forEach((item: any) => {
item.data.push(...fillVal) // item.data.push(...fillVal)
}) // })
createTimer() // createTimer()
} // }
defineExpose({ defineExpose({
saveChart, saveChart,
continueChart, // continueChart,
}) })
onMounted(() => { onMounted(() => {
if (selectList.value.length > 0) { if (selectList.value.length > 0) {

View File

@ -0,0 +1,212 @@
<template>
<div class="logConfiguration">
<div class="header">
<el-input @input="searchInput" class="logConfigurationInput" v-model="searchInputValue" placeholder="请输入日志名称" clearable></el-input>
<el-button type="primary" @click="addLogConfiguration">新增日志配置</el-button>
</div>
<div class="content">
<el-table :data="tableData" class="logTable">
<el-table-column label="名称" prop="loggerName" align="left"></el-table-column>
<el-table-column label="日志级别" prop="level" align="center">
<template #default="scope">
<el-select v-model="scope.row.level" v-if="scope.row.hasEdit">
<el-option value="FATAL"></el-option>
<el-option value="ERROR"></el-option>
<el-option value="WARN"></el-option>
<el-option value="INFO"></el-option>
<el-option value="DEBUG"></el-option>
<el-option value="TRACE"></el-option>
</el-select>
<div v-else @click="editLevel(scope.row)">
<el-button text>{{ scope.row.level }}</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="240px" align="center">
<template #default="scope">
<div class="logTableOperate">
<el-button v-if="scope.row.hasEdit" @click="submitLevel(scope.row)" text type="success">保存</el-button>
<el-button v-if="scope.row.hasEdit" @click="cancelLevel(scope.row)" text type="info">取消</el-button>
<el-button text type="primary" @click.stop="editLogConfiguration(scope)">编辑</el-button>
<el-popconfirm title="确定删除吗?" @confirm="delLogConfiguration(scope)">
<template #reference>
<el-button text type="danger" @click.stop>删除</el-button>
</template>
</el-popconfirm>
</div>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :title="logDialogTitle" v-model="logDialogVisible" :width="400" align-center>
<el-form :model="logFormModel" label-width="80">
<el-form-item label="名称">
<el-input v-model="logFormModel.loggerName"></el-input>
</el-form-item>
<el-form-item label="日志级别">
<el-select v-model="logFormModel.level">
<el-option value="FATAL"></el-option>
<el-option value="ERROR"></el-option>
<el-option value="WARN"></el-option>
<el-option value="INFO"></el-option>
<el-option value="DEBUG"></el-option>
<el-option value="TRACE"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="logDialogFooter">
<el-button type="primary" @click="submitlogForm(null)">保存</el-button>
<el-button @click="closeLogForm">取消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { getLogConfigurationListReq, updateLogConfigurationListReq, delLogConfigurationListReq } from '/@/api/backend/logConfiguration/request'
import { ElMessage } from 'element-plus'
import { debounce } from 'lodash-es'
const searchInputValue = ref('')
const change = () => {
if (searchInputValue.value === '') {
tableData.value = originTableData
return
}
const reg = new RegExp(searchInputValue.value, 'i')
tableData.value = originTableData.filter((item) => {
return reg.test(item.loggerName)
}) as { loggerName: string; level: string; hasEdit: boolean }[]
}
const searchInput = debounce(change, 500)
let originTableData: { loggerName: string; level: string; hasEdit: boolean }[] = []
const tableData = ref<{ loggerName: string; level: string; hasEdit: boolean }[]>([])
const originLogFormModel = {
loggerName: '',
level: '',
}
const logFormModel = reactive(JSON.parse(JSON.stringify(originLogFormModel)))
const logDialogTitle = ref('编辑日志配置')
const logDialogVisible = ref(false)
const submitlogForm = (data: { loggerName: string; level: string } | null) => {
const reqData = data ?? logFormModel
updateLogConfigurationListReq(reqData).then((res: any) => {
if (res.success) {
logDialogVisible.value = false
getLogList()
ElMessage.success('保存成功')
}
})
}
const closeLogForm = () => {
logDialogVisible.value = false
}
const originLevel = ref('')
const editLevel = (data: { loggerName: string; level: string; hasEdit: boolean }) => {
originLevel.value = data.level
data.hasEdit = true
}
const submitLevel = (data: { loggerName: string; level: string; hasEdit: boolean }) => {
submitlogForm({ loggerName: data.loggerName, level: data.level })
}
const cancelLevel = (data: { loggerName: string; level: string; hasEdit: boolean }) => {
data.level = originLevel.value
data.hasEdit = false
}
const addLogConfiguration = () => {
logDialogTitle.value = '新增日志配置'
logDialogVisible.value = true
logFormModel.loggerName = originLogFormModel.loggerName
logFormModel.level = originLogFormModel.level
}
const editLogConfiguration = (scope: any) => {
logDialogTitle.value = '编辑日志配置'
logDialogVisible.value = true
logFormModel.loggerName = scope.row.loggerName
logFormModel.level = scope.row.level
}
const delLogConfiguration = (scope: any) => {
delLogConfigurationListReq({ loggerName: scope.row.loggerName }).then((res: any) => {
if (res.success) {
getLogList()
ElMessage.success('删除成功')
}
})
}
const getLogList = () => {
getLogConfigurationListReq().then((res) => {
if (res.data) {
const data = Object.keys(res.data)
.sort()
.map((item: string) => {
return {
loggerName: item,
level: res.data[item],
hasEdit: false,
}
})
tableData.value = data
originTableData = data
}
})
}
getLogList()
</script>
<style lang="scss" scoped>
.logConfiguration {
width: 100%;
height: 100%;
padding: 10px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
width: 100%;
height: 60px;
.el-input {
width: 250px;
height: 40px;
}
.el-button {
height: 40px;
}
}
.content {
width: 100%;
height: calc(100% - 60px);
.logTable {
width: 100%;
height: 100%;
.el-select {
width: 200px;
}
&:deep(.el-select__wrapper) {
width: 200x;
}
.logTableOperate {
display: flex;
justify-content: right;
width: 100%;
.el-button {
margin-left: 0;
}
}
}
}
.pagination {
width: 100%;
height: 40px;
display: flex;
justify-content: right;
align-items: center;
}
}
</style>