Files
fe.ems.vue3/src/views/dashboard/overview/index.vue
2025-09-12 14:42:22 +08:00

954 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { onBeforeUnmount, onMounted, reactive, ref, nextTick } from 'vue';
import svgBase from '@/assets/svg/base.svg';
import svgUserIMS from '@/assets/svg/userIMS.svg';
import svgUserSMF from '@/assets/svg/userSMF.svg';
import useI18n from '@/hooks/useI18n';
import Topology from './components/Topology/index.vue';
import NeResources from './components/NeResources/index.vue';
import UserActivity from './components/UserActivity/index.vue';
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
import UPFFlow from './components/UPFFlow/index.vue';
import { listUDMSub } from '@/api/neData/udm_sub';
import { listUENumBySMF } from '@/api/neUser/smf';
import { listUENumByIMS } from '@/api/neUser/ims';
import { listBase5G } from '@/api/neUser/base5G';
import { listIMSSub } from '@/api/neData/ims_sub';
import { listUDMAuth } from '@/api/neData/voip_auth';
import {
graphNodeClickID,
graphState,
notNeNodes,
graphNodeStateNum,
neStateRequestMap,
} from './hooks/useTopology';
import { upfTotalFlow, upfTFActive } from './hooks/useUPFTotalFlow';
import { useFullscreen } from '@vueuse/core';
import useWS from './hooks/useWS';
import useAppStore from '@/store/modules/app';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { useRouter } from 'vue-router';
import useNeInfoStore from '@/store/modules/neinfo';
import { message } from 'ant-design-vue';
import { upfWhoId } from './hooks/useWS';
const neInfoStore = useNeInfoStore();
const router = useRouter();
const appStore = useAppStore();
const { t } = useI18n();
const { wsSend, userActivitySend, upfTFSend, reSendUPF } = useWS();
// const viewportDom = ref<HTMLElement | null>(null);
//
// // 定义 resize 处理函数,确保能正确移除事件监听器
// const handleResize = () => {
// setTimeout(calculateScale, 100);
// };
//
//
//
//
//
// // 计算缩放比例的函数
// const calculateScale = () => {
// const container = document.querySelector('.dashboard-container') as HTMLElement;
// const wrapper = document.querySelector('.dashboard-wrapper') as HTMLElement;
//
// if (!container || !wrapper) return;
//
// const containerWidth = 1400; // 设计宽度
// const containerHeight = 900; // 设计高度
//
// // 获取可用空间减去padding
// const availableWidth = wrapper.clientWidth - 40;
// const availableHeight = wrapper.clientHeight - 40;
//
// // 计算缩放比例
// const scaleX = availableWidth / containerWidth;
// const scaleY = availableHeight / containerHeight;
//
// // 选择较小的比例,确保内容完全可见
// const scale = Math.min(scaleX, scaleY);
//
//
// container.style.transform = `scale(${scale})`;
// container.style.transformOrigin = 'center center';
// };
/**概览状态类型 */
type SkimStateType = {
/**UDM签约用户数量 */
udmSubNum: number;
/**SMF在线用户数 */
smfUeNum: number;
/**IMS在线用户数 */
imsUeNum: number;
/**5G基站数量 */
gnbNum: number;
/**5G在线用户数量 */
gnbUeNum: number;
/**4G基站数量 */
enbNum: number;
/**4G在线用户数量 */
enbUeNum: number;
/**IMS用户数量 */
imsUserNum: number;
/**VOIP用户数量 */
voipUserNum: number;
};
/**概览状态信息 */
let skimState: SkimStateType = reactive({
udmSubNum: 0,
smfUeNum: 0,
imsUeNum: 0,
gnbNum: 0,
gnbUeNum: 0,
enbNum: 0,
enbUeNum: 0,
imsUserNum: 0,
voipUserNum: 0,
});
/**网元参数 */
let neCascaderOptions = ref<Record<string, any>[]>([]);
/**总览节点 */
const viewportDom = ref<HTMLElement | null>(null);
const { isFullscreen, toggle } = useFullscreen(viewportDom);
let initFlag = false;
/**10s调度器 */
const interval10s = ref<any>(null);
/**5s调度器 */
const interval5s = ref<any>(null);
/**查询网元状态 */
function fnGetNeState() {
// 获取节点状态
for (const node of graphState.data.nodes) {
if (notNeNodes.includes(node.id)) continue;
const neInfoList = node.neInfoList || [];
if (neInfoList.length === 0) continue;
for (const neInfo of neInfoList) {
if (!neInfo.neType || !neInfo.neId) continue;
wsSend({
requestId: `neState_${neInfo.neType}_${neInfo.neId}`,
type: 'ne_state',
data: {
neType: neInfo.neType,
neId: neInfo.neId,
},
});
}
}
}
/**获取概览信息 */
async function fnGetSkim() {
const neHandlers = new Map([
// [
// 'UDM',
// {
// request: (neId: string) =>
// listUDMSub({ neId: neId, pageNum: 1, pageSize: 1 }),
// process: (res: any) =>
// res.code === RESULT_CODE_SUCCESS &&
// (skimState.udmSubNum += res.total),
// },
// ],
[
'SMF',
{
request: (neId: string) => listUENumBySMF(neId),
process: (res: any) =>
res.code === RESULT_CODE_SUCCESS && (skimState.smfUeNum += res.data),
},
],
[
'IMS',
{
request: (neId: string) => listUENumByIMS(neId),
process: (res: any) =>
res.code === RESULT_CODE_SUCCESS && (skimState.imsUeNum += res.data),
},
],
[
'AMF',
{
request: (neId: string) => listBase5G({ neType: 'AMF', neId }),
process: (res: any) => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.gnbNum += res.total;
skimState.gnbUeNum += res.rows.reduce(
(sum: number, item: any) => sum + item.ueNum,
0
);
}
},
},
],
[
'MME',
{
request: (neId: string) => listBase5G({ neType: 'MME', neId }),
process: (res: any) => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.enbNum += res.total;
skimState.enbUeNum += res.rows.reduce(
(sum: number, item: any) => sum + item.ueNum,
0
);
}
},
},
],
]);
const requests = neCascaderOptions.value.flatMap(
(ne: any) =>
ne.children
?.map((child: any) => {
const handler = neHandlers.get(child.neType);
return handler
? {
promise: handler.request(child.neId),
process: handler.process,
}
: null;
})
.filter(Boolean) || []
);
const results = await Promise.allSettled(requests.map(r => r.promise));
// 重置
Object.assign(skimState, {
// udmSubNum: 0,
smfUeNum: 0,
imsUeNum: 0,
gnbNum: 0,
gnbUeNum: 0,
enbNum: 0,
enbUeNum: 0,
// imsUserNum: 0,
// voipUserNum: 0,
});
results.forEach((result: any, index: any) => {
if (result.status === 'fulfilled') {
requests[index].process(result.value);
} else {
requests[index].process(0);
}
});
// UDM
listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.udmSubNum = res.total;
}
});
// IMS用户数
listIMSSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.imsUserNum = res.total;
}
});
// VOIP用户数
listUDMAuth({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.voipUserNum = res.total;
}
});
}
/**初始数据函数 */
function loadData() {
fnGetNeState(); // 获取网元状态
userActivitySend();
upfTFSend('0');
upfTFSend('7');
upfTFSend('30');
clearInterval(interval10s.value);
interval10s.value = setInterval(() => {
if (!interval10s.value) return;
if (upfTFActive.value === '0') {
upfTFActive.value = '7';
} else if (upfTFActive.value === '7') {
upfTFActive.value = '30';
} else if (upfTFActive.value === '30') {
upfTFActive.value = '0';
}
upfTFSend('0');
upfTFSend('7');
upfTFSend('30');
}, 10_000);
clearInterval(interval5s.value);
interval5s.value = setInterval(() => {
if (!interval5s.value || !initFlag) return;
fnGetSkim(); // 获取概览信息
fnGetNeState(); // 获取网元状态
}, 10_000);
}
/**栏目信息跳转 */
function fnToRouter(name: string, query?: any) {
router.push({ name, query });
}
/**网元参数 */
let neOtions = ref<Record<string, any>[]>([]);
// UPF实时流量下拉框选择
function fnSelectNe(value: any, option: any) {
upfWhoId.value = value;
reSendUPF(value);
// upfTotalFlow.value.map((item: any) => {
// item.requestFlag = false;
// });
for (var key in upfTotalFlow.value) {
upfTotalFlow.value[key].requestFlag = false;
}
// loadData();
}
let udmNeId = ref<string>('001');
let udmOtions = ref<Record<string, any>[]>([]);
let onlineOtions = ref<Record<string, any>[]>([]);
/**用户数量-选择UDM */
function fnSelectUDM(e: any) {
udmNeId.value = e.key;
listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.udmSubNum = res.total;
}
});
// 更新IMS用户数
listIMSSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.imsUserNum = res.total;
}
});
// 更新VOIP用户数
listUDMAuth({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
skimState.voipUserNum = res.total;
}
});
}
/**资源控制-选择NE */
function fnSelectNeRe(e: any) {
graphNodeClickID.value = e.key;
}
//
// 定义一个方法返回 views 容器
const getPopupContainer = () => {
// 使用 ref 或其他方式来引用你的 views 容器
// 如果 views 容器直接在这个组件内部,你可以使用 ref
// 但在这个例子中,我们假设它是通过类名来获取的
// return document.querySelector('.dashboard-wrapper');
return document.querySelector('.viewport');
};
onMounted(() => {
// // 使用自定义缩放方案
// nextTick(() => {
// // 确保DOM完全渲染
// setTimeout(() => {
// calculateScale();
// }, 100);
//
// // 监听窗口大小变化
// window.addEventListener('resize', handleResize);
// });
neInfoStore
.fnNelist()
.then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
if (res.data.length > 0) {
// UPF
let arr: Record<string, any>[] = [];
res.data.forEach(i => {
if (i.neType === 'UPF') {
arr.push({ value: i.neId, label: i.neName, rmUid: i.rmUid });
}
});
neOtions.value = arr;
if (arr.length > 0) {
//queryParams.neRealId = arr[0].value;
fnSelectNe(arr[0].value, arr[0]);
}
//online Ne
let onlineArr: Record<string, any>[] = [];
// UDM
let arr1: Record<string, any>[] = [];
res.data.forEach((v: any) => {
if (
v.status &&
[
'UDM',
'UPF',
'AUSF',
'PCF',
'SMF',
'AMF',
'OMC',
'SMSC',
'IMS',
'MME',
].includes(v.neType)
) {
onlineArr.push({
value: v.neType + '_' + v.neId,
label: v.neName,
rmUid: v.rmUid,
});
}
if (v.neType === 'UDM') {
arr1.push({ value: v.neId, label: v.neName, rmUid: v.rmUid });
}
});
udmOtions.value = arr1;
onlineOtions.value = onlineArr;
if (arr1.length > 0) {
fnSelectUDM({ key: arr1[0].value });
}
if (onlineArr.length > 0) {
fnSelectNeRe({ key: onlineArr[0].value });
}
// 过滤不可用的网元
neCascaderOptions.value = neInfoStore.getNeCascaderOptions.filter(
(item: any) => {
return ['UDM', 'SMF', 'IMS', 'AMF', 'MME'].includes(item.value);
}
);
if (neCascaderOptions.value.length === 0) {
message.warning({
content: t('common.noData'),
duration: 2,
});
return;
}
}
} else {
message.warning({
content: t('common.noData'),
duration: 2,
});
}
})
.finally(() => {
initFlag = true;
fnGetSkim().then(() => {
loadData();
});
});
});
onBeforeUnmount(() => {
clearInterval(interval10s.value);
interval10s.value = null;
clearInterval(interval5s.value);
interval5s.value = null;
initFlag = false;
// // 清理事件监听和样式
// window.removeEventListener('resize', handleResize);
});
</script>
<template>
<!-- <div class="dashboard-wrapper">-->
<!-- <div class="dashboard-container">-->
<div class="viewport" ref="viewportDom">
<div class="brand">
<div
class="brand-title"
@click="toggle"
:title="t('views.dashboard.overview.fullscreen')"
>
{{ t('views.dashboard.overview.title') }}
<FullscreenExitOutlined v-if="isFullscreen" />
<FullscreenOutlined v-else />
</div>
<div class="brand-desc">{{ appStore.appName }}</div>
</div>
<div class="column">
<!--概览-->
<div class="skim panel">
<div class="inner" style="padding: 0.8rem 1.5rem">
<h3 style="display: flex; align-items: center; justify-content: space-between; margin: 0 0 0.3rem 0; padding: 0; line-height: 1; height: 20px; font-size: 0.833rem">
<span style="display: flex; align-items: center">
<IdcardOutlined style="color: #68d8fe" />&nbsp;&nbsp;
{{ t('views.dashboard.overview.skim.userTitle') }}
</span>
<a-dropdown
:trigger="['click']"
:get-Popup-Container="getPopupContainer"
style="margin-left: 8px"
>
<div class="toDeep-text" style="padding: 2px 6px; font-size: 0.7rem; line-height: 1; height: 16px; display: inline-flex; align-items: center">
{{ udmOtions.find(item => item.value === udmNeId)?.label || 'UDM' }}
<DownOutlined style="margin-left: 4px; font-size: 9px" />
</div>
<template #overlay>
<a-menu @click="fnSelectUDM">
<a-menu-item
v-for="v in udmOtions"
:key="v.value"
:disabled="udmNeId === v.value"
>
{{ v.label }}
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</h3>
<div class="data">
<div
class="item toRouter"
:title="t('views.dashboard.overview.Users')"
>
<div @click="fnToRouter('Sub_2010')">
<UserOutlined
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
/>
{{ skimState.udmSubNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.users') }}
<!-- <a-dropdown-->
<!-- :trigger="['click']"-->
<!-- :get-Popup-Container="getPopupContainer"-->
<!-- >-->
<!-- <div class="toDeep-text">-->
<!-- {{ t('views.dashboard.overview.skim.users') }}-->
<!-- <DownOutlined style="margin-left: 12px; font-size: 12px" />-->
<!-- </div>-->
<!-- <template #overlay>-->
<!-- <a-menu @click="fnSelectUDM">-->
<!-- <a-menu-item-->
<!-- v-for="v in udmOtions"-->
<!-- :key="v.value"-->
<!-- :disabled="udmNeId === v.value"-->
<!-- >-->
<!-- {{ v.label }}-->
<!-- </a-menu-item>-->
<!-- </a-menu>-->
<!-- </template>-->
<!-- </a-dropdown>-->
</span>
</div>
<div
class="item toRouter"
@click="fnToRouter('ImsUDM_2012')"
:title="t('views.dashboard.overview.IMSUsers')"
style="margin: 0 12px"
>
<div>
<UserOutlined
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
/>
{{ skimState.imsUserNum }}
</div>
<span>
{{t('views.dashboard.overview.skim.ims')}}
</span>
</div>
<div
class="item toRouter"
@click="fnToRouter('Voip_2011')"
:title="t('views.dashboard.overview.VoIPUsers')"
>
<div>
<UserOutlined
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
/>
{{ skimState.voipUserNum }}
</div>
<span>
{{t('views.dashboard.overview.skim.voip')}}
</span>
</div>
</div>
</div>
</div>
<div class="skim panel base" v-perms:has="['dashboard:overview:gnbBase']">
<div class="inner">
<h3>
<GlobalOutlined style="color: #68d8fe" />&nbsp;&nbsp; 5G
{{ t('views.dashboard.overview.skim.baseTitle') }}
</h3>
<div class="data">
<div
class="item toRouter"
@click="fnToRouter('BaseStation_2096', { neType: 'AMF' })"
:title="t('views.dashboard.overview.FivegNodeN')"
>
<div style="align-items: flex-start">
<img
:src="svgBase"
style="width: 18px; margin-right: 8px; height: 2rem"
/>
{{ skimState.gnbNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.gnbBase') }}</span>
</div>
<div
class="item toRouter"
@click="fnToRouter('BaseStation_2096', { neType: 'AMF' })"
:title="t('views.dashboard.overview.Fiveusers')"
>
<div style="align-items: flex-start">
<UserOutlined
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
/>
{{ skimState.gnbUeNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.gnbUeNum') }}</span>
</div>
</div>
</div>
</div>
<div class="skim panel base" v-perms:has="['dashboard:overview:enbBase']">
<div class="inner">
<h3>
<GlobalOutlined style="color: #68d8fe" />&nbsp;&nbsp; 4G
{{ t('views.dashboard.overview.skim.baseTitle') }}
</h3>
<div class="data">
<div
class="item toRouter"
@click="fnToRouter('BaseStation_2096', { neType: 'MME' })"
:title="t('views.dashboard.overview.FourgNodeN')"
>
<div style="align-items: flex-start">
<img
:src="svgBase"
style="width: 18px; margin-right: 8px; height: 2rem"
/>
{{ skimState.enbNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.enbBase') }}</span>
</div>
<div
class="item toRouter"
@click="fnToRouter('BaseStation_2096', { neType: 'MME' })"
:title="t('views.dashboard.overview.Fourusers')"
>
<div style="align-items: flex-start">
<UserOutlined
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
/>
{{ skimState.enbUeNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.enbUeNum') }}</span>
</div>
</div>
</div>
</div>
<!-- Online Information -->
<div class="skim panel base" v-perms:has="['dashboard:overview:onlineInfo']">
<div class="inner">
<h3>
<IdcardOutlined style="color: #68d8fe" />&nbsp;&nbsp; {{ t('views.dashboard.overview.skim.onlineinfo') }}
</h3>
<div class="data">
<div
class="item toRouter"
@click="fnToRouter('Ims_2080')"
:title="t('views.dashboard.overview.VoNR')"
v-perms:has="['dashboard:overview:imsUeNum']"
>
<div style="align-items: flex-start">
<img :src="svgUserIMS" style="width: 18px; margin-right: 8px; height: 2rem" />
{{ skimState.imsUeNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.imsUeNum') }}</span>
</div>
<div
class="item toRouter"
@click="fnToRouter('Ue_2081')"
:title="t('views.dashboard.overview.sessions')"
v-perms:has="['dashboard:overview:smfUeNum']"
>
<div style="align-items: flex-start">
<img :src="svgUserSMF" style="width: 18px; margin-right: 8px; height: 2rem" />
{{ skimState.smfUeNum }}
</div>
<span>{{ t('views.dashboard.overview.skim.smfUeNum') }}</span>
</div>
</div>
</div>
</div>
<!-- 用户行为 -->
<!-- <div class="userActivity panel">-->
<!-- <div class="inner">-->
<!-- <h3>-->
<!-- <WhatsAppOutlined style="color: #68d8fe" />&nbsp;&nbsp;-->
<!-- {{ t('views.dashboard.overview.userActivity.title') }}-->
<!-- </h3>-->
<!-- <div class="chart">-->
<!-- <UserActivity />-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<div class="userActivity panel">
<div class="inner">
<h3 style="display: flex; align-items: center">
<DashboardOutlined style="color: #68d8fe" />&nbsp;&nbsp;
{{ t('views.dashboard.overview.resources.title') }}
<a-dropdown
:trigger="['click']"
:get-Popup-Container="getPopupContainer"
>
<div class="toDeep-text">
{{ graphNodeClickID }}
<DownOutlined style="margin-left: 12px; font-size: 12px" />
</div>
<template #overlay>
<a-menu @click="fnSelectNeRe">
<a-menu-item v-for="v in onlineOtions" :key="v.value">
{{ v.label }}
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</h3>
<div class="chart">
<NeResources />
</div>
</div>
</div>
</div>
<div class="column" style="flex: 4; margin: 1.333rem 0.833rem 0">
<!-- 实时流量 -->
<div class="upfFlow panel">
<div class="inner">
<h3
class="toRouter"
:title="t('views.dashboard.overview.UPFjump')"
style="display: flex; align-items: center"
>
<AreaChartOutlined style="color: #68d8fe" />&nbsp;&nbsp;
<span @click="fnToRouter('GoldTarget_2104')">{{
t('views.dashboard.overview.upfFlow.title')
}}</span>
<a-select
v-model:value="upfWhoId"
:options="neOtions"
:get-Popup-Container="getPopupContainer"
class="toDeep"
style="width: 100px; color: #fff; margin-left: auto"
@change="fnSelectNe"
/>
</h3>
<div class="chart">
<UPFFlow />
</div>
</div>
</div>
<!-- 网络拓扑 -->
<div class="topology panel">
<div class="inner">
<h3
class="toRouter"
@click="fnToRouter('TopologyArchitecture_2128')"
:title="t('views.dashboard.overview.Networkjump')"
>
<span>
<ApartmentOutlined style="color: #68d8fe" />&nbsp;&nbsp;
{{ t('views.dashboard.overview.topology.title') }}
</span>
<span>
{{ t('views.dashboard.overview.topology.normal') }}:
<span class="normal"> {{ graphNodeStateNum[0] }} </span>
{{ t('views.dashboard.overview.topology.abnormal') }}:
<span class="abnormal"> {{ graphNodeStateNum[1] }} </span>
</span>
</h3>
<div class="chart">
<Topology />
</div>
</div>
</div>
</div>
<div class="column">
<!-- 流量统计 -->
<div class="upfFlowTotal panel">
<div class="inner">
<h3>
<span>
<SwapOutlined style="color: #68d8fe" />&nbsp;&nbsp;
{{ t('views.dashboard.overview.upfFlowTotal.title') }}
</span>
<!-- 筛选 -->
<div class="filter">
<span
:data-key="v"
:class="{ active: upfTFActive === v }"
v-for="v in ['0', '7', '30']"
:key="v"
@click="
() => {
upfTFActive = v;
}
"
>
{{
v === '0'
? '24' + t('common.units.hour')
: v + t('common.units.day')
}}
</span>
</div>
</h3>
<div class="chart">
<!-- 数据 -->
<div class="data">
<div class="item">
<span>
<ArrowUpOutlined style="color: #597ef7" />
{{ t('views.dashboard.overview.upfFlowTotal.up') }}
</span>
<h4>{{ upfTotalFlow[upfTFActive].upFrom }}</h4>
</div>
<div class="item">
<span>
<ArrowDownOutlined style="color: #52c41a" />
{{ t('views.dashboard.overview.upfFlowTotal.down') }}
</span>
<h4>{{ upfTotalFlow[upfTFActive].downFrom }}</h4>
</div>
</div>
</div>
</div>
</div>
<!-- 告警统计 -->
<div class="alarmType panel">
<div class="inner">
<h3
class="toRouter"
@click="fnToRouter('ActiveAlarm_2088')"
:title="t('views.dashboard.overview.Alarmjump')"
>
<PieChartOutlined style="color: #68d8fe" />&nbsp;&nbsp;
{{ t('views.dashboard.overview.alarmTypeBar.alarmSum') }}
</h3>
<div class="chart">
<AlarnTypeBar />
</div>
</div>
</div>
<!-- &lt;!&ndash; 资源情况 &ndash;&gt;-->
<!-- <div class="resources panel">-->
<!-- <div class="inner">-->
<!-- <h3 style="display: flex; align-items: center">-->
<!-- <DashboardOutlined style="color: #68d8fe" />&nbsp;&nbsp;-->
<!-- {{ t('views.dashboard.overview.resources.title') }}-->
<!-- <a-dropdown-->
<!-- :trigger="['click']"-->
<!-- :get-Popup-Container="getPopupContainer"-->
<!-- >-->
<!-- <div class="toDeep-text">-->
<!-- {{ graphNodeClickID }}-->
<!-- <DownOutlined style="margin-left: 12px; font-size: 12px" />-->
<!-- </div>-->
<!-- <template #overlay>-->
<!-- <a-menu @click="fnSelectNeRe">-->
<!-- <a-menu-item v-for="v in onlineOtions" :key="v.value">-->
<!-- {{ v.label }}-->
<!-- </a-menu-item>-->
<!-- </a-menu>-->
<!-- </template>-->
<!-- </a-dropdown>-->
<!-- </h3>-->
<!-- <div class="chart">-->
<!-- <NeResources />-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</div>
</div>
<!-- </div>-->
<!-- </div>-->
</template>
<style lang="less" scoped>
@import url('./css/index.css');
/* Dashboard 页面专用包装器,不影响其他页面 */
//.dashboard-wrapper {
// position: absolute;
// top: 0;
// left: 0;
// width: 100%;
// height: 100%;
// background: #0b1023;
// display: flex;
// align-items: center;
// justify-content: center;
// padding: 20px;
// overflow: hidden;
// box-sizing: border-box;
//}
//
//.dashboard-container {
// width: 1400px;
// height: 900px;
// background: #0b1023;
// position: relative;
// overflow: visible;
// flex-shrink: 0;
//}
.toDeep {
--editor-background-color: blue;
}
.toDeep :deep(.ant-select-selector) {
background-color: #101129;
border: none;
}
.toDeep :deep(.ant-select-arrow) {
color: #fff;
}
.toDeep :deep(.ant-select-selection-item) {
color: #fff;
}
.toDeep-text {
color: #4c9bfd !important;
font-size: 0.844rem !important;
position: relative !important;
line-height: 2rem !important;
white-space: nowrap !important;
text-align: start !important;
text-overflow: ellipsis !important;
overflow: hidden !important;
}
</style>