@@ -32,6 +32,7 @@ interface ChartDataItem {
[ kpiId : string ] : string | number ; // 动态指标
}
const tableLoading = ref ( false ) ;
const rangeLoading = ref ( false ) ;
//网元类型定义
const ALL _NE _TYPES = [ 'AMF' , 'SMF' , 'UPF' , 'MME' , 'IMS' , 'SMSC' ] as const ;
type NeType = typeof ALL _NE _TYPES [ number ] ;
@@ -47,6 +48,18 @@ echarts.use([
// WebSocket连接
const ws = ref < WS | null > ( null ) ;
//时间选择
let ranges = ref < Record < string , [ Dayjs , Dayjs ] > > ( {
[ t ( 'views.perfManage.customTarget.sixHoursAgo' ) ] : [
dayjs ( ) . subtract ( 6 , 'hours' ) ,
dayjs ( ) ,
] ,
[ t ( 'views.perfManage.customTarget.threeHoursAgo' ) ] : [
dayjs ( ) . subtract ( 3 , 'hours' ) ,
dayjs ( ) ,
] ,
[ t ( 'views.monitor.monitor.today' ) ] : [ dayjs ( ) . startOf ( 'day' ) , dayjs ( ) ] ,
} ) ;
//日期范围响应式变量
const dateRange = ref < [ string , string ] > ( [
dayjs ( ) . startOf ( 'hour' ) . valueOf ( ) . toString ( ) ,
@@ -168,8 +181,10 @@ const processChartData = (rawData: any[]) => {
}
Object . assign ( groupedData . get ( timeKey ) , item ) ;
} ) ;
// 获取当前选择的结束时间
const endTime = dateRange . value [ 1 ] ;
return Array . from ( groupedData . values ( ) )
const processedData = Array . from ( groupedData . values ( ) )
. sort ( ( a , b ) => Number ( a . timeGroup ) - Number ( b . timeGroup ) )
. map ( item => { //转换成图表需要的格式
const dataItem : ChartDataItem = { date : item . timeGroup . toString ( ) } ;
@@ -178,6 +193,17 @@ const processChartData = (rawData: any[]) => {
} ) ;
return dataItem ;
} ) ;
// 如果有数据,且最后一个数据点的时间小于选择的结束时间
if ( processedData . length > 0 && Number ( processedData [ processedData . length - 1 ] . date ) < Number ( endTime ) ) {
// 添加一个结束时间点, 所有指标值设为0
const endDataPoint : ChartDataItem = { date : endTime } ;
selectedKPIs . value . forEach ( kpiId => {
endDataPoint [ kpiId ] = 0 ;
} ) ;
processedData . push ( endDataPoint ) ;
}
return processedData ;
} ;
// 获取图表数据方法
const fetchChartData = async ( ) => {
@@ -185,6 +211,8 @@ const fetchChartData = async () => {
updateChart ( ) ;
return ;
}
tableLoading . value = true ;
rangeLoading . value = true ;
try {
const [ startTime , endTime ] = dateRange . value ;
if ( ! startTime || ! endTime ) {
@@ -226,6 +254,9 @@ const fetchChartData = async () => {
} catch ( error ) {
console . error ( 'Failed to fetch chart data:' , error ) ;
message . error ( t ( 'common.getInfoFail' ) ) ;
} finally {
tableLoading . value = false ;
rangeLoading . value = false ;
}
} ;
@@ -250,6 +281,26 @@ const updateChart = () => {
const color = kpiColors . get ( kpiId ) || generateColorRGBA ( ) ;
kpiColors . set ( kpiId , color ) ;
// 获取数据数组
const data = chartData . value . map ( ( item , index ) => {
const value = item [ kpiId ] || 0 ;
// 如果是最后一个数据点,添加特殊样式
if ( index === chartData . value . length - 1 ) {
return {
value ,
symbolSize : 12 , // 更大的节点
itemStyle : {
color , // 保持与线条相同的颜色
borderWidth : 3 , // 添加边框
borderColor : color , // 边框颜色
shadowBlur : 10 , // 添加阴影效果
shadowColor : color ,
} ,
} ;
}
return value ;
} ) ;
return {
name : kpi . title ,
type : 'line' ,
@@ -266,6 +317,27 @@ const updateChart = () => {
} ,
tooltip : {
trigger : 'axis' ,
position : function ( point : number [ ] , params : any , dom : HTMLElement , rect : any , size : { viewSize : number [ ] , contentSize : number [ ] } ) {
const [ x , y ] = point ;
const [ viewWidth ] = size . viewSize ;
const [ tooltipWidth , tooltipHeight ] = size . contentSize ;
// 距离右侧的距离
const rightSpace = viewWidth - x ;
// 计算垂直方向的居中位置
// 将 tooltip 的中心点对齐到鼠标位置
const verticalOffset = - tooltipHeight / 2 ;
// 如果右侧空间不足以显示tooltip( 假设需要20px的安全距离)
if ( rightSpace < tooltipWidth + 20 ) {
// 向左显示,垂直居中
return [ x - tooltipWidth - 10 , y + verticalOffset ] ;
}
// 默认向右显示,垂直居中
return [ x + 10 , y + verticalOffset ] ;
} ,
} ,
legend : {
data : selectedKPIs . value . map ( kpiId =>
@@ -309,6 +381,29 @@ const updateChart = () => {
dayjs ( Number ( item . date ) ) . format ( 'YYYY-MM-DD HH:mm:ss' )
) ,
//设置坐标轴刻度标签的样式
axisLabel : {
interval : function ( index : number , value : string ) {
const currentTime = dayjs ( value ) ;
const minutes = currentTime . minute ( ) ;
const seconds = currentTime . second ( ) ;
// 始终显示小时的起始和结束时间点
if ( ( minutes === 0 && seconds === 0 ) ||
( minutes === 59 && seconds === 59 ) ) {
return true ;
}
// 对于中间的时间点,使用 auto 的逻辑
if ( index % Math . ceil ( chartData . value . length / 6 ) === 0 ) {
return true ;
}
return false ;
} ,
rotate : 0 ,
align : 'center' ,
hideOverlap : true
}
} ,
yAxis : {
// y轴配置
@@ -446,7 +541,7 @@ const updateChartData = (newData: ChartDataItem) => {
return ;
}
chartData . value . push ( newData ) ;
if ( chartData . value . length > 5 0) { //100改为50
if ( chartData . value . length > 10 0) { //100改为50
chartData . value . shift ( ) ; //大于100条时删除最早的数据
}
//使用try-catch包裹图表更新逻辑
@@ -590,6 +685,8 @@ const updateChartLegendSelect = (selectedKpiId?: string) => {
format = "YYYY-MM-DD HH:mm:ss"
:value-format = "'x'"
:disabled = "isRealtime"
:ranges = "ranges"
:loading = "rangeLoading"
@change ="handleDateChange"
/ >
< a-form-item