feat: 仪表板看板

This commit is contained in:
TsMask
2024-01-19 16:51:32 +08:00
parent bf246d621d
commit 533370ee8e
8 changed files with 1385 additions and 238 deletions

View File

@@ -0,0 +1,242 @@
<script setup lang="ts">
import { reactive, onMounted, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listNe, stateNe } from '@/api/ne/ne';
import { message } from 'ant-design-vue/lib';
import { getGraphData } from '@/api/monitor/topology';
import { parseDateToStr } from '@/utils/date-utils';
import { Graph, GraphData, Menu, Tooltip } from '@antv/g6';
import {
edgeCubicAnimateCircleMove,
edgeCubicAnimateLineDash,
edgeLineAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerEdge';
import {
nodeCircleAnimateShapeR,
nodeCircleAnimateShapeStroke,
nodeImageAnimateState,
nodeRectAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerNode';
import * as echarts from 'echarts/core';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
echarts.use([TooltipComponent, GaugeChart, CanvasRenderer]);
type EChartsOption = echarts.ComposeOption<GaugeSeriesOption>;
/**图DOM节点实例对象 */
const neResourcesDom = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const neResourcesChart = ref<any>(null);
const optionData: EChartsOption = {
tooltip: {
formatter: '{a} <br> {b} : {c}%',
},
series: [
{
name: '系统内存',
type: 'gauge',
center: ['30%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
{
name: '系统CPU',
type: 'gauge',
center: ['70%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
],
};
/**图数据渲染 */
function handleRanderChart(
container: HTMLElement | undefined,
option: EChartsOption
) {
if (!container) return;
const { clientHeight, clientWidth } = container;
neResourcesChart.value = echarts.init(container, 'light', {
width: clientWidth,
height: clientHeight - 36,
});
option && neResourcesChart.value.setOption(option);
}
onMounted(() => {
setInterval(function () {
const random = +(Math.random() * 90).toFixed(2);
const random2 = +(Math.random() * 90).toFixed(2);
const random3 = +(Math.random() * 90).toFixed(2);
const random4 = +(Math.random() * 90).toFixed(2);
let color = '#1890ff';
if (random < 30) {
color = '#73d13d';
}
if (random > 60) {
color = '#ff4d4f';
}
neResourcesChart.value.setOption({
series: [
{
data: [
{
name: '系统内存',
value: random,
itemStyle: {
color: color,
shadowColor: color,
},
},
],
},
{
data: [
{
name: '系统CPU',
value: random2,
},
],
},
],
});
}, 2000);
handleRanderChart(neResourcesDom.value, optionData);
});
onBeforeUnmount(() => {});
</script>
<template>
<div ref="neResourcesDom" class="chart"></div>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,171 @@
<script setup lang="ts">
import { reactive, onMounted, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listNe, stateNe } from '@/api/ne/ne';
import { message } from 'ant-design-vue/lib';
import { getGraphData } from '@/api/monitor/topology';
import { parseDateToStr } from '@/utils/date-utils';
import { Graph, GraphData, Menu, Tooltip } from '@antv/g6';
import {
edgeCubicAnimateCircleMove,
edgeCubicAnimateLineDash,
edgeLineAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerEdge';
import {
nodeCircleAnimateShapeR,
nodeCircleAnimateShapeStroke,
nodeImageAnimateState,
nodeRectAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerNode';
import * as echarts from 'echarts/core';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
echarts.use([TooltipComponent, GaugeChart, CanvasRenderer]);
type EChartsOption = echarts.ComposeOption<GaugeSeriesOption>;
/**图DOM节点实例对象 */
const neResourcesDom = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const neResourcesChart = ref<any>(null);
const optionData: EChartsOption = {
tooltip: {
formatter: '{a} <br> {b} : {c}%',
},
series: [
{
name: '系统内存',
type: 'gauge',
center: ['30%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
],
};
/**图数据渲染 */
function handleRanderChart(
container: HTMLElement | undefined,
option: EChartsOption
) {
if (!container) return;
const { clientHeight, clientWidth } = container;
neResourcesChart.value = echarts.init(container, 'light', {
width: clientWidth,
height: clientHeight - 36,
});
option && neResourcesChart.value.setOption(option);
}
onMounted(() => {
setInterval(function () {
const random = +(Math.random() * 90).toFixed(2);
const random2 = +(Math.random() * 90).toFixed(2);
const random3 = +(Math.random() * 90).toFixed(2);
const random4 = +(Math.random() * 90).toFixed(2);
let color = '#1890ff';
if (random < 30) {
color = '#73d13d';
}
if (random > 60) {
color = '#ff4d4f';
}
neResourcesChart.value.setOption({
series: [
{
data: [
{
name: '系统内存',
value: random,
itemStyle: {
color: color,
shadowColor: color,
},
},
],
},
],
});
}, 2000);
handleRanderChart(neResourcesDom.value, optionData);
});
onBeforeUnmount(() => {});
</script>
<template>
<div ref="neResourcesDom" class="chart"></div>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,143 @@
<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const newNumber = ref(1);
const dataArr = ref([
{
recordType: 'CALL',
seqNumber: 1,
callReference: 'X1gcbQ8zT@10.10.91.252',
callerParty: '12307551241',
calledParty: '12307550064',
serviceResult: 'ok',
seizureTime: 1705542348,
answerTime: 1705542356,
releaseTime: 1705542378,
callDuration: 22,
},
]);
onMounted(() => {
setInterval(function () {
const random = Math.ceil(Math.random() * 1000);
const time = Math.ceil(Date.now() / 1000);
newNumber.value = time;
dataArr.value.unshift({
recordType: 'CALL',
seqNumber: time,
callReference: `X${random}Q8zT@10${random}.252`,
callerParty: `1230755${random}`,
calledParty: `${random}075064`,
serviceResult: random > 500 ? 'ok' : 'fail',
seizureTime: time,
answerTime: time,
releaseTime: time - random,
callDuration: 22,
});
if (dataArr.value.length > 50) {
dataArr.value.splice(50);
}
}, 2000);
});
</script>
<template>
<div class="cdr" style="display: block">
<div class="cdr-head">
<span class="col">号码</span>
<span class="col">行为</span>
<span class="col-w">描述</span>
</div>
<div class="cdr-marquee-view">
<div
class="row"
:class="{ 'row-new': item.seqNumber === newNumber }"
v-for="item in dataArr"
:key="item.seqNumber"
>
<span class="col">{{ item.callReference }}</span>
<span class="col">{{ item.recordType }}</span>
<span class="col-w"
>[{{ item.serviceResult }}]
{{ item.callerParty }}
->
{{ item.calledParty }}
# {{ item.callDuration }}
</span>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.cdr {
&-head {
background: rgba(255, 255, 255, 0.1);
font-size: 0.583rem;
padding: 0.5rem 1.5rem;
color: #68d8fe;
display: flex;
justify-content: space-between;
line-height: 1.05;
& .col {
width: 3.2rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&-w {
width: 8.4rem;
}
}
}
&-marquee-view {
overflow-x: hidden;
overflow-y: auto;
height: 70%;
& .row {
line-height: 1.05;
padding: 0.5rem 1.5rem;
color: #61a8ff;
font-size: 0.75rem;
position: relative;
display: flex;
justify-content: space-between;
&-new {
color: #fff;
animation: backInRight 0.3s alternate;
}
@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 {
width: 3.2rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&-w {
width: 8.4rem;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,384 @@
<script setup lang="ts">
import { reactive, onMounted, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listNe, stateNe } from '@/api/ne/ne';
import { message } from 'ant-design-vue/lib';
import { getGraphData } from '@/api/monitor/topology';
import { parseDateToStr } from '@/utils/date-utils';
import { Graph, GraphData, Menu, Tooltip } from '@antv/g6';
import {
edgeCubicAnimateCircleMove,
edgeCubicAnimateLineDash,
edgeLineAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerEdge';
import {
nodeCircleAnimateShapeR,
nodeCircleAnimateShapeStroke,
nodeImageAnimateState,
nodeRectAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerNode';
import * as echarts from 'echarts/core';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
echarts.use([TooltipComponent, GaugeChart, CanvasRenderer]);
type EChartsOption = echarts.ComposeOption<GaugeSeriesOption>;
/**图DOM节点实例对象 */
const neResourcesDom = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const neResourcesChart = ref<any>(null);
const optionData: EChartsOption = {
tooltip: {
formatter: '{a} <br> {b} : {c}%',
},
series: [
{
name: '系统内存',
type: 'gauge',
center: ['30%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
{
name: '系统CPU',
type: 'gauge',
center: ['70%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
{
name: '网元内存',
type: 'gauge',
center: ['30%', '75%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
{
name: '网元CPU',
type: 'gauge',
center: ['70%', '75%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
],
};
/**图数据渲染 */
function handleRanderChart(
container: HTMLElement | undefined,
option: EChartsOption
) {
if (!container) return;
const { clientHeight, clientWidth } = container;
neResourcesChart.value = echarts.init(container, 'light', {
width: clientWidth,
height: clientHeight - 36,
});
option && neResourcesChart.value.setOption(option);
}
onMounted(() => {
setInterval(function () {
const random = +(Math.random() * 90).toFixed(2);
const random2 = +(Math.random() * 90).toFixed(2);
const random3 = +(Math.random() * 90).toFixed(2);
const random4 = +(Math.random() * 90).toFixed(2);
let color = '#1890ff';
if (random < 30) {
color = '#73d13d';
}
if (random > 60) {
color = '#ff4d4f';
}
neResourcesChart.value.setOption({
series: [
{
data: [
{
name: '系统内存',
value: random,
itemStyle: {
color: color,
shadowColor: color,
},
},
],
},
{
data: [
{
name: '系统CPU',
value: random2,
},
],
},
{
data: [
{
name: '网元内存',
value: random3,
},
],
},
{
data: [
{
name: '网元CPU',
value: random4,
},
],
},
],
});
}, 2000);
handleRanderChart(neResourcesDom.value, optionData);
});
onBeforeUnmount(() => {});
</script>
<template>
<div ref="neResourcesDom" class="chart"></div>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -167,8 +167,9 @@ function handleRanderGraph(
const graph = new Graph({
container: container,
width: clientWidth,
height: clientHeight,
height: clientHeight - 36,
fitCenter: true,
fitView: true,
modes: {
default: [
'drag-combo',

View File

@@ -0,0 +1,242 @@
<script setup lang="ts">
import { reactive, onMounted, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listNe, stateNe } from '@/api/ne/ne';
import { message } from 'ant-design-vue/lib';
import { getGraphData } from '@/api/monitor/topology';
import { parseDateToStr } from '@/utils/date-utils';
import { Graph, GraphData, Menu, Tooltip } from '@antv/g6';
import {
edgeCubicAnimateCircleMove,
edgeCubicAnimateLineDash,
edgeLineAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerEdge';
import {
nodeCircleAnimateShapeR,
nodeCircleAnimateShapeStroke,
nodeImageAnimateState,
nodeRectAnimateState,
} from '@/views/monitor/topologyBuild/hooks/registerNode';
import * as echarts from 'echarts/core';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
echarts.use([TooltipComponent, GaugeChart, CanvasRenderer]);
type EChartsOption = echarts.ComposeOption<GaugeSeriesOption>;
/**图DOM节点实例对象 */
const neResourcesDom = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const neResourcesChart = ref<any>(null);
const optionData: EChartsOption = {
tooltip: {
formatter: '{a} <br> {b} : {c}%',
},
series: [
{
name: '系统内存',
type: 'gauge',
center: ['30%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
{
name: '系统CPU',
type: 'gauge',
center: ['70%', '25%'],
radius: '40%',
startAngle: 90,
endAngle: -270,
min: 1,
max: 100,
itemStyle: {
color: '#1890ff',
},
progress: {
show: true,
width: 10,
overlap: true,
roundCap: true,
clip: false,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 10,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
anchor: {
show: false,
},
title: {
show: true,
offsetCenter: [0, -5],
fontSize: 10,
color: '#fafafa',
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, 10],
fontSize: 10,
fontWeight: 'bolder',
formatter: '{value}%',
color: 'inherit',
},
data: [
{
name: '系统内存',
value: 20,
},
],
},
],
};
/**图数据渲染 */
function handleRanderChart(
container: HTMLElement | undefined,
option: EChartsOption
) {
if (!container) return;
const { clientHeight, clientWidth } = container;
neResourcesChart.value = echarts.init(container, 'light', {
width: clientWidth,
height: clientHeight - 36,
});
option && neResourcesChart.value.setOption(option);
}
onMounted(() => {
setInterval(function () {
const random = +(Math.random() * 90).toFixed(2);
const random2 = +(Math.random() * 90).toFixed(2);
const random3 = +(Math.random() * 90).toFixed(2);
const random4 = +(Math.random() * 90).toFixed(2);
let color = '#1890ff';
if (random < 30) {
color = '#73d13d';
}
if (random > 60) {
color = '#ff4d4f';
}
neResourcesChart.value.setOption({
series: [
{
data: [
{
name: '系统内存',
value: random,
itemStyle: {
color: color,
shadowColor: color,
},
},
],
},
{
data: [
{
name: '系统CPU',
value: random2,
},
],
},
],
});
}, 2000);
handleRanderChart(neResourcesDom.value, optionData);
});
onBeforeUnmount(() => {});
</script>
<template>
<div ref="neResourcesDom" class="chart"></div>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -11,6 +11,35 @@
background-color: #101129;
}
.column {
flex: 3;
position: relative;
}
/* 边框 */
.panel {
box-sizing: border-box;
border: 2px solid red;
border-image: url(../images/border.png) 51 38 21 132;
border-width: 2.125rem 1.583rem 0.875rem 5.5rem;
position: relative;
margin-bottom: 0.833rem;
}
.panel .inner {
/* 装内容 */
/* height: 60px; */
position: absolute;
top: -2.125rem;
right: -1.583rem;
bottom: -0.875rem;
left: -5.5rem;
padding: 1rem 1.5rem;
}
.panel h3 {
font-size: 0.833rem;
color: #fff;
}
/* 总览标题 */
.brand {
background-image: url(../images/brand.png);
@@ -40,53 +69,28 @@
font-size: 0.9rem;
}
/* 拓扑图 */
.topology {
height: 24.1rem;
margin-bottom: 0.833rem;
/* 实时流量 */
.upfFlow {
height: 16rem;
display: flex;
flex-direction: column;
}
.topology .topology-title {
line-height: 1;
padding: 0.667rem 0;
margin: 0;
font-size: 0.833rem;
color: #fff;
}
.topology .topology-chart {
flex: 1;
background-color: rgba(255, 255, 255, 0.05);
.upfFlow .inner .chart {
width: 100%;
height: 100%;
margin-top: 1rem;
}
.column {
flex: 3;
position: relative;
/* 网络拓扑 */
.topology {
height: 25.55rem;
display: flex;
}
.topology .inner .chart {
width: 100%;
height: 100%;
margin-top: 1rem;
}
.panel {
/* 边框 */
box-sizing: border-box;
border: 2px solid red;
border-image: url(../images/border.png) 51 38 21 132;
border-width: 2.125rem 1.583rem 0.875rem 5.5rem;
position: relative;
margin-bottom: 0.833rem;
}
.panel .inner {
/* 装内容 */
/* height: 60px; */
position: absolute;
top: -2.125rem;
right: -1.583rem;
bottom: -0.875rem;
left: -5.5rem;
padding: 1rem 1.5rem;
}
.panel h3 {
font-size: 0.833rem;
color: #fff;
}
/* 概览区域 */
.overview {
height: 4.583rem;
@@ -95,16 +99,128 @@
display: flex;
justify-content: space-between;
}
.overview h4 {
.overview .inner h4 {
font-size: 1.167rem;
padding-left: 0.2rem;
color: #fff;
margin-bottom: 0.333rem;
}
.overview span {
.overview .inner span {
font-size: 0.667rem;
color: #4c9bfd;
}
/* 本月告警统计 */
.alarmType {
height: 14.167rem;
}
.alarmType .chart {
display: flex;
margin-top: 1rem;
justify-content: space-between;
}
.alarmType .bar {
width: 13rem;
height: 10rem;
margin-left: -0.4rem;
}
.alarmType .data {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 7rem;
padding: 1.5rem 1.25rem;
box-sizing: border-box;
background-image: url(../images/rect.png);
background-size: cover;
}
.alarmType .data h4 {
margin-bottom: 0.5rem;
font-size: 1.167rem;
color: #fff;
}
.alarmType .data span {
display: block;
color: #4c9bfd;
font-size: 0.667rem;
}
/* 告警趋势 */
.alarmDay {
height: 16rem;
display: flex;
}
.alarmDay .inner .chart {
width: 100%;
height: 100%;
margin-top: 1rem;
}
/* 总流量 */
.totalFlow {
height: 6.167rem;
}
.totalFlow .inner .filter {
display: flex;
}
.totalFlow .inner .filter span {
display: block;
height: 0.75rem;
line-height: 1;
padding: 0 0.75rem;
color: #1950c4;
font-size: 0.75rem;
border-right: 0.083rem solid #00f2f1;
}
.totalFlow .inner .filter span:first-child {
padding-left: 0;
}
.totalFlow .inner .filter span:last-child {
border-right: none;
}
.totalFlow .inner .filter span.active {
color: #fff;
font-size: 0.833rem;
}
.totalFlow .data {
display: flex;
margin-top: 0.833rem;
}
.totalFlow .item {
width: 50%;
}
.totalFlow h4 {
font-size: 1.167rem;
color: #fff;
margin-bottom: 0.417rem;
}
.totalFlow span {
color: #4c9bfd;
font-size: 0.667rem;
}
/* 资源情况 */
.resources {
height: 16rem;
display: flex;
}
.resources .inner .chart {
width: 100%;
height: 100%;
margin-top: 1rem;
}
/* 会话监控 */
.cdr {
height: 22rem;
display: flex;
}
.cdr .inner .chart {
width: 100%;
height: 100%;
margin-top: 1rem;
}
/* 监控 */
.monitor {
height: 20rem;
@@ -328,49 +444,7 @@
color: #4c9bfd;
font-size: 0.667rem;
}
/* 订单 */
.order {
height: 6.167rem;
}
.order .filter {
display: flex;
}
.order .filter a {
display: block;
height: 0.75rem;
line-height: 1;
padding: 0 0.75rem;
color: #1950c4;
font-size: 0.75rem;
border-right: 0.083rem solid #00f2f1;
}
.order .filter a:first-child {
padding-left: 0;
}
.order .filter a:last-child {
border-right: none;
}
.order .filter a.active {
color: #fff;
font-size: 0.833rem;
}
.order .data {
display: flex;
margin-top: 0.833rem;
}
.order .item {
width: 50%;
}
.order h4 {
font-size: 1.167rem;
color: #fff;
margin-bottom: 0.417rem;
}
.order span {
display: block;
color: #4c9bfd;
font-size: 0.667rem;
}
/* 销售区域 */
.sales {
height: 10.333rem;

View File

@@ -2,6 +2,12 @@
import { onMounted, ref } from 'vue';
import useI18n from '@/hooks/useI18n';
import Topology from './components/Topology/index.vue';
import NeResources from './components/NeResources/index.vue';
import CDR from './components/CDR/index.vue';
import AlarnDayLine from './components/AlarnDayLine/index.vue';
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
import UPFFlow from './components/UPFFlow/index.vue';
import { useFullscreen } from '@vueuse/core';
import useAppStore from '@/store/modules/app';
const appStore = useAppStore();
@@ -61,11 +67,13 @@ onMounted(() => {});
</div>
<!--本月告警统计-->
<div class="point panel">
<div class="alarmType panel">
<div class="inner">
<h3>本月告警统计</h3>
<div class="chart">
<div class="pie"></div>
<div class="bar">
<AlarnTypeBar />
</div>
<div class="data">
<div class="item">
<h4>320,11</h4>
@@ -87,75 +95,46 @@ onMounted(() => {});
</div>
<!-- 告警趋势 -->
<div class="top panel">
<div class="alarmDay panel">
<div class="inner">
<div class="all">
<h3>告警趋势</h3>
<ul>
<li>
<i class="icon-cup1" style="color: #d93f36"></i>
可爱多
</li>
<li>
<i class="icon-cup2" style="color: #68d8fe"></i>
娃哈啥
</li>
<li>
<i class="icon-cup3" style="color: #4c9bfd"></i>
喜之郎
</li>
</ul>
<h3>告警趋势</h3>
<div class="chart">
<AlarnDayLine />
</div>
</div>
</div>
</div>
<div class="column" style="flex: 4; margin: 1.333rem 0.833rem 0">
<!-- 实时流量 -->
<div class="users panel">
<div class="upfFlow panel">
<div class="inner">
<h3>实时流量</h3>
<div class="chart">
<div class="bar"></div>
<div class="data">
<div class="item">
<h4>120,899</h4>
<span>
<i class="icon-dot" style="color: #ed3f35"></i>
用户总量
</span>
</div>
<div class="item">
<h4>248</h4>
<span>
<i class="icon-dot" style="color: #eacf19"></i>
本月新增
</span>
</div>
</div>
<UPFFlow />
</div>
</div>
</div>
<!-- 拓扑 -->
<!-- 网络拓扑 -->
<div class="topology panel">
<div class="topology-title">
<PartitionOutlined style="color: #68d8fe" />
<DeploymentUnitOutlined style="color: #68d8fe" />
网络拓扑
</div>
<div class="topology-chart">
<Topology />
<div class="inner">
<h3>
<ApartmentOutlined style="color: #68d8fe" />&nbsp;&nbsp;网络拓扑
</h3>
<div class="chart">
<Topology />
</div>
</div>
</div>
</div>
<div class="column">
<!-- 流量 -->
<div class="order panel">
<!-- 流量 -->
<div class="totalFlow panel">
<div class="inner">
<!-- 筛选 -->
<div class="filter">
<a href="javascript:;" data-key="day1" class="active">24小时</a>
<a href="javascript:;" data-key="day30">7</a>
<a href="javascript:;" data-key="day30">30</a>
<span data-key="1" class="active">24小时</span>
<span data-key="7">7</span>
<span data-key="30">30</span>
</div>
<!-- 数据 -->
<div class="data">
@@ -177,113 +156,24 @@ onMounted(() => {});
</div>
</div>
<!-- 资源情况 -->
<div class="users panel">
<div class="resources panel">
<div class="inner">
<h3>资源情况</h3>
<h3>
<DashboardOutlined style="color: #68d8fe" />&nbsp;&nbsp; 资源情况
</h3>
<div class="chart">
<div class="bar"></div>
<div class="data">
<div class="item">
<h4>120,899</h4>
<span>
<i class="icon-dot" style="color: #ed3f35"></i>
磁盘
</span>
</div>
<div class="item">
<h4>248</h4>
<span>
<i class="icon-dot" style="color: #eacf19"></i>
cpu
</span>
</div>
<div class="item">
<h4>248</h4>
<span>
<i class="icon-dot" style="color: #eacf19"></i>
内存
</span>
</div>
</div>
<NeResources />
</div>
</div>
</div>
<!--会话监控-->
<div class="monitor panel">
<!-- 会话监控 -->
<div class="cdr panel">
<div class="inner">
<div class="tabs">
<a href="javascript:;" data-index="0" class="active">会话监控</a>
</div>
<div class="content" style="display: block">
<div class="head">
<span class="col">故障时间</span>
<span class="col">设备地址</span>
<span class="col">异常代码</span>
</div>
<div class="marquee-view">
<div class="marquee">
<div class="row">
<span class="col">20180701</span>
<span class="col">11北京市昌平西路金燕龙写字楼</span>
<span class="col">1000001</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190601</span>
<span class="col">北京市昌平区城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190704</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000003</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20180701</span>
<span class="col">北京市昌平区建路金燕龙写字楼</span>
<span class="col">1000004</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000005</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000006</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建西路金燕龙写字楼</span>
<span class="col">1000007</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000008</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000009</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190710</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000010</span>
<span class="icon-dot"></span>
</div>
</div>
</div>
<h3>
<WhatsAppOutlined style="color: #d93f36" />&nbsp;&nbsp; 会话监控
</h3>
<div class="chart">
<CDR />
</div>
</div>
</div>