| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- <template>
- <div class="content--r--t">
- <div class="content--inner">
- <div class="content--inner--title">
- <h3>장비 현황 <span class="color--blue">({{ neRanList?.length || 0 }})</span></h3>
- <div
- v-if="neRanList && neRanList?.length > 0"
- class="status--wrap"
- >
- <div class="map">
- <v-btn
- class="custom-btn btn-blue btn-map"
- @click="isShowRanGroupDtailModal = true"
- >
- <i class="ico" />위치보기
- </v-btn>
- </div>
- </div>
- </div>
- <div
- v-if="neRanList?.length > 0"
- class="content--inner--content"
- >
- <div class="db--status">
- <swiper
- :slides-per-view="5"
- :space-between="spaceBetween"
- :pagination="paginationOptions"
- :navigation="navigationOptions"
- :modules="[Pagination, Navigation]"
- class="mySwiper"
- >
- <swiper-slide
- v-for="(ran, idx) in neRanList"
- :key="idx"
- >
- <div class="equip--card--wrap">
- <div :class="['equip--card', ran.isConnected ? '' : 'dis']">
- <div class="equip--icon" />
- <div class="equip--txt">
- <p>{{ ran.neName }}</p>
- <span>IP : XXXX.XXXX.XXXX.XXXX</span>
- <!-- <span>{{ ran.ip ? `IP : ${ran.ip}`: '' }}</span> -->
- </div>
- <ul class="equip--st">
- <li><i class="circle" /><p>STATUS</p><span>{{ ran.isConnected ? 'ACTIVE' : '' }}</span></li>
- <li
- v-for="(kpi, index) in ran.kpiItems"
- :key="`tb-ran-swiper-${index}`"
- >
- <i
- class="circle"
- :class="getBodyLevelClass(kpi.val)"
- />
- <p>{{ kpi.label }}</p>
- <span>{{ toRoundFix(kpi.val, 2) }}%</span>
- </li>
- </ul>
- </div>
- </div>
- </swiper-slide>
- <div class="swiper-controls">
- <div class="swiper-button-prev" />
- <div class="swiper-pagination" />
- <div class="swiper-button-next" />
- </div>
- </swiper>
- </div>
- </div>
- <!-- 데이터 없을 경우 -->
- <div
- v-else
- class="content--inner--content no--data"
- >
- <i class="ico" />데이터가 없습니다.
- </div>
- </div>
- <ranGroupDetailModal
- v-if="isShowRanGroupDtailModal"
- :tenant-name="selectedTenantName"
- @close-modal="isShowRanGroupDtailModal=false"
- />
- </div>
- </template>
- <script setup>
- /***********************
- * import
- ************************/
- import { useI18n } from "vue-i18n"
- import apiUrl from '@/composables/useApi';
- import useAxios from '@/composables/useAxios';
- import useUtil from '@/composables/useUtil';
- import ranGroupDetailModal from "./common/ranGroupDetailModal.vue";
- import { Swiper, SwiperSlide } from 'swiper/vue';
- import { Navigation, Pagination } from 'swiper/modules';
- import 'swiper/css';
- import 'swiper/swiper-bundle.css'
- import testJson from "@/components/home/dashboard/test.json"
- /***********************
- * plugins inject
- ************************/
- const { $toast, $log, $dayjs, $eventBus } = useNuxtApp()
- // props
- const props = defineProps({})
- // 참조가능 데이터 설정
- defineExpose({
- fnInit,
- })
- // 발신 이벤트 선언
- const emit = defineEmits([""]);
- const i18n = useI18n();
- /***********************
- * data & created
- ************************/
- // 위치보기 모달 show 여부
- const isShowRanGroupDtailModal = ref(false);
- // 선택된 테넌트명
- const selectedTenantName = ref('');
- // 장비 목록
- const neRanList = ref([]);
- const remToPx = () => parseFloat(getComputedStyle(document.documentElement).fontSize);
- const spaceRem = 0.94; // 원하는 rem 값
- const spaceRemPx = spaceRem * remToPx();
- const spaceBetween = spaceRemPx;
-
- // swiper option
- const paginationOptions = {
- el: '.swiper-pagination',
- clickable: true,
- type: 'bullets',
- bulletClass: 'swiper-pagination-bullet',
- bulletActiveClass: 'swiper-pagination-bullet-active',
- }
- const navigationOptions = {
- nextEl: '.swiper-button-next',
- prevEl: '.swiper-button-prev',
- clickable: true,
- };
- /***********************
- * Methods
- ************************/
- function fnInit(tenantName) {
- console.log('::::::: tenantRan init ::::' , tenantName)
- selectedTenantName.value = tenantName;
- fnGeoTenantNeInfo(tenantName);
- }
- /**
- * P5G RAN Ne 정보 조회
- */
- function fnGeoTenantNeInfo(tenantName) {
- return new Promise((resolve, reject) => {
- const params = {
- tenantName: tenantName
- }
- useAxios().post(useApi.tenantNeInfo, params).then((res) => {
- const {resCode, resMsg, data} = res.data;
- if(resCode == 200) {
- // 테스트를 위한 테스트 코드 (삭제 필수)
- // fnParseData([...(data?.items || []), ...testJson.ranNeGroupList.data.items])
- fnParseData(data.items || [])
- $log.debug("[tenantDashboard][fnGeoTenantNeInfo][success]")
- resolve();
- } else {
- $log.debug("[tenantDashboard][fnGeoTenantNeInfo][error]", `[${resCode}] ${resMsg}`);
- reject()
- }
- }).catch((error)=>{
- $log.debug("[tenantDashboard][fnGeoTenantNeInfo][error]", error)
- useErrorHandler().fnSetCommErrorHandle(error, fnGeoTenantNeInfo)
- reject()
- }).finally(()=>{
- $log.debug("[tenantDashboard][fnGeoTenantNeInfo][finished]")
- })
- // fnParseData([...testJson.ranNeGroupList.data.items]);
- resolve();
- })
- }
- const fnParseData = (items = []) => {
- console.log("#################### fnParseData", items)
-
- // 테넌트 필터링
- const tenantNeItems = items.filter((i) => i.tenantName == selectedTenantName.value);
-
- // 데이터 가공
- neRanList.value = tenantNeItems.map((item) => {
- // KPI 정보 셋팅 - TODO: CPU, MEM 외의 값이 추가되면 여기에 추가
- const { cpu, mem } = item;
- const kpiItems = [];
-
- if(cpu) {
- const objCpu = typeof cpu === 'string' ? JSON.parse(cpu) : cpu;
- if(objCpu && objCpu[`AVG_CPU_L`]){
- kpiItems.push({label: 'CPU', val: objCpu[`AVG_CPU_L`] || 0})
- item.cpu = objCpu;
- }
- }
- if(mem) {
- const objMem = typeof mem === 'string' ? JSON.parse(mem) : mem ;
- if(objMem && objMem['AVG_MEM_L']){
- kpiItems.push({label: 'MEMORY', val: objMem['AVG_MEM_L'] || 0})
- item.mem = objMem;
- }
- }
- // disconnected 셋팅 - Todo: connect 구분을 위한 값 확인 필요 > 20240
- const isConnected = true;
-
-
- return {
- ...item,
- kpiItems,
- isConnected,
- }
- })
- console.log("#################### neRanList 셋팅완료 ", neRanList.value)
- }
- const toRoundFix = (data, digit) => parseFloat(data).toFixed(digit);
- // 세부 데이터 상태값
- const getBodyLevelClass = (val) => {
- if(val >= 95) return 'critical';
- else if(val >= 90) return 'major';
- else if(val >= 85) return 'minor';
- else return 'normal';
- }
- </script>
|