This commit is contained in:
TsMask
2025-08-07 15:49:49 +08:00
3 changed files with 80 additions and 49 deletions

View File

@@ -404,7 +404,7 @@ export default {
areaId:'The areaId value is a hexadecimal string.',
detail:'Detail',
}
},
},
dashboard: {
overview:{
title: "Core Network Dashboard",
@@ -1105,6 +1105,21 @@ export default {
"chooseShowMetrics":"Select the metric you want to display",
"chooseMetrics":"Select an indicator",
},
voiceOverView:{
"voiceTitle":"Voice Calls Dashboard",
"tips":"Data and voice statistics per minute",
"ne":"NE",
"now":"now",
"last":"last",
"calls":"Calls",
"activeCall":"active calls",
"callMOMT":"calls MO/MT",
"failedcall":"failed calls",
"registration":"Registrations",
"activeregistration":"active registrations",
"registrationsuccess":"registration success",
"failedregistration":"failed registrations total",
},
},
traceManage: {
pcap: {

View File

@@ -404,7 +404,7 @@ export default {
areaId:'areaId值是十六进制字符串',
detail:'详情',
}
},
},
dashboard: {
overview:{
title: "核心网系统看板",
@@ -1105,6 +1105,21 @@ export default {
"chooseShowMetrics":"选择需要显示的指标",
"chooseMetrics":"选择指标",
},
voiceOverView:{
"voiceTitle":"语音通话仪表盘",
"tips":"每分钟数据语音统计",
"ne":"网元",
"now":"现在",
"last":"过去",
"calls":"呼叫",
"activeCall":"主动呼叫",
"callMOMT":"呼叫 主叫接通率/被叫接通率",
"failedcall":"失败呼叫",
"registration":"注册",
"activeregistration":"主动注册",
"registrationsuccess":"注册成功率",
"failedregistration":"失败注册",
},
},
traceManage: {
pcap: {

View File

@@ -1,13 +1,13 @@
<template>
<div class="dashboard-cards">
<div style="font-size:32px; font-weight: bold; margin-bottom: 20px; text-align: center; position: relative;">
Voice Calls Dashboard
{{ t('views.perfManage.voiceOverView.voiceTitle') }}
<!-- <span class="control-tower-badge">IMS Control Tower</span>-->
</div>
<div style="margin-bottom: 24px; display: flex; align-items: center; justify-content: flex-end;">
<span style="font-size: 12px; color: #999; font-style: italic;">*Data and voice statistics per minute</span>
<span style="font-size: 12px; color: #999; font-style: italic;">*{{ t('views.perfManage.voiceOverView.tips') }}</span>
<div style="display: flex; align-items: center; margin-left: 32px;">
<label style="margin-right: 8px; font-weight: 600;">NE</label>
<label style="margin-right: 8px; font-weight: 600;">{{ t('views.perfManage.voiceOverView.ne') }}</label>
<a-select
v-model:value="selectedImsNeId"
:options="imsNeList.map(ne => ({ label: ne.neName || ne.neId, value: ne.neId }))"
@@ -21,11 +21,11 @@
/>
</div>
</div>
<div class="row-title">Calls</div>
<div class="row-title">{{ t('views.perfManage.voiceOverView.calls') }}</div>
<a-row :gutter="[16, 16]">
<a-col :xs="24" :sm="24" :lg="8">
<a-card bordered class="metric-card">
<div class="card-title">active calls <span class="main-icon phone">📞</span></div>
<div class="card-title">{{ t('views.perfManage.voiceOverView.activeCall') }} <span class="main-icon phone">📞</span></div>
<div class="card-content">
<div class="trend-chart">
<div class="mini-chart" ref="callsChartRef"></div>
@@ -61,7 +61,7 @@
<!-- </a-col>-->
<a-col :xs="24" :sm="24" :lg="8">
<a-card bordered class="metric-card">
<div class="card-title">calls MO / MT</div>
<div class="card-title">{{ t('views.perfManage.voiceOverView.callMOMT') }}</div>
<div class="card-content full-width">
<div class="metric-info" style="width:100%;text-align:center;">
<div class="metric-value" style="font-size:38px;justify-content:center;">
@@ -74,7 +74,7 @@
</a-col>
<a-col :xs="24" :sm="24" :lg="8">
<a-card bordered class="metric-card">
<div class="card-title">failed calls <span class="main-icon phone">📞</span></div>
<div class="card-title">{{ t('views.perfManage.voiceOverView.failedcall') }} <span class="main-icon phone">📞</span></div>
<div class="card-content">
<div class="trend-chart">
<div class="mini-chart" ref="failedCallsChartRef"></div>
@@ -91,11 +91,11 @@
</a-card>
</a-col>
</a-row>
<div class="row-title" style="margin-top: 48px;">Registrations</div>
<div class="row-title" style="margin-top: 48px;">{{ t('views.perfManage.voiceOverView.registration') }}</div>
<a-row :gutter="[16, 16]">
<a-col :xs="24" :sm="24" :lg="8">
<a-card bordered class="metric-card">
<div class="card-title">active registrations <span class="main-icon calendar">📅</span></div>
<div class="card-title">{{ t('views.perfManage.voiceOverView.activeregistration') }} <span class="main-icon calendar">📅</span></div>
<div class="card-content">
<div class="trend-chart">
<div class="mini-chart" ref="regChartRef"></div>
@@ -113,7 +113,7 @@
</a-col>
<a-col :xs="24" :sm="24" :lg="8">
<a-card bordered class="metric-card">
<div class="card-title">registration success</div>
<div class="card-title">{{ t('views.perfManage.voiceOverView.registrationsuccess') }}</div>
<div class="card-content full-width">
<div class="metric-info" style="width:100%;text-align:center;">
<div class="metric-value" style="font-size:38px;justify-content:center;">{{ calculateRegSuccessValue() }}%</div>
@@ -124,7 +124,7 @@
</a-col>
<a-col :xs="24" :sm="24" :lg="8">
<a-card bordered class="metric-card">
<div class="card-title">failed registrations total <span class="main-icon calendar">📅</span></div>
<div class="card-title">{{ t('views.perfManage.voiceOverView.failedregistration') }} <span class="main-icon calendar">📅</span></div>
<div class="card-content">
<div class="trend-chart">
<div class="mini-chart" ref="failedRegChartRef"></div>
@@ -154,7 +154,8 @@ import useNeListStore from '@/store/modules/ne_list';
import { WS } from '@/plugins/ws-websocket'
import { listKPIData } from '@/api/perfManage/goldTarget'
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
echarts.use([LineChart, GridComponent, CanvasRenderer])
const callsChartRef = ref<HTMLDivElement | null>(null)
@@ -473,7 +474,7 @@ function updateActiveCallsChart() {
pointer-events: none;
z-index: 10;
`
nowTimeLabel.textContent = 'now'
nowTimeLabel.textContent = t('views.perfManage.voiceOverView.now')
chartContainer.appendChild(maxLabel)
chartContainer.appendChild(latestLabel)
@@ -635,7 +636,7 @@ function updateFailedCallsChart() {
pointer-events: none;
z-index: 10;
`
nowTimeLabel.textContent = 'now'
nowTimeLabel.textContent = t('views.perfManage.voiceOverView.now')
chartContainer.appendChild(maxLabel)
chartContainer.appendChild(latestLabel)
@@ -795,7 +796,7 @@ function updateActiveRegistrationsChart() {
pointer-events: none;
z-index: 10;
`
nowTimeLabel.textContent = 'now'
nowTimeLabel.textContent = t('views.perfManage.voiceOverView.now')
chartContainer.appendChild(maxLabel)
chartContainer.appendChild(latestLabel)
@@ -957,7 +958,7 @@ function updateFailedRegistrationsChart() {
pointer-events: none;
z-index: 10;
`
nowTimeLabel.textContent = 'now'
nowTimeLabel.textContent = t('views.perfManage.voiceOverView.now')
chartContainer.appendChild(maxLabel)
chartContainer.appendChild(latestLabel)
@@ -1172,13 +1173,13 @@ function calculateMTValue() {
// 计算MO变化值完善版本
function calculateMOChange() {
if (imsRealtimeRawData.value.length < 2) return '±0.00% last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0.00% last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1187,31 +1188,31 @@ function calculateMOChange() {
const previousMO = calculateMOValueFromData(previousKpi)
// 检查MO是否有有效值
if (latestMO === '-' || previousMO === '-') return '±0.00% last 1m'
if (latestMO === '-' || previousMO === '-') return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 计算变化幅度
const change = latestMO - previousMO
// 检查是否有变化
if (change === 0) return '±0.00% last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(2)}%` : `${change.toFixed(2)}%`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 计算MT变化值完善版本
function calculateMTChange() {
if (imsRealtimeRawData.value.length < 2) return '±0.00% last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0.00% last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1220,20 +1221,20 @@ function calculateMTChange() {
const previousMT = calculateMTValueFromData(previousKpi)
// 检查MT是否有有效值
if (latestMT === '-' || previousMT === '-') return '±0.00% last 1m'
if (latestMT === '-' || previousMT === '-') return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 计算变化幅度
const change = latestMT - previousMT
// 检查是否有变化
if (change === 0) return '±0.00% last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(2)}%` : `${change.toFixed(2)}%`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 计算时间差函数
@@ -1316,13 +1317,13 @@ function calculateRegSuccessValue() {
// 计算registration success变化值
function calculateRegSuccessChange() {
if (imsRealtimeRawData.value.length < 2) return '±0.00% last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0.00% last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1331,20 +1332,20 @@ function calculateRegSuccessChange() {
const previousRegSuccess = calculateRegSuccessValueFromData(previousKpi)
// 检查registration success是否有有效值
if (latestRegSuccess === '-' || previousRegSuccess === '-') return '±0.00% last 1m'
if (latestRegSuccess === '-' || previousRegSuccess === '-') return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 计算变化幅度
const change = latestRegSuccess - previousRegSuccess
// 检查是否有变化
if (change === 0) return '±0.00% last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(2)}%` : `${change.toFixed(2)}%`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 辅助函数从数据中计算registration success值
@@ -1420,13 +1421,13 @@ function calculateActiveCallsArrow() {
// 计算active calls变化值
function calculateActiveCallsChange() {
if (imsRealtimeRawData.value.length < 2) return '±0 last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0 last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1439,14 +1440,14 @@ function calculateActiveCallsChange() {
const change = latestActiveCalls - previousActiveCalls
// 检查是否有变化
if (change === 0) return '±0 last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(0)}` : `${change.toFixed(0)}`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 计算failed calls值
@@ -1525,13 +1526,13 @@ function calculateFailedCallsArrow() {
// 计算failed calls变化值
function calculateFailedCallsChange() {
if (imsRealtimeRawData.value.length < 2) return '±0 last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0 last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1548,14 +1549,14 @@ function calculateFailedCallsChange() {
const change = latestFailedCalls - previousFailedCalls
// 检查是否有变化
if (change === 0) return '±0 last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(0)}` : `${change.toFixed(0)}`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 计算active registrations值
@@ -1624,13 +1625,13 @@ function calculateActiveRegistrationsArrow() {
// 计算active registrations变化值
function calculateActiveRegistrationsChange() {
if (imsRealtimeRawData.value.length < 2) return '±0 last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0 last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1643,14 +1644,14 @@ function calculateActiveRegistrationsChange() {
const change = latestActiveRegistrations - previousActiveRegistrations
// 检查是否有变化
if (change === 0) return '±0 last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(0)}` : `${change.toFixed(0)}`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 计算failed registrations值
@@ -1729,13 +1730,13 @@ function calculateFailedRegistrationsArrow() {
// 计算failed registrations变化值
function calculateFailedRegistrationsChange() {
if (imsRealtimeRawData.value.length < 2) return '±0 last 1m'
if (imsRealtimeRawData.value.length < 2) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
// 获取最新和上一个数据点
const latestData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 1]
const previousData = imsRealtimeRawData.value[imsRealtimeRawData.value.length - 2]
if (!latestData?.data || !previousData?.data) return '±0 last 1m'
if (!latestData?.data || !previousData?.data) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const latestKpi = latestData.data
const previousKpi = previousData.data
@@ -1752,14 +1753,14 @@ function calculateFailedRegistrationsChange() {
const change = latestFailedRegistrations - previousFailedRegistrations
// 检查是否有变化
if (change === 0) return '±0 last 1m'
if (change === 0) return '±0.00%' +t('views.perfManage.voiceOverView.last') +'1m'
const changeText = change > 0 ? `+${change.toFixed(0)}` : `${change.toFixed(0)}`
// 计算时间差
const timeDiff = calculateTimeDifference(latestData, previousData)
return `${changeText} last ${timeDiff}`
return `${changeText} ${+t('views.perfManage.voiceOverView.last')} ${timeDiff}`
}
// 测试数据更新