feat:kpi看板数据显示修复

This commit is contained in:
zhongzm
2025-07-04 17:30:54 +08:00
parent 8990fa8dee
commit 82cb796a50

View File

@@ -11,10 +11,21 @@
@change="onImsNeChange" @change="onImsNeChange"
style="width: 100px; font-size: 15px;" style="width: 100px; font-size: 15px;"
:dropdown-style="{ borderRadius: '8px' }" :dropdown-style="{ borderRadius: '8px' }"
placeholder='No NE'
:bordered="true" :bordered="true"
class="ims-select" class="ims-select"
:allow-clear="false" :allow-clear="false"
/> />
<!-- <a-button-->
<!-- type="primary"-->
<!-- style="margin-left: 16px;"-->
<!-- @click="testDataUpdate"-->
<!-- >-->
<!-- 测试数据更新-->
<!-- </a-button>-->
<!-- <div style="margin-top: 8px; font-size: 12px; color: #666;">-->
<!-- WebSocket状态: {{ wsStatus }} | 数据点数量: {{ imsRealtimeRawData.length }}-->
<!-- </div>-->
</div> </div>
<div class="row-title">Calls</div> <div class="row-title">Calls</div>
<a-row :gutter="[48, 48]"> <a-row :gutter="[48, 48]">
@@ -42,7 +53,7 @@
<!-- <div class="card-content">--> <!-- <div class="card-content">-->
<!-- <div class="trend-chart">--> <!-- <div class="trend-chart">-->
<!-- <div class="mini-chart" ref="mosChartRef"></div>--> <!-- <div class="mini-chart" ref="mosChartRef"></div>-->
<!-- <div class="card-subtext">60m <span class="card-sub-sep">now</span></div>--> <!--&lt;!&ndash; <div class="card-subtext">60m <span class="card-sub-sep">now</span></div>&ndash;&gt;-->
<!-- </div>--> <!-- </div>-->
<!-- <div class="metric-info">--> <!-- <div class="metric-info">-->
<!-- <div class="metric-value">--> <!-- <div class="metric-value">-->
@@ -164,42 +175,74 @@ const selectedImsNeId = ref('')
const imsWs = ref<any>(null) const imsWs = ref<any>(null)
// IMS实时原始数据只存储当前选中网元 // IMS实时原始数据只存储当前选中网元
const imsRealtimeRawData = ref<any[]>([]) const imsRealtimeRawData = ref<any[]>([])
// WebSocket连接状态
const wsStatus = ref('未连接')
// 获取IMS网元列表 // 获取IMS网元列表
onMounted(async () => { onMounted(async () => {
// console.log('组件挂载开始获取IMS网元列表') // 调试信息
const neInfoStore = useNeInfoStore() const neInfoStore = useNeInfoStore()
const res = await neInfoStore.fnNelist() const res = await neInfoStore.fnNelist()
// console.log('获取到的网元列表响应:', res) // 调试信息
if (res && Array.isArray(res.data)) { if (res && Array.isArray(res.data)) {
imsNeList.value = res.data.filter((ne: any) => ne.neType === 'IMS') imsNeList.value = res.data.filter((ne: any) => ne.neType === 'IMS')
// console.log('过滤后的IMS网元列表:', imsNeList.value) // 调试信息
if (imsNeList.value.length > 0) { if (imsNeList.value.length > 0) {
selectedImsNeId.value = imsNeList.value[0].neId selectedImsNeId.value = imsNeList.value[0].neId
// console.log('默认选中第一个IMS网元:', selectedImsNeId.value) // 调试信息
subscribeImsRealtime(selectedImsNeId.value) subscribeImsRealtime(selectedImsNeId.value)
} else {
// console.warn('没有找到IMS类型的网元') // 调试信息
} }
} else {
// console.error('获取网元列表失败或数据格式不正确') // 调试信息
} }
}) })
// 切换IMS网元时重新订阅 // 切换IMS网元时重新订阅
function onImsNeChange() { function onImsNeChange() {
// console.log('切换IMS网元新的网元ID:', selectedImsNeId.value) // 调试信息
subscribeImsRealtime(selectedImsNeId.value) subscribeImsRealtime(selectedImsNeId.value)
} }
// 订阅指定IMS网元实时数据 // 订阅指定IMS网元实时数据
function subscribeImsRealtime(neId: string) { function subscribeImsRealtime(neId: string) {
// console.log('开始订阅IMS网元数据网元ID:', neId) // 调试信息
wsStatus.value = '连接中...' // 更新状态
// 关闭旧WebSocket // 关闭旧WebSocket
if (imsWs.value) { if (imsWs.value) {
// console.log('关闭旧WebSocket连接') // 调试信息
imsWs.value.close() imsWs.value.close()
imsWs.value = null imsWs.value = null
} }
imsRealtimeRawData.value = [] imsRealtimeRawData.value = []
if (!neId) return if (!neId) return
imsWs.value = new WS() imsWs.value = new WS()
// console.log('创建新的WebSocket连接') // 调试信息
imsWs.value.connect({ imsWs.value.connect({
url: '/ws', url: '/ws',
params: { params: {
subGroupID: `10_IMS_${neId}`, subGroupID: `10_IMS_${neId}`,
}, },
onmessage: handleIMSRealtimeData, onmessage: handleIMSRealtimeData,
onerror: () => {}, onerror: (error: any) => {
// console.error('WebSocket连接错误:', error) // 调试信息
wsStatus.value = '连接错误' // 更新状态
},
onopen: () => {
// console.log('WebSocket连接已建立') // 调试信息
wsStatus.value = '已连接' // 更新状态
},
onclose: () => {
// console.log('WebSocket连接已关闭') // 调试信息
wsStatus.value = '已断开' // 更新状态
}
}) })
} }
@@ -209,6 +252,7 @@ onBeforeUnmount(() => {
imsWs.value.close() imsWs.value.close()
imsWs.value = null imsWs.value = null
} }
wsStatus.value = '已断开' // 更新状态
}) })
// 更新active calls图表 // 更新active calls图表
@@ -465,10 +509,53 @@ function updateFailedRegistrationsChart() {
// 处理IMS实时数据只存储当前选中网元 // 处理IMS实时数据只存储当前选中网元
function handleIMSRealtimeData(res: any) { function handleIMSRealtimeData(res: any) {
if (res && res.data) { // console.log('收到实时数据:', res) // 调试信息
imsRealtimeRawData.value.push(res)
// 检查数据结构:后端实际格式是 {code: 1, data: {...}, msg: 'success'}
const { code, data, msg } = res
// 检查是否是错误响应
if (code !== 1 || !data) {
// console.warn('收到错误响应或数据格式不正确:', res) // 调试信息
return
}
// 检查是否是连接确认消息只包含clientId
if (data.clientId) {
// console.log('收到WebSocket连接确认消息:', data.clientId) // 调试信息
return
}
// 检查是否是KPI数据消息包含data和groupId
if (data.data && data.groupId) {
// console.log('收到KPI数据消息groupId:', data.groupId) // 调试信息
// 解析订阅组ID确认是我们订阅的IMS网元
const [_, neType, neId] = data.groupId.split('_')
if (neType !== 'IMS' || neId !== selectedImsNeId.value) {
// console.log('收到其他网元数据,忽略:', data.groupId) // 调试信息
return
}
const kpiEvent = data.data
if (!kpiEvent) {
// console.warn('KPI事件数据为空') // 调试信息
return
}
// console.log('处理IMS网元KPI数据:', kpiEvent) // 调试信息
// 确保数据结构正确
const dataToStore = {
timestamp: Date.now(),
data: kpiEvent
}
imsRealtimeRawData.value.push(dataToStore)
if (imsRealtimeRawData.value.length > 200) imsRealtimeRawData.value.shift() if (imsRealtimeRawData.value.length > 200) imsRealtimeRawData.value.shift()
// console.log('数据已存储,当前数组长度:', imsRealtimeRawData.value.length) // 调试信息
// 更新active calls图表 // 更新active calls图表
updateActiveCallsChart() updateActiveCallsChart()
// 更新failed calls图表 // 更新failed calls图表
@@ -477,26 +564,32 @@ function handleIMSRealtimeData(res: any) {
updateActiveRegistrationsChart() updateActiveRegistrationsChart()
// 更新failed registrations图表 // 更新failed registrations图表
updateFailedRegistrationsChart() updateFailedRegistrationsChart()
} else {
// console.log('收到未知格式的数据:', data) // 调试信息
} }
} }
onMounted(() => { onMounted(() => {
// active calls // 初始化所有图表为0值线
if (callsChartRef.value) { const defaultChartOption = {
const chart = echarts.init(callsChartRef.value)
chart.setOption({
grid: { left: 0, right: 0, top: 10, bottom: 10 }, grid: { left: 0, right: 0, top: 10, bottom: 10 },
xAxis: { type: 'category', show: false, data: [1, 2, 3, 4, 5] }, xAxis: { type: 'category', show: false, data: [1, 2, 3, 4, 5] },
yAxis: { type: 'value', show: false }, yAxis: { type: 'value', show: false },
series: [{ series: [{
data: [12701, 12000, 11000, 10700, 10274], data: [0, 0, 0, 0, 0], // 默认显示0值
type: 'line', smooth: true, symbol: 'none', type: 'line', smooth: true, symbol: 'none',
lineStyle: { width: 2, color: '#1890ff' }, lineStyle: { width: 2, color: '#d9d9d9' }, // 灰色线条表示无数据
areaStyle: { color: 'rgba(24,144,255,0.1)' } areaStyle: { color: 'rgba(217,217,217,0.1)' } // 淡灰色填充
}] }]
})
} }
// MOS
// active calls
if (callsChartRef.value) {
const chart = echarts.init(callsChartRef.value)
chart.setOption(defaultChartOption)
}
// MOS - 保持原有的模拟数据
if (mosChartRef.value) { if (mosChartRef.value) {
const chart = echarts.init(mosChartRef.value) const chart = echarts.init(mosChartRef.value)
chart.setOption({ chart.setOption({
@@ -511,50 +604,23 @@ onMounted(() => {
}] }]
}) })
} }
// failed calls // failed calls
if (failedCallsChartRef.value) { if (failedCallsChartRef.value) {
const chart = echarts.init(failedCallsChartRef.value) const chart = echarts.init(failedCallsChartRef.value)
chart.setOption({ chart.setOption(defaultChartOption)
grid: { left: 0, right: 0, top: 10, bottom: 10 },
xAxis: { type: 'category', show: false, data: [1,2,3,4,5] },
yAxis: { type: 'value', show: false },
series: [{
data: [6, 5, 4, 3, 3],
type: 'line', smooth: true, symbol: 'none',
lineStyle: { width: 2, color: '#faad14' },
areaStyle: { color: 'rgba(250,173,20,0.1)' }
}]
})
} }
// active registrations // active registrations
if (regChartRef.value) { if (regChartRef.value) {
const chart = echarts.init(regChartRef.value) const chart = echarts.init(regChartRef.value)
chart.setOption({ chart.setOption(defaultChartOption)
grid: { left: 0, right: 0, top: 10, bottom: 10 },
xAxis: { type: 'category', show: false, data: [1,2,3,4,5] },
yAxis: { type: 'value', show: false },
series: [{
data: [272124, 260000, 255000, 250000, 248968],
type: 'line', smooth: true, symbol: 'none',
lineStyle: { width: 2, color: '#1890ff' },
areaStyle: { color: 'rgba(24,144,255,0.1)' }
}]
})
} }
// failed registrations // failed registrations
if (failedRegChartRef.value) { if (failedRegChartRef.value) {
const chart = echarts.init(failedRegChartRef.value) const chart = echarts.init(failedRegChartRef.value)
chart.setOption({ chart.setOption(defaultChartOption)
grid: { left: 0, right: 0, top: 10, bottom: 10 },
xAxis: { type: 'category', show: false, data: [1,2,3,4,5] },
yAxis: { type: 'value', show: false },
series: [{
data: [10, 9, 8, 8, 8],
type: 'line', smooth: true, symbol: 'none',
lineStyle: { width: 2, color: '#f5222d' },
areaStyle: { color: 'rgba(245,34,45,0.1)' }
}]
})
} }
}) })
@@ -1028,6 +1094,32 @@ function calculateFailedRegistrationsChange() {
return `${changeText} last ${timeDiff}` return `${changeText} last ${timeDiff}`
} }
// 测试数据更新
function testDataUpdate() {
// console.log('测试数据更新')
// 创建模拟的后端KPI数据消息格式
const mockWebSocketMessage = {
code: 1,
data: {
data: {
'SCSCF.03': Math.floor(Math.random() * 300000) + 200000, // active registrations
'SCSCF.04': Math.floor(Math.random() * 310000) + 200000, // total registrations
'SCSCF.05': Math.floor(Math.random() * 15000) + 10000, // MO calls
'SCSCF.06': Math.floor(Math.random() * 16000) + 10000, // total calls
'SCSCF.07': Math.floor(Math.random() * 15000) + 10000, // successful calls
},
groupId: `10_IMS_${selectedImsNeId.value}`
},
msg: 'success'
}
// console.log('模拟WebSocket消息:', mockWebSocketMessage)
// 直接调用handleIMSRealtimeData函数
handleIMSRealtimeData(mockWebSocketMessage)
}
</script> </script>
<style scoped> <style scoped>