Merge branch 'main' of http://192.168.2.166:3180/OMC/ems_frontend_vue3
This commit is contained in:
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS"
|
|||||||
VITE_APP_CODE = "CN EMS"
|
VITE_APP_CODE = "CN EMS"
|
||||||
|
|
||||||
# 应用版本
|
# 应用版本
|
||||||
VITE_APP_VERSION = "2.2401.5"
|
VITE_APP_VERSION = "2.2401.6"
|
||||||
|
|
||||||
# 接口基础URL地址-不带/后缀
|
# 接口基础URL地址-不带/后缀
|
||||||
VITE_API_BASE_URL = "/omc-api"
|
VITE_API_BASE_URL = "/omc-api"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS"
|
|||||||
VITE_APP_CODE = "CN EMS"
|
VITE_APP_CODE = "CN EMS"
|
||||||
|
|
||||||
# 应用版本
|
# 应用版本
|
||||||
VITE_APP_VERSION = "2.240126.5"
|
VITE_APP_VERSION = "2.240130.6"
|
||||||
|
|
||||||
# 接口基础URL地址-不带/后缀
|
# 接口基础URL地址-不带/后缀
|
||||||
VITE_API_BASE_URL = "/omc-api"
|
VITE_API_BASE_URL = "/omc-api"
|
||||||
|
|||||||
@@ -288,14 +288,13 @@ export async function exportAll(query: Record<string, any>) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 展示页全部告警
|
* 展示页全部告警
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns bolb
|
* @returns bolb
|
||||||
*/
|
*/
|
||||||
export async function mainGet() {
|
export async function origGet() {
|
||||||
let totalSQL = `select count(*) as value,orig_severity as name from alarm group by orig_severity`;
|
let totalSQL = `select count(*) as value,orig_severity as name from alarm group by orig_severity`;
|
||||||
|
|
||||||
// 发起请求
|
// 发起请求
|
||||||
const result = await request({
|
const result = await request({
|
||||||
@@ -305,6 +304,43 @@ export async function mainGet() {
|
|||||||
SQL: totalSQL,
|
SQL: totalSQL,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
////
|
||||||
|
|
||||||
|
// 解析数据
|
||||||
|
if (result.code === RESULT_CODE_SUCCESS) {
|
||||||
|
const itemData = result.data.data;
|
||||||
|
if (Array.isArray(itemData)) {
|
||||||
|
const v = itemData[0]['alarm'];
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
result.data = v;
|
||||||
|
}
|
||||||
|
if (v === null) {
|
||||||
|
result.data = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询前三的网元
|
||||||
|
* @param filterFlag 查询参数
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export async function top3Sel(filterFlag?: string) {
|
||||||
|
let filter = ` WHERE orig_severity='${filterFlag}'`;
|
||||||
|
if (!filterFlag) filter = '';
|
||||||
|
|
||||||
|
let top3SQL = `select count(*) as value,ne_type as name from alarm ${filter} group by ne_type ORDER BY value desc limit 0,3 `;
|
||||||
|
|
||||||
|
// 发起请求
|
||||||
|
const result = await request({
|
||||||
|
url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
SQL: top3SQL,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// 解析数据
|
// 解析数据
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
if (result.code === RESULT_CODE_SUCCESS) {
|
||||||
@@ -314,7 +350,10 @@ export async function mainGet() {
|
|||||||
if (Array.isArray(v)) {
|
if (Array.isArray(v)) {
|
||||||
result.data = v;
|
result.data = v;
|
||||||
}
|
}
|
||||||
|
if (v === null) {
|
||||||
|
result.data = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,392 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div ref="chartGraphG6Dom" :style="{ height: height, width: width }"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { nextTick, watch, onMounted, onBeforeUnmount, ref } from 'vue';
|
|
||||||
import { Graph } from '@antv/g6';
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
/**
|
|
||||||
* 图表主题
|
|
||||||
*
|
|
||||||
* 'dark' | 'light'
|
|
||||||
*/
|
|
||||||
theme: {
|
|
||||||
type: String,
|
|
||||||
default: 'light', // 'dark' | 'light'
|
|
||||||
},
|
|
||||||
/**宽度,默认100% */
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '100%',
|
|
||||||
},
|
|
||||||
/**高度 */
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '500px',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const chartGraphG6Dom = ref<HTMLElement | undefined>(undefined);
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
nodes: [
|
|
||||||
// 0 基站
|
|
||||||
{
|
|
||||||
id: '0',
|
|
||||||
x: 50,
|
|
||||||
y: 150,
|
|
||||||
size: 48,
|
|
||||||
type: 'circle',
|
|
||||||
label: '基站',
|
|
||||||
labelCfg: {
|
|
||||||
position: 'bottom',
|
|
||||||
offset: 10,
|
|
||||||
style: {
|
|
||||||
fill: '#333',
|
|
||||||
stroke: '#fff',
|
|
||||||
lineWidth: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: '#9EC9FF',
|
|
||||||
stroke: '#5B8FF9',
|
|
||||||
lineWidth: 2,
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
show: true,
|
|
||||||
// 可更换为其他图片地址
|
|
||||||
img: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 1 DM
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
x: 450,
|
|
||||||
y: 450,
|
|
||||||
label: 'DM',
|
|
||||||
labelCfg: {
|
|
||||||
position: 'center',
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: '#00b050',
|
|
||||||
stroke: '#00b050',
|
|
||||||
lineWidth: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 2 O&M
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
x: 50,
|
|
||||||
y: 450,
|
|
||||||
label: 'O&M',
|
|
||||||
},
|
|
||||||
// 100 EMS
|
|
||||||
{
|
|
||||||
id: '100',
|
|
||||||
label: 'EMS',
|
|
||||||
comboId: 'combo-ems',
|
|
||||||
x: 300,
|
|
||||||
y: 450,
|
|
||||||
},
|
|
||||||
// 190 UPF
|
|
||||||
{
|
|
||||||
id: '190',
|
|
||||||
comboId: 'combo-upf',
|
|
||||||
x: 300,
|
|
||||||
y: 350,
|
|
||||||
label: 'UPF',
|
|
||||||
labelCfg: {
|
|
||||||
position: 'center',
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: '#d580ff',
|
|
||||||
stroke: '#d580ff',
|
|
||||||
lineWidth: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// EP-IMS
|
|
||||||
{
|
|
||||||
id: '110',
|
|
||||||
comboId: 'combo-ims',
|
|
||||||
x: 600,
|
|
||||||
y: 350,
|
|
||||||
label: 'IMS',
|
|
||||||
labelCfg: {
|
|
||||||
position: 'center',
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: '#ed7d31',
|
|
||||||
stroke: '#ed7d31',
|
|
||||||
lineWidth: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 5GC控制面
|
|
||||||
{
|
|
||||||
id: '170',
|
|
||||||
label: 'NSSF',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 300,
|
|
||||||
y: 50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '130',
|
|
||||||
label: 'AUSF',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 450,
|
|
||||||
y: 50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '140',
|
|
||||||
label: 'UDM',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 600,
|
|
||||||
y: 50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '120',
|
|
||||||
label: 'AMF',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 300,
|
|
||||||
y: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '180',
|
|
||||||
label: 'NRF',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 450,
|
|
||||||
y: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '150',
|
|
||||||
label: 'SMF',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 300,
|
|
||||||
y: 250,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '160',
|
|
||||||
label: 'PCF',
|
|
||||||
comboId: 'combo-5gc',
|
|
||||||
x: 700,
|
|
||||||
y: 250,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
edges: [
|
|
||||||
{
|
|
||||||
id: '0-5gc',
|
|
||||||
source: '0',
|
|
||||||
target: 'combo-5gc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '0-upf',
|
|
||||||
source: '0',
|
|
||||||
target: 'combo-upf',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'upf-1',
|
|
||||||
source: 'combo-upf',
|
|
||||||
target: '1',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 'ems-2',
|
|
||||||
source: 'combo-ems',
|
|
||||||
target: '2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '170-120',
|
|
||||||
source: '170',
|
|
||||||
target: '120',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '130-120',
|
|
||||||
source: '130',
|
|
||||||
target: '120',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '140-120',
|
|
||||||
source: '140',
|
|
||||||
target: '120',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '140-180',
|
|
||||||
source: '140',
|
|
||||||
target: '180',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '120-180',
|
|
||||||
source: '120',
|
|
||||||
target: '180',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '130-180',
|
|
||||||
source: '130',
|
|
||||||
target: '180',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '140-150',
|
|
||||||
source: '140',
|
|
||||||
target: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '140-110',
|
|
||||||
source: '140',
|
|
||||||
target: '110',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '120-150',
|
|
||||||
source: '120',
|
|
||||||
target: '150',
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '150-180',
|
|
||||||
source: '150',
|
|
||||||
target: '180',
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '150-160',
|
|
||||||
source: '150',
|
|
||||||
target: '160',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '160-120',
|
|
||||||
source: '160',
|
|
||||||
target: '120',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '160-180',
|
|
||||||
source: '160',
|
|
||||||
target: '180',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '160-110',
|
|
||||||
source: '160',
|
|
||||||
target: '110',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: '150-190',
|
|
||||||
source: '150',
|
|
||||||
target: '190',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 'upf-ims',
|
|
||||||
source: 'combo-upf',
|
|
||||||
target: 'combo-ims',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ems-5gc',
|
|
||||||
source: 'combo-ems',
|
|
||||||
target: 'combo-5gc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ems-upf',
|
|
||||||
source: 'combo-ems',
|
|
||||||
target: 'combo-upf',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ems-ims',
|
|
||||||
source: 'combo-ems',
|
|
||||||
target: 'combo-ims',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
combos: [
|
|
||||||
{
|
|
||||||
id: 'combo-5gc',
|
|
||||||
data: {
|
|
||||||
text: '5GC控制面',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'combo-upf',
|
|
||||||
data: {
|
|
||||||
keyShape: {
|
|
||||||
opacity: 0.8,
|
|
||||||
padding: [20, 20, 20, 20],
|
|
||||||
radius: 4,
|
|
||||||
lineWidth: 1,
|
|
||||||
stroke: '#d580ff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'combo-ims',
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'combo-ems',
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
let graph: any = null;
|
|
||||||
|
|
||||||
/**初始化渲染图表 */
|
|
||||||
function initChart() {
|
|
||||||
if (!chartGraphG6Dom.value) return;
|
|
||||||
console.log(chartGraphG6Dom.value.clientWidth);
|
|
||||||
console.log(chartGraphG6Dom.value.clientHeight);
|
|
||||||
graph = new Graph({
|
|
||||||
container: chartGraphG6Dom.value,
|
|
||||||
height: chartGraphG6Dom.value.clientHeight,
|
|
||||||
width: chartGraphG6Dom.value.clientWidth,
|
|
||||||
fitCenter: true,
|
|
||||||
modes: {
|
|
||||||
default: ['drag-canvas', 'zoom-canvas', 'drag-node'], // 允许拖拽画布、放缩画布、拖拽节点
|
|
||||||
},
|
|
||||||
// 全局节点 矩形
|
|
||||||
defaultNode: {
|
|
||||||
type: 'rect',
|
|
||||||
size: [80, 40],
|
|
||||||
style: {
|
|
||||||
fill: '#fff',
|
|
||||||
lineWidth: 1,
|
|
||||||
radius: 8,
|
|
||||||
},
|
|
||||||
labelCfg: {},
|
|
||||||
},
|
|
||||||
// 全局边 三次贝塞尔曲线
|
|
||||||
defaultEdge: {
|
|
||||||
type: 'polyline',
|
|
||||||
style: {
|
|
||||||
offset: 20, // 拐弯处距离节点最小距离
|
|
||||||
radius: 4, // 拐弯处的圆角弧度,若不设置则为直角
|
|
||||||
lineWidth: 1,
|
|
||||||
stroke: '#87e8de',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 全局框节点 矩形
|
|
||||||
defaultCombo: {
|
|
||||||
type: 'rect', // Combo 类型
|
|
||||||
size: [40, 40],
|
|
||||||
// ... 其他配置
|
|
||||||
style: {
|
|
||||||
lineWidth: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
graph.data(data); // 加载数据
|
|
||||||
graph.render(); // 渲染
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
nextTick(() => {
|
|
||||||
initChart();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
|
||||||
<div ref="chartDom" :style="{ height: height, width: width }"></div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, watch, onMounted, onBeforeUnmount, ref } from 'vue';
|
import { nextTick, watch, onMounted, onBeforeUnmount, ref, markRaw } from 'vue';
|
||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
import {
|
import {
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
@@ -121,28 +118,24 @@ let newChart: echarts.ECharts;
|
|||||||
const chartDom = ref<HTMLElement | undefined>(undefined);
|
const chartDom = ref<HTMLElement | undefined>(undefined);
|
||||||
|
|
||||||
/**初始化渲染图表 */
|
/**初始化渲染图表 */
|
||||||
function initChart() {
|
function handleRanderChart(container: HTMLElement | undefined) {
|
||||||
|
if (!container || !props.option.yDatas) return;
|
||||||
if (!newChart) {
|
if (!newChart) {
|
||||||
newChart = echarts.init(chartDom.value);
|
newChart = markRaw(echarts.init(container, props.theme));
|
||||||
}
|
}
|
||||||
|
|
||||||
const series: any = [];
|
const series: any = [];
|
||||||
const yDatasLen = props.option?.yDatas?.length || 0;
|
const yDatasLen = props.option.yDatas.length;
|
||||||
if (yDatasLen > 0) {
|
props.option.yDatas.forEach((item: any, index: number) => {
|
||||||
props.option?.yDatas.forEach((item: any, index: number) => {
|
series.push({
|
||||||
series.push({
|
name: item?.name,
|
||||||
name: item?.name,
|
type: 'line',
|
||||||
type: 'line',
|
areaStyle: seriesStyle[index % yDatasLen],
|
||||||
areaStyle: seriesStyle[index % yDatasLen],
|
data: item?.data,
|
||||||
data: item?.data,
|
showSymbol: false,
|
||||||
showSymbol: false,
|
yAxisIndex: item.yAxisIndex ? 1 : null,
|
||||||
yAxisIndex: item.yAxisIndex ? 1 : null,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
console.error('components ChartLine echarts yDatas error!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 右侧y轴辅助线
|
// 右侧y轴辅助线
|
||||||
const yAxis: any = [];
|
const yAxis: any = [];
|
||||||
@@ -229,12 +222,16 @@ function initChart() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 渲染数据
|
// 渲染数据
|
||||||
newChart.setOption(option, true);
|
option && newChart.setOption(option, true);
|
||||||
}
|
|
||||||
|
|
||||||
/**重置图表尺寸 */
|
// 创建 ResizeObserver 实例
|
||||||
function changeChartSize() {
|
var observer = new ResizeObserver(entries => {
|
||||||
newChart.resize();
|
if (newChart) {
|
||||||
|
newChart.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 监听元素大小变化
|
||||||
|
observer.observe(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -242,7 +239,7 @@ watch(
|
|||||||
val => {
|
val => {
|
||||||
if (val) {
|
if (val) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
initChart();
|
handleRanderChart(chartDom.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,15 +247,17 @@ watch(
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
initChart();
|
handleRanderChart(chartDom.value);
|
||||||
window.addEventListener('resize', changeChartSize);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
newChart.dispose();
|
newChart.dispose();
|
||||||
window.removeEventListener('resize', changeChartSize);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="chartDom" :style="{ height: height, width: width }"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|||||||
@@ -509,27 +509,30 @@ export default {
|
|||||||
alarmType: {
|
alarmType: {
|
||||||
title: "Alarm Statistics",
|
title: "Alarm Statistics",
|
||||||
},
|
},
|
||||||
|
alarmTypeBar:{
|
||||||
|
alarmSum:'Alarm Statistics',
|
||||||
|
topTitle:"Alarm-TOP 3 ",
|
||||||
|
},
|
||||||
resources: {
|
resources: {
|
||||||
title: "Resource Situation",
|
title: "Resource Summary",
|
||||||
sysMem: "Memory",
|
sysMem: "Memory",
|
||||||
sysCpu: "CPU",
|
sysCpu: "CPU",
|
||||||
neCpu: "NE CPU",
|
neCpu: "NE CPU",
|
||||||
},
|
},
|
||||||
topology: {
|
topology: {
|
||||||
title: "Network Topology",
|
title: "Network Topology",
|
||||||
|
normal: "Normal",
|
||||||
|
abnormal: "AbNormal",
|
||||||
},
|
},
|
||||||
cdrEvent: {
|
userActivity: {
|
||||||
title: "CDR User Activity",
|
title: "User Activity",
|
||||||
id: "Serial",
|
|
||||||
type: "Type",
|
type: "Type",
|
||||||
msg: "Info",
|
duration: "Duration",
|
||||||
|
caller: "Caller",
|
||||||
|
called: "Called",
|
||||||
|
result: "Result",
|
||||||
|
time: "Time",
|
||||||
},
|
},
|
||||||
ueEvent: {
|
|
||||||
title: "UE User Activity",
|
|
||||||
id: "IMSI",
|
|
||||||
type: "Type",
|
|
||||||
msg: "Info",
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
neUser: {
|
neUser: {
|
||||||
|
|||||||
@@ -509,6 +509,10 @@ export default {
|
|||||||
alarmType: {
|
alarmType: {
|
||||||
title: "告警统计",
|
title: "告警统计",
|
||||||
},
|
},
|
||||||
|
alarmTypeBar:{
|
||||||
|
alarmSum:'告警统计',
|
||||||
|
topTitle:"告警总数TOP3",
|
||||||
|
},
|
||||||
resources: {
|
resources: {
|
||||||
title: "资源情况",
|
title: "资源情况",
|
||||||
sysMem: "系统内存",
|
sysMem: "系统内存",
|
||||||
@@ -517,19 +521,18 @@ export default {
|
|||||||
},
|
},
|
||||||
topology: {
|
topology: {
|
||||||
title: "网络拓扑",
|
title: "网络拓扑",
|
||||||
|
normal: "正常",
|
||||||
|
abnormal: "异常",
|
||||||
},
|
},
|
||||||
cdrEvent: {
|
userActivity: {
|
||||||
title: "CDR用户活动",
|
title: "用户活动",
|
||||||
id: "编号",
|
|
||||||
type: "类型",
|
type: "类型",
|
||||||
msg: "信息",
|
duration: "时长",
|
||||||
|
caller: "主叫",
|
||||||
|
called: "被叫",
|
||||||
|
result: "结果",
|
||||||
|
time: "时间",
|
||||||
},
|
},
|
||||||
ueEvent: {
|
|
||||||
title: "UE用户活动",
|
|
||||||
id: "IMSI",
|
|
||||||
type: "类型",
|
|
||||||
msg: "信息",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
neUser: {
|
neUser: {
|
||||||
|
|||||||
@@ -122,26 +122,6 @@ const useUserStore = defineStore('user', {
|
|||||||
this.phonenumber = user.phonenumber;
|
this.phonenumber = user.phonenumber;
|
||||||
this.email = user.email;
|
this.email = user.email;
|
||||||
this.sex = user.sex;
|
this.sex = user.sex;
|
||||||
// 额外信息
|
|
||||||
try {
|
|
||||||
this.profile = JSON.parse(user.profile);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
this.profile = {
|
|
||||||
color: {
|
|
||||||
critical: '#e8994a',
|
|
||||||
event: '#c5d2dc',
|
|
||||||
major: '#494040',
|
|
||||||
minor: '#5f70a8',
|
|
||||||
sound: 'custom',
|
|
||||||
warning: '#b9e1dd',
|
|
||||||
},
|
|
||||||
custom: 'hrxz.com-exz2s3uxhc47391.mp3',
|
|
||||||
pwdErrCount: 0,
|
|
||||||
pwdErrTime: 0,
|
|
||||||
sound: 'custom',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证返回的roles是否是一个非空数组
|
// 验证返回的roles是否是一个非空数组
|
||||||
if (Array.isArray(roles) && roles.length > 0) {
|
if (Array.isArray(roles) && roles.length > 0) {
|
||||||
|
|||||||
@@ -73,6 +73,29 @@ export function diffValue(
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化秒值为 ?h?m?s
|
||||||
|
* @param seconds 2558 秒
|
||||||
|
* @returns 1h42m38s
|
||||||
|
*/
|
||||||
|
export function parseDuration(seconds: number | string) {
|
||||||
|
seconds = Number(seconds) || 0;
|
||||||
|
const duration = dayjs().startOf('day').subtract(seconds, 'seconds');
|
||||||
|
const secondsLeft = duration.format('s');
|
||||||
|
const minutes = duration.format('m');
|
||||||
|
const hours = duration.format('H');
|
||||||
|
if (+hours > 0) {
|
||||||
|
return `${hours}h${minutes}m${secondsLeft}s`;
|
||||||
|
}
|
||||||
|
if (+minutes > 0) {
|
||||||
|
return `${minutes}m${secondsLeft}s`;
|
||||||
|
}
|
||||||
|
if (+secondsLeft > 0) {
|
||||||
|
return `${secondsLeft}s`;
|
||||||
|
}
|
||||||
|
return `${seconds}s`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式时间不带年份
|
* 格式时间不带年份
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { markRaw, onMounted, ref } from 'vue';
|
import { markRaw, onMounted, ref } from 'vue';
|
||||||
import { mainGet } from '@/api/faultManage/actAlarm';
|
import { origGet } from '@/api/faultManage/actAlarm';
|
||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
import {
|
import {
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
|
|||||||
@@ -3,13 +3,15 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { markRaw, onMounted, ref } from 'vue';
|
import { markRaw, onMounted, ref } from 'vue';
|
||||||
import { mainGet } from '@/api/faultManage/actAlarm';
|
import { origGet, top3Sel } from '@/api/faultManage/actAlarm';
|
||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
import {
|
import {
|
||||||
|
DatasetComponent,
|
||||||
GridComponent,
|
GridComponent,
|
||||||
|
TransformComponent,
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
LegendComponent, //
|
LegendComponent,
|
||||||
} from 'echarts/components';
|
} from 'echarts/components';
|
||||||
import { BarChart, PieChart } from 'echarts/charts';
|
import { BarChart, PieChart } from 'echarts/charts';
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
@@ -17,21 +19,26 @@ import { LabelLayout } from 'echarts/features';
|
|||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
echarts.use([
|
echarts.use([
|
||||||
GridComponent,
|
|
||||||
BarChart,
|
|
||||||
CanvasRenderer,
|
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
GridComponent,
|
|
||||||
LegendComponent,
|
|
||||||
BarChart,
|
|
||||||
CanvasRenderer,
|
|
||||||
TooltipComponent,
|
|
||||||
LegendComponent,
|
LegendComponent,
|
||||||
PieChart,
|
PieChart,
|
||||||
CanvasRenderer,
|
CanvasRenderer,
|
||||||
LabelLayout,
|
LabelLayout,
|
||||||
|
DatasetComponent,
|
||||||
|
GridComponent,
|
||||||
|
TransformComponent,
|
||||||
|
BarChart,
|
||||||
|
CanvasRenderer,
|
||||||
|
GridComponent,
|
||||||
|
BarChart,
|
||||||
|
CanvasRenderer,
|
||||||
|
GridComponent,
|
||||||
|
BarChart,
|
||||||
|
CanvasRenderer,
|
||||||
|
CanvasRenderer,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**图DOM节点实例对象 */
|
/**图DOM节点实例对象 */
|
||||||
@@ -40,269 +47,171 @@ const alarmTypeBar = ref<HTMLElement | undefined>(undefined);
|
|||||||
/**图实例对象 */
|
/**图实例对象 */
|
||||||
const alarmTypeBarChart = ref<any>(null);
|
const alarmTypeBarChart = ref<any>(null);
|
||||||
|
|
||||||
// 将现有数据补全为期望的格式
|
//
|
||||||
function completeData(existingData: any, expectedData: any) {
|
|
||||||
const result = expectedData.map((item: any) => {
|
|
||||||
const found = existingData.find(
|
|
||||||
(existingItem: any) => existingItem.name === item.name
|
|
||||||
);
|
|
||||||
if (found) return found;
|
|
||||||
else {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// result.forEach((item: any) => {
|
|
||||||
// item.title = t('views.index.' + item.name);
|
|
||||||
// });//
|
|
||||||
console.log(result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
var wantArr = [
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
name: 'Critical',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
name: 'Major',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
name: 'Minor',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
name: 'Warning',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
name: 'Event',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function initPicture() {
|
function initPicture() {
|
||||||
mainGet().then((res: any) => {
|
Promise.allSettled([origGet(), top3Sel()]).then(resArr => {
|
||||||
const colorList = ['##ae273e', '#ffb854', '#ffc069', '#99ccff', '#49a9ee'];
|
let barArr: any = [
|
||||||
|
{ name: 'AMF', value: 0 },
|
||||||
|
{ name: 'UDM', value: 0 },
|
||||||
|
{ name: 'SMF', value: 0 },
|
||||||
|
];
|
||||||
|
let pieArr: any = [];
|
||||||
|
|
||||||
let yData: any[] = [];
|
if (resArr[0].status === 'fulfilled') {
|
||||||
let realData = completeData(res.data, wantArr).sort(function (
|
resArr[0].value.data.map((item: any) => {
|
||||||
a: any,
|
item.name = item.name + ':' + item.value;
|
||||||
b: any
|
pieArr.push(item);
|
||||||
) {
|
});
|
||||||
return a.value - b.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0; i < realData.length; i++) {
|
|
||||||
yData.push(realData[i].name);
|
|
||||||
realData[i].name = t('views.index.' + realData[i].name);
|
|
||||||
// realData[i].itemStyle = {
|
|
||||||
// color: colorList[i],
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
// const optionData: any = {
|
if (resArr[1].status === 'fulfilled') {
|
||||||
// tooltip: {
|
if (resArr[1].value.data.length) barArr = [];
|
||||||
// trigger: 'item',
|
resArr[1].value.data.map((item: any) => {
|
||||||
// },
|
barArr.push(item);
|
||||||
|
});
|
||||||
// visualMap: {
|
}
|
||||||
// show: false,
|
console.log(pieArr);
|
||||||
// min: 80,
|
|
||||||
// max: 600,
|
|
||||||
// inRange: {
|
|
||||||
// colorLightness: [0, 1],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// series: [
|
|
||||||
// {
|
|
||||||
// name: 'Access From',
|
|
||||||
// type: 'pie',
|
|
||||||
// radius: '75%',
|
|
||||||
// center: ['50%', '48%'],
|
|
||||||
// data: realData,
|
|
||||||
// roseType: 'radius',
|
|
||||||
// label: {
|
|
||||||
// formatter: '{c|{c}}\n{b|{b}}',
|
|
||||||
// distance: 80,
|
|
||||||
// rich: {
|
|
||||||
// c: {
|
|
||||||
// color: 'rgb(241,246,104)',
|
|
||||||
// fontSize: 18,
|
|
||||||
// fontWeight: 'bold',
|
|
||||||
// lineHeight: 5,
|
|
||||||
// },
|
|
||||||
// b: {
|
|
||||||
// color: 'rgb(98,137,169)',
|
|
||||||
// fontSize: 15,
|
|
||||||
// height: 30,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// labelLine: {
|
|
||||||
// lineStyle: {
|
|
||||||
// color: 'rgba(255, 255, 255, 0.3)',
|
|
||||||
// },
|
|
||||||
// smooth: 0.2,
|
|
||||||
// length: 10,
|
|
||||||
// length2: 80,
|
|
||||||
// },
|
|
||||||
// itemStyle: {
|
|
||||||
// shadowColor: 'rgba(0, 0, 0, 0.8)',
|
|
||||||
// shadowBlur: 50,
|
|
||||||
// },
|
|
||||||
|
|
||||||
// animationType: 'scale',
|
|
||||||
// animationEasing: 'elasticOut',
|
|
||||||
// animationDelay: function (idx: any) {
|
|
||||||
// return Math.random() * 200;
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// };
|
|
||||||
const optionData: any = {
|
const optionData: any = {
|
||||||
color: ['#EAEA26', '#906BF9', '#FE5656', '#01E17E', '#3DD1F9'],
|
title: [
|
||||||
|
{
|
||||||
|
text: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t('views.dashboard.overview.alarmTypeBar.topTitle'),
|
||||||
|
textStyle: {
|
||||||
|
color: '#63C0FA',
|
||||||
|
fontSize: '14',
|
||||||
|
fontFamily: 'PingFang',
|
||||||
|
fontWeight: '400',
|
||||||
|
},
|
||||||
|
top: '210',
|
||||||
|
left: '4%',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
grid: {
|
grid: [
|
||||||
left: -100,
|
{
|
||||||
top: 50,
|
top: '55%',
|
||||||
bottom: 10,
|
left: '15%',
|
||||||
right: 10,
|
right: '25%',
|
||||||
containLabel: true,
|
bottom: '3%',
|
||||||
},
|
},
|
||||||
tooltip: {
|
],
|
||||||
trigger: 'item',
|
|
||||||
formatter: '{b} : {c} ({d}%)',
|
|
||||||
},
|
|
||||||
legend: {
|
legend: {
|
||||||
type: 'scroll',
|
orient: 'vertical',
|
||||||
orient: 'vartical',
|
left: '65%',
|
||||||
// x: "right",
|
right: 'right',
|
||||||
top: 'center',
|
top: '10%',
|
||||||
right: '15',
|
data: pieArr.map((item: any) => item.name), //label数组
|
||||||
// bottom: "0%",
|
|
||||||
itemWidth: 16,
|
|
||||||
itemHeight: 8,
|
|
||||||
itemGap: 16,
|
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#A3E2F4',
|
color: '#A7D6F4', // 设置图例文字颜色
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 0,
|
|
||||||
},
|
|
||||||
data: yData,
|
|
||||||
},
|
|
||||||
polar: {},
|
|
||||||
angleAxis: {
|
|
||||||
interval: 1,
|
|
||||||
type: 'category',
|
|
||||||
data: [],
|
|
||||||
z: 10,
|
|
||||||
axisLine: {
|
|
||||||
show: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#0B4A6B',
|
|
||||||
width: 1,
|
|
||||||
type: 'solid',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
interval: 0,
|
|
||||||
show: true,
|
|
||||||
color: '#0B4A6B',
|
|
||||||
margin: 8,
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
radiusAxis: {
|
// 饼图设置
|
||||||
min: 40,
|
color: ['#FFAE57', '#FF7853', '#EA5151', '#CC3F57', '#9A2555'],
|
||||||
max: 120,
|
// color: ['#FFAE57', '#FFA500', '#FFAE57', '#1E90FF', '#1E90FF'], //红橙黄蓝绿 为告警级别配色 以严重性依次往下!
|
||||||
interval: 20,
|
|
||||||
axisLine: {
|
|
||||||
show: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#0B3E5E',
|
|
||||||
width: 1,
|
|
||||||
type: 'solid',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
formatter: '{value} %',
|
|
||||||
show: false,
|
|
||||||
padding: [0, 0, 20, 0],
|
|
||||||
color: '#0B3E5E',
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#0B3E5E',
|
|
||||||
width: 2,
|
|
||||||
type: 'solid',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
calculable: true,
|
|
||||||
series: [
|
series: [
|
||||||
|
//饼图:
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['5%', '10%'],
|
radius: '35%',
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
labelLine: {
|
labelLine: {
|
||||||
show: false,
|
show: false,
|
||||||
length: 30,
|
|
||||||
length2: 55,
|
|
||||||
},
|
},
|
||||||
data: [
|
center: ['40%', '25%'],
|
||||||
{
|
data: pieArr.sort((a: any, b: any) => {
|
||||||
name: '',
|
return a.value - b.value;
|
||||||
value: 0,
|
}),
|
||||||
itemStyle: {
|
lineStyle: 'none', // 设置线条样式为无,即可去掉线条
|
||||||
color: '#0B4A6B',
|
zlevel: 2, // 设置zlevel为1,使得柱状图在下层显示
|
||||||
},
|
itemStyle: {
|
||||||
},
|
shadowBlur: 10,
|
||||||
],
|
shadowOffsetX: 0,
|
||||||
},
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
{
|
// color: function (params: any) {
|
||||||
type: 'pie',
|
// console.log(params);
|
||||||
radius: ['90%', '95%'],
|
// // 设置每个数据项的颜色
|
||||||
labelLine: {
|
// var colorList = {
|
||||||
show: false,
|
// '#FFAE57',
|
||||||
length: 30,
|
// '#FF7853',
|
||||||
length2: 55,
|
// '#EA5151',
|
||||||
|
// '#CC3F57',
|
||||||
|
// '#9A2555',
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ;
|
||||||
|
// return colorList[params.dataIndex];
|
||||||
|
// },
|
||||||
},
|
},
|
||||||
name: '',
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
value: 0,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#0B4A6B',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
//柱状
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'bar',
|
||||||
radius: ['20%', '80%'],
|
barWidth: 12, // 柱子宽度
|
||||||
roseType: 'area',
|
barCategoryGap: '30%', // 控制同一系列的柱间距离
|
||||||
zlevel: 10,
|
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
formatter: '{c|{c}}',
|
position: 'right', // 位置
|
||||||
rich: {
|
color: '#A7D6F4', //淡蓝色
|
||||||
c: {
|
fontSize: 14,
|
||||||
color: 'rgb(241,246,104)',
|
distance: 14, // label与柱子距离
|
||||||
fontSize: 16,
|
formatter: '{c}',
|
||||||
fontWeight: 'bold',
|
}, // 柱子上方的数值
|
||||||
lineHeight: 5,
|
itemStyle: {
|
||||||
},
|
borderRadius: [0, 20, 20, 0], // 圆角(左上、右上、右下、左下)
|
||||||
},
|
color: new echarts.graphic.LinearGradient(
|
||||||
position: 'outside',
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: '#51C5FD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: '#005BB1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
false
|
||||||
|
), // 渐变
|
||||||
},
|
},
|
||||||
labelLine: {
|
data: barArr.map((item: any) => item.value),
|
||||||
show: true,
|
},
|
||||||
length: 20,
|
],
|
||||||
length2: 55,
|
// 柱状图设置
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
type: 'value',
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
//y轴
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
type: 'category',
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
inverse: true,
|
||||||
|
data: barArr.map((item: any) => item.name),
|
||||||
|
axisLabel: {
|
||||||
|
color: '#A7D6F4',
|
||||||
|
fontSize: 14,
|
||||||
},
|
},
|
||||||
data: realData,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -313,13 +222,13 @@ function fnDesign(container: HTMLElement | undefined, option: any) {
|
|||||||
if (!container) return;
|
if (!container) return;
|
||||||
const { clientHeight, clientWidth } = container;
|
const { clientHeight, clientWidth } = container;
|
||||||
|
|
||||||
alarmTypeBarChart.value = markRaw(
|
alarmTypeBarChart.value = markRaw(echarts.init(container, 'light'));
|
||||||
echarts.init(container, 'light', {
|
|
||||||
width: clientWidth,
|
|
||||||
height: clientHeight - 36,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
option && alarmTypeBarChart.value.setOption(option);
|
option && alarmTypeBarChart.value.setOption(option);
|
||||||
|
|
||||||
|
window.onresize = function () {
|
||||||
|
// echarts 窗口缩放自适应 随着div--echarts-records的大小来适应
|
||||||
|
alarmTypeBarChart.value.resize();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {
|
|
||||||
cdrEventData,
|
|
||||||
cdrEventTotal,
|
|
||||||
cdrEventId,
|
|
||||||
} from '../../hooks/useCDREvent';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
const { t } = useI18n();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="cdr" style="display: block">
|
|
||||||
<div class="cdr-head">
|
|
||||||
<span class="col">{{ t('views.dashboard.overview.cdrEvent.id') }}</span>
|
|
||||||
<span class="col">{{ t('views.dashboard.overview.cdrEvent.type') }}</span>
|
|
||||||
<span class="col-w">
|
|
||||||
{{ t('views.dashboard.overview.cdrEvent.msg') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="cdr-marquee-view">
|
|
||||||
<div
|
|
||||||
class="row"
|
|
||||||
:class="{ 'row-new': item.id === cdrEventId }"
|
|
||||||
v-for="item in cdrEventData"
|
|
||||||
:key="item.id"
|
|
||||||
>
|
|
||||||
<span class="col" :title="item.call">{{ item.call }}</span>
|
|
||||||
<span class="col" :title="item.type">{{ item.type }}</span>
|
|
||||||
<span class="col-w" :title="item.msg">{{ item.msg }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.cdr {
|
|
||||||
height: 88%;
|
|
||||||
|
|
||||||
&-head {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
font-size: 0.583rem;
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
color: #68d8fe;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
line-height: 1.05;
|
|
||||||
& .col {
|
|
||||||
min-width: 3.2rem;
|
|
||||||
width: 30%;
|
|
||||||
margin-right: 1rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
&-w {
|
|
||||||
min-width: 8.4rem;
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-marquee-view {
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
height: 92%;
|
|
||||||
|
|
||||||
/* 修改滚动条的样式 */
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 8px; /* 设置滚动条宽度 */
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background-color: #101129; /* 设置滚动条轨道背景颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #28293f; /* 设置滚动条滑块颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb:hover {
|
|
||||||
background-color: #68d8fe; /* 设置鼠标悬停时滚动条滑块颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
& .row {
|
|
||||||
line-height: 1.5;
|
|
||||||
padding: 0 1.5rem;
|
|
||||||
color: #61a8ff;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
cursor: context-menu;
|
|
||||||
&-new {
|
|
||||||
color: #fff;
|
|
||||||
animation: backInRight 0.3s alternate;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
@keyframes backInRight {
|
|
||||||
0% {
|
|
||||||
opacity: 0.7;
|
|
||||||
-webkit-transform: translateX(2000px) scale(0.7);
|
|
||||||
transform: translateX(2000px) scale(0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
80% {
|
|
||||||
opacity: 0.7;
|
|
||||||
-webkit-transform: translateX(0) scale(0.7);
|
|
||||||
transform: translateX(0) scale(0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transform: scale(1);
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& .col {
|
|
||||||
min-width: 3.2rem;
|
|
||||||
width: 30%;
|
|
||||||
margin-right: 1rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
&-w {
|
|
||||||
min-width: 8.4rem;
|
|
||||||
width: 60%;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ueEventData, ueEventTotal, ueEventId } from '../../hooks/useUEEvent';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
const { t } = useI18n();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="ue" style="display: block">
|
|
||||||
<div class="ue-head">
|
|
||||||
<span class="col">{{ t('views.dashboard.overview.ueEvent.id') }}</span>
|
|
||||||
<span class="col">{{ t('views.dashboard.overview.ueEvent.type') }}</span>
|
|
||||||
<span class="col-w">{{ t('views.dashboard.overview.ueEvent.msg') }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="ue-marquee-view">
|
|
||||||
<div
|
|
||||||
class="row"
|
|
||||||
:class="{ 'row-new': item.id === ueEventId }"
|
|
||||||
v-for="item in ueEventData"
|
|
||||||
:key="item.id"
|
|
||||||
>
|
|
||||||
<span class="col" :title="item.imsi">{{ item.imsi }}</span>
|
|
||||||
<span class="col" :title="item.type">{{ item.type }}</span>
|
|
||||||
<span class="col-w" :title="item.msg">{{ item.msg }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.ue {
|
|
||||||
height: 88%;
|
|
||||||
|
|
||||||
&-head {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
font-size: 0.583rem;
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
color: #68d8fe;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
line-height: 1.05;
|
|
||||||
& .col {
|
|
||||||
min-width: 3.2rem;
|
|
||||||
width: 30%;
|
|
||||||
margin-right: 1rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
&-w {
|
|
||||||
min-width: 8.4rem;
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-marquee-view {
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
height: 92%;
|
|
||||||
|
|
||||||
/* 修改滚动条的样式 */
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 8px; /* 设置滚动条宽度 */
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background-color: #101129; /* 设置滚动条轨道背景颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #28293f; /* 设置滚动条滑块颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb:hover {
|
|
||||||
background-color: #68d8fe; /* 设置鼠标悬停时滚动条滑块颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
& .row {
|
|
||||||
line-height: 1.5;
|
|
||||||
padding: 0 1.5rem;
|
|
||||||
color: #61a8ff;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
cursor: context-menu;
|
|
||||||
&-new {
|
|
||||||
color: #fff;
|
|
||||||
animation: backInRight 0.3s alternate;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
@keyframes backInRight {
|
|
||||||
0% {
|
|
||||||
opacity: 0.7;
|
|
||||||
-webkit-transform: translateX(2000px) scale(0.7);
|
|
||||||
transform: translateX(2000px) scale(0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
80% {
|
|
||||||
opacity: 0.7;
|
|
||||||
-webkit-transform: translateX(0) scale(0.7);
|
|
||||||
transform: translateX(0) scale(0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transform: scale(1);
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& .col {
|
|
||||||
min-width: 3.2rem;
|
|
||||||
width: 30%;
|
|
||||||
margin-right: 1rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
&-w {
|
|
||||||
min-width: 8.4rem;
|
|
||||||
width: 60%;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -62,20 +62,15 @@ function fnDesign(container: HTMLElement | undefined, option: EChartsOption) {
|
|||||||
if (!container) {
|
if (!container) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { clientHeight, clientWidth } = container;
|
|
||||||
if (!upfFlowChart.value) {
|
if (!upfFlowChart.value) {
|
||||||
upfFlowChart.value = markRaw(
|
upfFlowChart.value = markRaw(echarts.init(container, 'light'));
|
||||||
echarts.init(container, 'light', {
|
|
||||||
width: clientWidth,
|
|
||||||
height: clientHeight - 36,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
option && upfFlowChart.value.setOption(option);
|
||||||
window.onresize = function () {
|
window.onresize = function () {
|
||||||
// echarts 窗口缩放自适应 随着div--echarts-records的大小来适应
|
// echarts 窗口缩放自适应 随着div--echarts-records的大小来适应
|
||||||
upfFlowChart.value.resize();
|
upfFlowChart.value.resize();
|
||||||
};
|
};
|
||||||
option && upfFlowChart.value.setOption(option);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//渲染速率图
|
//渲染速率图
|
||||||
@@ -126,27 +121,25 @@ function initPicture() {
|
|||||||
color: color[x] + ')',
|
color: color[x] + ')',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
color: new echarts.graphic.LinearGradient(
|
||||||
color: new echarts.graphic.LinearGradient(
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
1,
|
||||||
1,
|
[
|
||||||
[
|
{
|
||||||
{
|
offset: 0,
|
||||||
offset: 0,
|
color: color[x] + ', 0.5)',
|
||||||
color: color[x] + ', 0.5)',
|
},
|
||||||
},
|
{
|
||||||
{
|
offset: 0.8,
|
||||||
offset: 0.8,
|
color: color[x] + ', 0.5)',
|
||||||
color: color[x] + ', 0.5)',
|
},
|
||||||
},
|
],
|
||||||
],
|
false
|
||||||
false
|
),
|
||||||
),
|
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
shadowBlur: 10,
|
||||||
shadowBlur: 10,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: 5,
|
symbolSize: 5,
|
||||||
@@ -201,7 +194,7 @@ function initPicture() {
|
|||||||
formatter: function (params: any) {
|
formatter: function (params: any) {
|
||||||
return params.split(' ')[0] + '\n' + params.split(' ')[1];
|
return params.split(' ')[0] + '\n' + params.split(' ')[1];
|
||||||
},
|
},
|
||||||
fontSize:12
|
fontSize: 14,
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
@@ -213,9 +206,9 @@ function initPicture() {
|
|||||||
{
|
{
|
||||||
name: charts.unit,
|
name: charts.unit,
|
||||||
type: 'value',
|
type: 'value',
|
||||||
// splitNumber: 4,
|
// splitNumber: 4,
|
||||||
min:0,
|
min: 0,
|
||||||
max:300,
|
max: 300,
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
formatter: '{value}',
|
formatter: '{value}',
|
||||||
},
|
},
|
||||||
@@ -230,11 +223,9 @@ function initPicture() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
],
|
],
|
||||||
series: lineY,
|
series: lineY,
|
||||||
};
|
};
|
||||||
console.log(optionData)
|
|
||||||
fnDesign(upfFlow.value, optionData);
|
fnDesign(upfFlow.value, optionData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
265
src/views/dashboard/overview/components/UserActivity/index.vue
Normal file
265
src/views/dashboard/overview/components/UserActivity/index.vue
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { parseDuration } from '@/utils/date-utils';
|
||||||
|
import { eventData, eventId } from '../../hooks/useUserActivity';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
const { t } = useI18n();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="activty">
|
||||||
|
<template v-for="item in eventData" :key="item.eId">
|
||||||
|
<div
|
||||||
|
class="card-cdr"
|
||||||
|
:class="{ active: item.eId === eventId }"
|
||||||
|
v-if="item.eType === 'cdr'"
|
||||||
|
>
|
||||||
|
<div class="card-cdr-item">
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.type') }}:
|
||||||
|
<span>{{ item.data.callType }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.duration') }}:
|
||||||
|
<span>{{ parseDuration(item.data.callDuration) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-cdr-item">
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.caller') }}:
|
||||||
|
<span>{{ item.data.callerParty }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.called') }}:
|
||||||
|
<span>{{ item.data.calledParty }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||||
|
<span>{{ item.data.cause }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="card-ue"
|
||||||
|
:class="{ active: item.eId === eventId }"
|
||||||
|
v-if="item.eType === 'ue'"
|
||||||
|
>
|
||||||
|
<div class="card-ue-item">
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.type') }}:
|
||||||
|
<span>{{ item.type }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
||||||
|
<span v-if="item.type === 'auth-result'">
|
||||||
|
{{ item.data.authTime }}
|
||||||
|
</span>
|
||||||
|
<span v-if="item.type === 'detach'">
|
||||||
|
{{ item.data.detachTime }}
|
||||||
|
</span>
|
||||||
|
<span v-if="item.type === 'cm-state'">
|
||||||
|
{{ item.data.changeTime }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>IMSI: <span>{{ item.data.imei }}</span></div>
|
||||||
|
<div class="card-ue-auth" v-if="item.type === 'auth-result'">
|
||||||
|
<div>
|
||||||
|
GNB ID: <span>{{ item.data.gNBID }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Cell ID: <span>{{ item.data.cellID }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Tac ID: <span>{{ item.data.tacID }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- <div class="card-cdr active">
|
||||||
|
<div class="card-cdr-item">
|
||||||
|
<div>类型: <span>video</span></div>
|
||||||
|
<div>时长: <span>123s</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-cdr-item">
|
||||||
|
<div>主叫: <span>12307550064</span></div>
|
||||||
|
<div>被叫: <span>12307550064</span></div>
|
||||||
|
</div>
|
||||||
|
<div>结果: <span>200</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-cdr">
|
||||||
|
<div class="card-cdr-item">
|
||||||
|
<div>类型: <span>audio</span></div>
|
||||||
|
<div>时长: <span>123s</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-cdr-item">
|
||||||
|
<div>主叫: <span>12307550064</span></div>
|
||||||
|
<div>被叫: <span>12307550064</span></div>
|
||||||
|
</div>
|
||||||
|
<div>结果: <span>200</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-ue">
|
||||||
|
<div class="card-ue-item">
|
||||||
|
<div>类型: <span>auth-result</span></div>
|
||||||
|
<div>Time: <span>2023-01-16 07:28:11</span></div>
|
||||||
|
</div>
|
||||||
|
<div>IMSI: <span>4600212141</span></div>
|
||||||
|
<div class="card-ue-auth">
|
||||||
|
<div>GNB ID: <span>31</span></div>
|
||||||
|
<div>Cell ID: <span>17</span></div>
|
||||||
|
<div>Tac ID: <span>98</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-ue">
|
||||||
|
<div class="card-ue-item">
|
||||||
|
<div>类型: <span>cm-state</span></div>
|
||||||
|
<div>Time: <span>2023-01-16 07:28:11</span></div>
|
||||||
|
</div>
|
||||||
|
<div>IMSI: <span>4600212141</span></div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- <div class="card-cdr">
|
||||||
|
{ "recordType":"MOC", // MOC, MTC, MOSM, MTSM
|
||||||
|
"seqNumber":81,
|
||||||
|
"callReference":"Y6ecb69Bj@10.25.0.210",
|
||||||
|
"callerParty":"7112",
|
||||||
|
"calledParty":"7108",
|
||||||
|
"serviceResult":"ok",
|
||||||
|
"seizureTime":1706515269,
|
||||||
|
"answerTime":1706515273,
|
||||||
|
"releaseTime":1706515294,
|
||||||
|
"callDuration":21
|
||||||
|
"callType":"audio" // audio, video
|
||||||
|
"fwdType": "CFB" // CFU,CFB, CFNR, CFNL
|
||||||
|
"fwdParty":"7999",
|
||||||
|
"cause": 200 // 200, 403, 408, 500 .... }
|
||||||
|
|
||||||
|
主叫:callerParty
|
||||||
|
被叫:calledParty
|
||||||
|
时长:callDuration
|
||||||
|
呼叫类型:callType
|
||||||
|
原因:cause
|
||||||
|
信息: 主叫 -> 被叫
|
||||||
|
</div>
|
||||||
|
<div class="card-ue">ue
|
||||||
|
事件类型:auth-result
|
||||||
|
imei
|
||||||
|
GNB ID
|
||||||
|
Cell ID
|
||||||
|
Tac ID
|
||||||
|
authTime
|
||||||
|
|
||||||
|
事件类型:detach
|
||||||
|
imsi
|
||||||
|
detachTime
|
||||||
|
|
||||||
|
事件类型:cm-state
|
||||||
|
imsi
|
||||||
|
changeTime
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.activty {
|
||||||
|
// background-color: rgb(253, 180, 180);
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 94%;
|
||||||
|
color: #61a8ff;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
& .card-ue {
|
||||||
|
// background-color: rgb(185, 241, 168);
|
||||||
|
border: 1px #61a8ff solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
& span {
|
||||||
|
color: #68d8fe;
|
||||||
|
}
|
||||||
|
&-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
& > div {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-auth {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
& > div {
|
||||||
|
width: 33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .card-cdr {
|
||||||
|
// background-color: rgb(184, 168, 241);
|
||||||
|
border: 1px #61a8ff solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
& span {
|
||||||
|
color: #68d8fe;
|
||||||
|
}
|
||||||
|
&-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
& > div {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .active {
|
||||||
|
color: #fff;
|
||||||
|
border: 1px #fff solid;
|
||||||
|
animation: backInRight 0.3s alternate;
|
||||||
|
& span {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 修改滚动条的样式 */
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 8px; /* 设置滚动条宽度 */
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background-color: #101129; /* 设置滚动条轨道背景颜色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #28293f; /* 设置滚动条滑块颜色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: #68d8fe; /* 设置鼠标悬停时滚动条滑块颜色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes backInRight {
|
||||||
|
0% {
|
||||||
|
opacity: 0.7;
|
||||||
|
-webkit-transform: translateX(2000px) scale(0.7);
|
||||||
|
transform: translateX(2000px) scale(0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
opacity: 0.7;
|
||||||
|
-webkit-transform: translateX(0) scale(0.7);
|
||||||
|
transform: translateX(0) scale(0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -135,16 +135,7 @@
|
|||||||
color: #4c9bfd;
|
color: #4c9bfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 本月告警统计 */
|
|
||||||
.alarmType {
|
|
||||||
min-height: 13rem;
|
|
||||||
height: 25%;
|
|
||||||
}
|
|
||||||
.alarmType .chart {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 用户行为 */
|
/* 用户行为 */
|
||||||
.userActivity {
|
.userActivity {
|
||||||
@@ -213,6 +204,17 @@
|
|||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 告警统计 */
|
||||||
|
.alarmType {
|
||||||
|
min-height: 22rem;
|
||||||
|
height: 60%;
|
||||||
|
}
|
||||||
|
.alarmType .inner .chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* 监控 */
|
/* 监控 */
|
||||||
.monitor {
|
.monitor {
|
||||||
height: 20rem;
|
height: 20rem;
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
/**事件数据 */
|
|
||||||
export const cdrEventData = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
/**事件总量 */
|
|
||||||
export const cdrEventTotal = ref<number>(0);
|
|
||||||
|
|
||||||
/**事件推送id */
|
|
||||||
export const cdrEventId = ref<string>('');
|
|
||||||
|
|
||||||
/**cdrEvent CDR会话事件 数据解析 */
|
|
||||||
export function cdrEventParse(item: Record<string, any>) {
|
|
||||||
let evData: Record<string, any> = item.cdrJSON || item.CDR;
|
|
||||||
if (typeof evData === 'string') {
|
|
||||||
try {
|
|
||||||
evData = JSON.parse(evData);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evData.recordType === 'CALL') {
|
|
||||||
return {
|
|
||||||
id: item.id || item.timestamp,
|
|
||||||
type: evData.recordType,
|
|
||||||
time: evData.callDuration,
|
|
||||||
call: evData.callReference,
|
|
||||||
msg: `${evData.calledParty} -> ${evData.callerParty}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,8 @@ export const notNeNodes = [
|
|||||||
'lan5',
|
'lan5',
|
||||||
'lan6',
|
'lan6',
|
||||||
'lan7',
|
'lan7',
|
||||||
|
'LAN',
|
||||||
|
'NR',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**图状态 */
|
/**图状态 */
|
||||||
@@ -114,9 +116,10 @@ export function neStateParse(neType: string, data: Record<string, any>) {
|
|||||||
const neS = nodes.find((n: any) => n.id === edgeSource);
|
const neS = nodes.find((n: any) => n.id === edgeSource);
|
||||||
const neT = nodes.find((n: any) => n.id === edgeTarget);
|
const neT = nodes.find((n: any) => n.id === edgeTarget);
|
||||||
// console.log(neS, edgeSource, neT, edgeTarget);
|
// console.log(neS, edgeSource, neT, edgeTarget);
|
||||||
// 通过 ID 查询节点实例
|
|
||||||
const item = graphG6.value.findById(edge.id);
|
if (neS && neT) {
|
||||||
if (neS && neT && item) {
|
// 通过 ID 查询节点实例
|
||||||
|
// const item = graphG6.value.findById(edge.id);
|
||||||
// console.log(
|
// console.log(
|
||||||
// `${edgeSource} - ${edgeTarget}`,
|
// `${edgeSource} - ${edgeTarget}`,
|
||||||
// neS.neState.online && neT.neState.online
|
// neS.neState.online && neT.neState.online
|
||||||
@@ -136,16 +139,16 @@ export function neStateParse(neType: string, data: Record<string, any>) {
|
|||||||
// });
|
// });
|
||||||
// 设置状态
|
// 设置状态
|
||||||
graphG6.value.setItemState(
|
graphG6.value.setItemState(
|
||||||
item,
|
edge.id,
|
||||||
'line-dash',
|
'line-dash',
|
||||||
neS.neState.online && neT.neState.online
|
neS.neState.online && neT.neState.online
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (neS && notNeNodes.includes(edgeTarget)) {
|
if (neS && notNeNodes.includes(edgeTarget)) {
|
||||||
graphG6.value.setItemState(item, 'line-dash', neT.neState.online);
|
graphG6.value.setItemState(edge.id, 'line-path', neS.neState.online);
|
||||||
}
|
}
|
||||||
if (neT && notNeNodes.includes(edgeSource)) {
|
if (neT && notNeNodes.includes(edgeSource)) {
|
||||||
graphG6.value.setItemState(item, 'line-dash', neT.neState.online);
|
graphG6.value.setItemState(edge.id, 'line-path', neT.neState.online);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
/**事件数据 */
|
|
||||||
export const ueEventData = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
/**事件总量 */
|
|
||||||
export const ueEventTotal = ref<number>(0);
|
|
||||||
|
|
||||||
/**事件推送id */
|
|
||||||
export const ueEventId = ref<string>('');
|
|
||||||
|
|
||||||
/**ueEvent UE会话事件 数据解析 */
|
|
||||||
export function ueEventParse(item: Record<string, any>) {
|
|
||||||
let evData: Record<string, any> = item.eventJSON;
|
|
||||||
if (typeof evData === 'string') {
|
|
||||||
try {
|
|
||||||
evData = JSON.parse(evData);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.eventType === 'auth-result') {
|
|
||||||
return {
|
|
||||||
id: item.id || item.timestamp,
|
|
||||||
type: item.eventType,
|
|
||||||
time: evData.authTime,
|
|
||||||
imsi: evData.imsi,
|
|
||||||
msg: `${evData.authMessage}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.eventType === 'detach') {
|
|
||||||
return {
|
|
||||||
id: item.id || item.timestamp,
|
|
||||||
type: item.eventType,
|
|
||||||
time: evData.detachTime,
|
|
||||||
imsi: evData.imsi,
|
|
||||||
msg: `${evData.detachResult}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.eventType === 'cm-state') {
|
|
||||||
return {
|
|
||||||
id: item.id || item.timestamp,
|
|
||||||
type: item.eventType,
|
|
||||||
time: evData.changeTime,
|
|
||||||
imsi: evData.imsi,
|
|
||||||
msg: `${evData.onlineNumber}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
66
src/views/dashboard/overview/hooks/useUserActivity.ts
Normal file
66
src/views/dashboard/overview/hooks/useUserActivity.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
/**UE事件数据 */
|
||||||
|
export const ueEventData = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
/**UE事件总量 */
|
||||||
|
export const ueEventTotal = ref<number>(0);
|
||||||
|
|
||||||
|
/**UE事件推送id */
|
||||||
|
export const ueEventId = ref<string>('');
|
||||||
|
|
||||||
|
/**ueEvent UE会话事件 数据解析 */
|
||||||
|
export function ueEventParse(item: Record<string, any>) {
|
||||||
|
let evData: Record<string, any> = item.eventJSON;
|
||||||
|
if (typeof evData === 'string') {
|
||||||
|
try {
|
||||||
|
evData = JSON.parse(evData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
eType: 'ue',
|
||||||
|
eId: `ue_${item.timestamp}`,
|
||||||
|
id: item.id,
|
||||||
|
type: item.eventType,
|
||||||
|
data: evData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**CDR事件数据 */
|
||||||
|
export const cdrEventData = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
/**CDR事件总量 */
|
||||||
|
export const cdrEventTotal = ref<number>(0);
|
||||||
|
|
||||||
|
/**CDR事件推送id */
|
||||||
|
export const cdrEventId = ref<string>('');
|
||||||
|
|
||||||
|
/**cdrEvent CDR会话事件 数据解析 */
|
||||||
|
export function cdrEventParse(item: Record<string, any>) {
|
||||||
|
let evData: Record<string, any> = item.cdrJSON || item.CDR;
|
||||||
|
if (typeof evData === 'string') {
|
||||||
|
try {
|
||||||
|
evData = JSON.parse(evData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
eType: 'cdr',
|
||||||
|
eId: `cdr_${item.timestamp}`,
|
||||||
|
id: item.id,
|
||||||
|
data: evData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**CDR+UE事件数据 */
|
||||||
|
export const eventData = ref<Record<string, any>[]>([]);
|
||||||
|
/**CDR+UE事件总量 */
|
||||||
|
export const eventTotal = ref<number>(0);
|
||||||
|
/**CDR/UE事件推送id */
|
||||||
|
export const eventId = ref<string>('');
|
||||||
@@ -2,17 +2,12 @@ import { RESULT_CODE_ERROR } from '@/constants/result-constants';
|
|||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import { onBeforeUnmount, onMounted } from 'vue';
|
import { onBeforeUnmount, onMounted } from 'vue';
|
||||||
import {
|
import {
|
||||||
ueEventData,
|
|
||||||
ueEventId,
|
|
||||||
ueEventTotal,
|
|
||||||
ueEventParse,
|
ueEventParse,
|
||||||
} from './useUEEvent';
|
|
||||||
import {
|
|
||||||
cdrEventData,
|
|
||||||
cdrEventTotal,
|
|
||||||
cdrEventId,
|
|
||||||
cdrEventParse,
|
cdrEventParse,
|
||||||
} from './useCDREvent';
|
eventData,
|
||||||
|
eventTotal,
|
||||||
|
eventId,
|
||||||
|
} from './useUserActivity';
|
||||||
import { upfTotalFlow, upfTFParse } from './useUPFTotalFlow';
|
import { upfTotalFlow, upfTFParse } from './useUPFTotalFlow';
|
||||||
import { neStateParse } from './useTopology';
|
import { neStateParse } from './useTopology';
|
||||||
|
|
||||||
@@ -28,21 +23,20 @@ export default function useWS() {
|
|||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsError(ev: any) {
|
function wsError(ev: any) {
|
||||||
// 接收数据后回调
|
// 接收数据后回调
|
||||||
console.log(ev);
|
console.error(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
console.log(res);
|
// console.log(res);
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
if (code === RESULT_CODE_ERROR) {
|
if (code === RESULT_CODE_ERROR) {
|
||||||
console.warn(res.msg);
|
console.warn(res.msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!requestId) return;
|
|
||||||
|
|
||||||
// 网元状态
|
// 网元状态
|
||||||
if (requestId.startsWith('neState')) {
|
if (requestId && requestId.startsWith('neState')) {
|
||||||
const neType = requestId.split('_')[1];
|
const neType = requestId.split('_')[1];
|
||||||
neStateParse(neType, data);
|
neStateParse(neType, data);
|
||||||
return;
|
return;
|
||||||
@@ -53,35 +47,27 @@ export default function useWS() {
|
|||||||
// ueEvent UE会话事件
|
// ueEvent UE会话事件
|
||||||
case '1010':
|
case '1010':
|
||||||
if (Array.isArray(data.rows)) {
|
if (Array.isArray(data.rows)) {
|
||||||
ueEventTotal.value = data.total;
|
eventTotal.value += data.total;
|
||||||
const evDataArr: Record<string, any>[] = [];
|
|
||||||
for (const item of data.rows) {
|
for (const item of data.rows) {
|
||||||
const v = ueEventParse(item);
|
const v = ueEventParse(item);
|
||||||
if (v) {
|
if (v) {
|
||||||
evDataArr.push(v);
|
eventData.value.push(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ueEventData.value = evDataArr;
|
eventId.value = eventData.value[0].eId;
|
||||||
if (evDataArr.length > 0) {
|
|
||||||
ueEventId.value = evDataArr[0].id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
//cdrEvent CDR会话事件
|
//cdrEvent CDR会话事件
|
||||||
case '1005':
|
case '1005':
|
||||||
if (Array.isArray(data.rows)) {
|
if (Array.isArray(data.rows)) {
|
||||||
cdrEventTotal.value = data.total;
|
eventTotal.value += data.total;
|
||||||
const evDataArr: Record<string, any>[] = [];
|
|
||||||
for (const item of data.rows) {
|
for (const item of data.rows) {
|
||||||
const v = cdrEventParse(item);
|
const v = cdrEventParse(item);
|
||||||
if (v) {
|
if (v) {
|
||||||
evDataArr.push(v);
|
eventData.value.push(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cdrEventData.value = evDataArr;
|
eventId.value = eventData.value[0].eId;
|
||||||
if (evDataArr.length > 0) {
|
|
||||||
cdrEventId.value = evDataArr[0].id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
//UPF-总流量数
|
//UPF-总流量数
|
||||||
@@ -112,8 +98,12 @@ export default function useWS() {
|
|||||||
if (data.data) {
|
if (data.data) {
|
||||||
const v = ueEventParse(data.data);
|
const v = ueEventParse(data.data);
|
||||||
if (v) {
|
if (v) {
|
||||||
ueEventData.value.unshift(v);
|
eventData.value.unshift(v);
|
||||||
ueEventId.value = v.id;
|
eventTotal.value += 1;
|
||||||
|
eventId.value = v.eId;
|
||||||
|
if (eventData.value.length > 50) {
|
||||||
|
eventData.value.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -122,8 +112,12 @@ export default function useWS() {
|
|||||||
if (data.data) {
|
if (data.data) {
|
||||||
const v = cdrEventParse(data.data);
|
const v = cdrEventParse(data.data);
|
||||||
if (v) {
|
if (v) {
|
||||||
cdrEventData.value.unshift(v);
|
eventData.value.unshift(v);
|
||||||
cdrEventId.value = v.id;
|
eventTotal.value += 1;
|
||||||
|
eventId.value = v.eId;
|
||||||
|
if (eventData.value.length > 50) {
|
||||||
|
eventData.value.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -154,7 +148,7 @@ export default function useWS() {
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 50,
|
pageSize: 25,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -170,7 +164,7 @@ export default function useWS() {
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 50,
|
pageSize: 25,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ import { onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
|||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import Topology from './components/Topology/index.vue';
|
import Topology from './components/Topology/index.vue';
|
||||||
import NeResources from './components/NeResources/index.vue';
|
import NeResources from './components/NeResources/index.vue';
|
||||||
import UEEvent from './components/UEEvent/index.vue';
|
import UserActivity from './components/UserActivity/index.vue';
|
||||||
import CDREvent from './components/CDREvent/index.vue';
|
|
||||||
import AlarnDayLine from './components/AlarnDayLine/index.vue';
|
|
||||||
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
|
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
|
||||||
import UPFFlow from './components/UPFFlow/index.vue';
|
import UPFFlow from './components/UPFFlow/index.vue';
|
||||||
import { listSub } from '@/api/neUser/sub';
|
import { listSub } from '@/api/neUser/sub';
|
||||||
@@ -75,6 +73,7 @@ async function fnGetState() {
|
|||||||
stateTimeout.value = setTimeout(() => fnGetState(), 5_000);
|
stateTimeout.value = setTimeout(() => fnGetState(), 5_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**初始数据函数 */
|
||||||
function InitData() {
|
function InitData() {
|
||||||
cdrEventSend();
|
cdrEventSend();
|
||||||
ueEventSend();
|
ueEventSend();
|
||||||
@@ -172,48 +171,38 @@ onBeforeUnmount(() => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<h4>{{ onlineInfo.ueNum }}</h4>
|
<h4>{{ onlineInfo.nbNum }}</h4>
|
||||||
<span>
|
<span>
|
||||||
<UserSwitchOutlined style="color: #6acca3" />
|
<GlobalOutlined style="color: #edcb35" />
|
||||||
{{ t('views.dashboard.overview.skim.session') }}
|
{{ t('views.dashboard.overview.skim.base') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<h4>1000</h4>
|
<h4>{{ onlineInfo.ueNum }}</h4>
|
||||||
|
<span>
|
||||||
|
<UserSwitchOutlined style="color: #6acca3" />
|
||||||
|
Data {{ t('views.dashboard.overview.skim.session') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<h4>0</h4>
|
||||||
<span>
|
<span>
|
||||||
<UserSwitchOutlined style="color: #6acca3" />
|
<UserSwitchOutlined style="color: #6acca3" />
|
||||||
IMS {{ t('views.dashboard.overview.skim.session') }}
|
IMS {{ t('views.dashboard.overview.skim.session') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
|
||||||
<h4>{{ onlineInfo.nbNum }}</h4>
|
|
||||||
<span>
|
|
||||||
<WifiOutlined style="color: #edcb35" />
|
|
||||||
{{ t('views.dashboard.overview.skim.base') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--告警统计-->
|
<!-- 用户行为 -->
|
||||||
<div class="alarmType panel">
|
<div class="userActivity panel">
|
||||||
<div class="inner">
|
|
||||||
<h3>{{ t('views.dashboard.overview.alarmType.title') }}</h3>
|
|
||||||
<div class="chart">
|
|
||||||
<AlarnTypeBar />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- CDR会话 -->
|
|
||||||
<div class="cdrEvent panel">
|
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>
|
<h3>
|
||||||
<WhatsAppOutlined style="color: #68d8fe" />
|
<WhatsAppOutlined style="color: #68d8fe" />
|
||||||
{{ t('views.dashboard.overview.cdrEvent.title') }}
|
{{ t('views.dashboard.overview.userActivity.title') }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="chart">
|
<div class="chart">
|
||||||
<CDREvent />
|
<UserActivity />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -237,9 +226,9 @@ onBeforeUnmount(() => {
|
|||||||
{{ t('views.dashboard.overview.topology.title') }}
|
{{ t('views.dashboard.overview.topology.title') }}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
normal:
|
{{ t('views.dashboard.overview.topology.normal') }}:
|
||||||
<span class="normal"> {{ graphNodeStateNum[0] }} </span>
|
<span class="normal"> {{ graphNodeStateNum[0] }} </span>
|
||||||
abnormal:
|
{{ t('views.dashboard.overview.topology.abnormal') }}:
|
||||||
<span class="abnormal"> {{ graphNodeStateNum[1] }} </span>
|
<span class="abnormal"> {{ graphNodeStateNum[1] }} </span>
|
||||||
</span>
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
@@ -305,15 +294,14 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- UE会话 -->
|
<!-- 告警统计 -->
|
||||||
<div class="ueEvent panel">
|
<div class="alarmType panel">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>
|
<h3>
|
||||||
<WhatsAppOutlined style="color: #68d8fe" />
|
<WhatsAppOutlined style="color: #68d8fe" /> {{ t('views.dashboard.overview.alarmTypeBar.alarmSum') }}
|
||||||
{{ t('views.dashboard.overview.ueEvent.title') }}
|
|
||||||
</h3>
|
</h3>
|
||||||
<div class="chart">
|
<div class="chart">
|
||||||
<UEEvent />
|
<AlarnTypeBar />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ function fnLoadChart(data: Record<string, any>[]) {
|
|||||||
type: 'value',
|
type: 'value',
|
||||||
name: `${t('views.monitor.monitor.resourceUsage')} ( % )`,
|
name: `${t('views.monitor.monitor.resourceUsage')} ( % )`,
|
||||||
position: 'right',
|
position: 'right',
|
||||||
alignTicks: true,
|
alignTicks: false
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
grid: { left: '5%', right: '5%', bottom: '20%' },
|
grid: { left: '5%', right: '5%', bottom: '20%' },
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ const notNeNodes = [
|
|||||||
'lan5',
|
'lan5',
|
||||||
'lan6',
|
'lan6',
|
||||||
'lan7',
|
'lan7',
|
||||||
|
'LAN',
|
||||||
|
'NR',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**图实例对象 */
|
/**图实例对象 */
|
||||||
@@ -419,9 +421,10 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
const neS = nodes.find((n: any) => n.id === edgeSource);
|
const neS = nodes.find((n: any) => n.id === edgeSource);
|
||||||
const neT = nodes.find((n: any) => n.id === edgeTarget);
|
const neT = nodes.find((n: any) => n.id === edgeTarget);
|
||||||
// console.log(neS, edgeSource, neT, edgeTarget);
|
// console.log(neS, edgeSource, neT, edgeTarget);
|
||||||
// 通过 ID 查询节点实例
|
|
||||||
const item = graphG6.value.findById(edge.id);
|
if (neS && neT) {
|
||||||
if (neS && neT && item) {
|
// 通过 ID 查询节点实例
|
||||||
|
// const item = graphG6.value.findById(edge.id);
|
||||||
// console.log(
|
// console.log(
|
||||||
// `${edgeSource} - ${edgeTarget}`,
|
// `${edgeSource} - ${edgeTarget}`,
|
||||||
// neS.neState.online && neT.neState.online
|
// neS.neState.online && neT.neState.online
|
||||||
@@ -441,16 +444,16 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
// });
|
// });
|
||||||
// 设置状态
|
// 设置状态
|
||||||
graphG6.value.setItemState(
|
graphG6.value.setItemState(
|
||||||
item,
|
edge.id,
|
||||||
'line-dash',
|
'line-dash',
|
||||||
neS.neState.online && neT.neState.online
|
neS.neState.online && neT.neState.online
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (neS && notNeNodes.includes(edgeTarget)) {
|
if (neS && notNeNodes.includes(edgeTarget)) {
|
||||||
graphG6.value.setItemState(item, 'line-dash', neT.neState.online);
|
graphG6.value.setItemState(edge.id, 'line-path', neS.neState.online);
|
||||||
}
|
}
|
||||||
if (neT && notNeNodes.includes(edgeSource)) {
|
if (neT && notNeNodes.includes(edgeSource)) {
|
||||||
graphG6.value.setItemState(item, 'line-dash', neT.neState.online);
|
graphG6.value.setItemState(edge.id, 'line-path', neT.neState.online);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,11 +208,15 @@ export function edgeLineAnimateState() {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// line-dash 虚线运动
|
// line-dash 虚线运动
|
||||||
if (name === 'line-dash') {
|
if (name === 'line-dash') {
|
||||||
if (value) {
|
if (value) {
|
||||||
if (keyShape.cfg.animating) return;
|
keyShape.stopAnimate();
|
||||||
|
keyShape.attr({
|
||||||
|
lineDash: null,
|
||||||
|
lineDashOffset: null,
|
||||||
|
});
|
||||||
let index = 0;
|
let index = 0;
|
||||||
keyShape.animate(
|
keyShape.animate(
|
||||||
() => {
|
() => {
|
||||||
@@ -221,7 +225,7 @@ export function edgeLineAnimateState() {
|
|||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
lineDash: [4, 2, 2, 2],
|
lineDash: [4, 2, 1, 2],
|
||||||
lineDashOffset: -index,
|
lineDashOffset: -index,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -230,12 +234,6 @@ export function edgeLineAnimateState() {
|
|||||||
duration: 3000, // 执行一次的持续时间
|
duration: 3000, // 执行一次的持续时间
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
keyShape.stopAnimate();
|
|
||||||
keyShape.attr({
|
|
||||||
lineDash: null,
|
|
||||||
lineDashOffset: null,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user