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

日志级别配置:新增页面
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>
</el-dialog>
<el-dialog v-model="realDataLineChartVisible" title="实时曲线" @close="closeLineChart" width="1200">
<RealDataChart
<!-- <RealDataChart
ref="realDataChartRef"
:visible="realDataLineChartVisible"
:id="clickRow!.irn"
:iot-model-id="selectPointModelId"
@clearChart="() => (linePause = false)"
></RealDataChart> -->
<RealDataChart
ref="realDataChartRef"
:visible="realDataLineChartVisible"
:id="clickRow!.irn"
:iot-model-id="selectPointModelId"
></RealDataChart>
<template #header>
<div>
<span style="font-size: 18px">实时曲线</span>
<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>
</template>
</el-dialog>
@ -796,16 +802,16 @@ const openLineChart = (row: TableDataObjType) => {
clickRow.value = row
realDataLineChartVisible.value = true
autoUpdate.value = false
linePause.value = false
// linePause.value = false
}
const closeLineChart = () => {
autoUpdate.value = true
}
const linePause = ref(false)
// const linePause = ref(false)
const saveLineChart = () => {
const data = realDataChartRef.value?.saveChart()
linePause.value = true
// linePause.value = true
const info = 'deviceCode:' + clickRow.value?.deviceCode + '\n' + 'deviceName:' + clickRow.value?.name + '\n'
let title = 'TimeStamp;'
let columns = ''
@ -824,16 +830,17 @@ const saveLineChart = () => {
let uri = 'data:text/plain;charset=utf-8,' + encodeURIComponent(str)
let link = document.createElement('a')
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)
link.click()
document.body.removeChild(link)
}
const continueLineChart = () => {
realDataChartRef.value?.continueChart()
linePause.value = false
}
// const continueLineChart = () => {
// realDataChartRef.value?.continueChart()
// linePause.value = false
// }
onUnmounted(() => {
autoUpdateInterval.value && clearInterval(autoUpdateInterval.value)

View File

@ -157,12 +157,18 @@ let realDataXAxis: any = []
let realDataSeries: any = []
let realDataYAxis: 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
}
@ -176,14 +182,13 @@ const createChartData = (data: { [k: string]: number }, time: string) => {
const attrCode = Object.keys(data)
realDataXAxis.push(time)
const lastSeriesId = realDataSeries.map((item: any) => item.id)
const color = getRandomDarkColor()
let clearState = null
lastSeriesId.forEach((item: any) => {
if (!attrCode.includes(item)) {
const cur = realDataSeries.findIndex((val: any) => val.id === item)
realDataSeries.splice(cur, 1)
const curLegendIndex = realDataLegend.findIndex((val:any)=>val.customKey===item)
realDataLegend.splice(curLegendIndex,1)
const curLegendIndex = realDataLegend.findIndex((val: any) => val.customKey === item)
realDataLegend.splice(curLegendIndex, 1)
clearState = true
}
})
@ -194,7 +199,7 @@ const createChartData = (data: { [k: string]: number }, time: string) => {
legend: realDataLegend,
},
{
replaceMerge: ['series','legend'],
replaceMerge: ['series', 'legend'],
}
)
}
@ -205,18 +210,19 @@ const createChartData = (data: { [k: string]: number }, time: string) => {
cur.data.push(curVal)
return cur
} else {
const color = getRandomDarkColor()
const info = realDataList.value.find((val) => val.prop === item)
const list = realDataSeries?.[0]?.data ?? []
const len = list.length
const fillData = new Array(len).fill('')
fillData.push(curVal)
realDataLegend.push({
name:info.name,
name: info.name,
icon: 'rect',
textStyle: {
color: color,
},
customKey:item
customKey: item,
})
return {
id: item,
@ -253,7 +259,7 @@ const createChart = () => {
})
const nameMapKeys = Object.keys(nameMap)
if (realDataSeries.length >= 4 && nameMapKeys.length === 4) {
if (nameMapKeys.length === 4) {
selectPointNum.value = realDataSeries.length
}
const yAxisData = nameMapKeys.map((item, index) => {
@ -308,7 +314,7 @@ const createChart = () => {
},
yAxis: realDataYAxis,
series: realDataSeries,
legend:realDataLegend
legend: realDataLegend,
}
} else {
option = {
@ -398,14 +404,11 @@ const createChart = () => {
],
legend: {
data: realDataLegend,
textStyle: {
color: '#73767a',
},
},
series: realDataSeries,
}
}
chart.setOption(option, { replaceMerge: ['series', 'yAxis','legend'] })
chart.setOption(option, { replaceMerge: ['series', 'yAxis', 'legend'] })
chartInstance = chart
}
@ -463,31 +466,31 @@ const clearTimer = () => {
realDataSeries = []
realDataXAxis = []
realDataYAxis = []
pauseState.value = false
emits('clearChart')
// pauseState.value = false
// emits('clearChart')
}
const pauseState = ref(false)
// const pauseState = ref(false)
const saveChart = () => {
timer && clearInterval(timer)
pauseState.value = true
// timer && clearInterval(timer)
// pauseState.value = true
return {
time: realDataXAxis,
chartData: realDataSeries,
}
}
const continueChart = () => {
pauseState.value = false
const fillVal = new Array(5).fill('')
realDataXAxis.push(...fillVal)
realDataSeries.forEach((item: any) => {
item.data.push(...fillVal)
})
createTimer()
}
// const continueChart = () => {
// pauseState.value = false
// const fillVal = new Array(5).fill('')
// realDataXAxis.push(...fillVal)
// realDataSeries.forEach((item: any) => {
// item.data.push(...fillVal)
// })
// createTimer()
// }
defineExpose({
saveChart,
continueChart,
// continueChart,
})
onMounted(() => {
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>