373 lines
10 KiB
Vue
373 lines
10 KiB
Vue
<script setup lang="ts">
|
|
import { parseDuration, parseDateToStr } from '@/utils/date-utils';
|
|
import { eventData, eventId } from '../../hooks/useUserActivity';
|
|
import useI18n from '@/hooks/useI18n';
|
|
import useDictStore from '@/store/modules/dict';
|
|
import { onMounted, reactive } from 'vue';
|
|
const { t } = useI18n();
|
|
const { getDict } = useDictStore();
|
|
|
|
/**字典数据 */
|
|
let dict: {
|
|
/**CDR SIP响应代码类别类型 */
|
|
cdrSipCode: DictType[];
|
|
/**CDR 呼叫类型 */
|
|
cdrCallType: DictType[];
|
|
/**UE 事件认证代码类型 */
|
|
ueAauthCode: DictType[];
|
|
/**UE 事件类型 */
|
|
ueEventType: DictType[];
|
|
/**UE 事件CM状态 */
|
|
ueEventCmState: DictType[];
|
|
} = reactive({
|
|
cdrSipCode: [],
|
|
cdrCallType: [],
|
|
ueAauthCode: [],
|
|
ueEventType: [],
|
|
ueEventCmState: [],
|
|
});
|
|
|
|
onMounted(() => {
|
|
// 初始字典数据
|
|
Promise.allSettled([
|
|
getDict('cdr_sip_code'),
|
|
getDict('cdr_call_type'),
|
|
getDict('ue_auth_code'),
|
|
getDict('ue_event_type'),
|
|
getDict('ue_event_cm_state'),
|
|
]).then(resArr => {
|
|
if (resArr[0].status === 'fulfilled') {
|
|
dict.cdrSipCode = resArr[0].value;
|
|
}
|
|
if (resArr[1].status === 'fulfilled') {
|
|
dict.cdrCallType = resArr[1].value;
|
|
}
|
|
if (resArr[2].status === 'fulfilled') {
|
|
dict.ueAauthCode = resArr[2].value;
|
|
}
|
|
if (resArr[3].status === 'fulfilled') {
|
|
dict.ueEventType = resArr[3].value;
|
|
}
|
|
if (resArr[4].status === 'fulfilled') {
|
|
dict.ueEventCmState = resArr[4].value;
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="activty">
|
|
<template v-for="item in eventData" :key="item.eId">
|
|
<!-- CDR事件IMS -->
|
|
<div
|
|
class="card-cdr"
|
|
:class="{ active: item.eId === eventId }"
|
|
v-if="item.eType === 'ims_cdr'"
|
|
>
|
|
<div class="card-cdr-item">
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.type') }}:
|
|
<span>
|
|
<DictTag
|
|
:options="dict.cdrCallType"
|
|
:value="item.data.callType"
|
|
/>
|
|
</span>
|
|
</div>
|
|
<div></div>
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
|
<span :title="item.data.releaseTime">
|
|
{{
|
|
typeof item.data.releaseTime === 'number'
|
|
? parseDateToStr(+item.data.releaseTime * 1000)
|
|
: item.data.releaseTime
|
|
}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-cdr-item">
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.caller') }}:
|
|
<span :title="item.data.callerParty">
|
|
{{ item.data.callerParty }}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.called') }}:
|
|
<span :title="item.data.calledParty">
|
|
{{ item.data.calledParty }}
|
|
</span>
|
|
</div>
|
|
<div v-if="item.data.callType !== 'sms'">
|
|
{{ t('views.dashboard.overview.userActivity.duration') }}:
|
|
<span>{{ parseDuration(item.data.callDuration) }}</span>
|
|
</div>
|
|
<div v-else></div>
|
|
</div>
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span v-if="item.data.callType !== 'sms'">
|
|
<DictTag
|
|
:options="dict.cdrSipCode"
|
|
:value="item.data.cause"
|
|
value-default="0"
|
|
/>
|
|
</span>
|
|
<span v-else>
|
|
{{ t('views.dashboard.overview.userActivity.resultOK') }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<!-- UE事件AMF -->
|
|
<div
|
|
class="card-ue"
|
|
:class="{ active: item.eId === eventId }"
|
|
v-if="item.eType === 'amf_ue'"
|
|
>
|
|
<div class="card-ue-item">
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.type') }}:
|
|
<span>
|
|
<DictTag :options="dict.ueEventType" :value="item.type" />
|
|
</span>
|
|
</div>
|
|
<div>
|
|
IMSI: <span :title="item.data.imsi">{{ item.data.imsi }}</span>
|
|
</div>
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
|
<template v-if="item.data?.time">
|
|
{{ item.data.time }}
|
|
</template>
|
|
<template v-else>
|
|
{{ parseDateToStr(+item.data.timestamp * 1000) }}
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-ue-w33" 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 v-if="item.type === 'auth-result'">
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span>
|
|
<DictTag :options="dict.ueAauthCode" :value="item.data.result" />
|
|
</span>
|
|
</div>
|
|
<div v-if="item.type === 'detach'">
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span>{{ t('views.dashboard.overview.userActivity.resultOK') }}</span>
|
|
</div>
|
|
<div class="card-ue-w33" v-if="item.type === 'cm-state'">
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span>
|
|
<DictTag :options="dict.ueEventCmState" :value="item.data.result" />
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<!-- UE事件MME -->
|
|
<div
|
|
class="card-ue"
|
|
:class="{ active: item.eId === eventId }"
|
|
v-if="item.eType === 'mme_ue'"
|
|
>
|
|
<div class="card-ue-item">
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.type') }}:
|
|
<span v-if="item.type === 'cm-state'">
|
|
{{
|
|
dict.ueEventType
|
|
.find(s => s.value === item.type)
|
|
?.label.replace('CM', 'ECM')
|
|
}}
|
|
</span>
|
|
<span v-else>
|
|
<DictTag :options="dict.ueEventType" :value="item.type" />
|
|
</span>
|
|
</div>
|
|
<div>
|
|
IMSI: <span :title="item.data?.imsi">{{ item.data?.imsi }}</span>
|
|
</div>
|
|
<div>
|
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
|
<span :title="item.data?.timestamp">
|
|
{{
|
|
typeof item.data?.timestamp === 'number'
|
|
? parseDateToStr(+item.data?.timestamp * 1000)
|
|
: item.data?.timestamp
|
|
}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-ue-w33" v-if="item.type === 'auth-result'">
|
|
<div>
|
|
ENB ID: <span>{{ item.data.eNBID }}</span>
|
|
</div>
|
|
<div>
|
|
Cell ID: <span>{{ item.data.cellID }}</span>
|
|
</div>
|
|
<div>
|
|
TAC ID: <span>{{ item.data.tacID }}</span>
|
|
</div>
|
|
</div>
|
|
<div v-if="item.type === 'auth-result'">
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span>
|
|
<DictTag :options="dict.ueAauthCode" :value="item.data.result" />
|
|
</span>
|
|
</div>
|
|
<div v-if="item.type === 'detach'">
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span>{{ t('views.dashboard.overview.userActivity.resultOK') }}</span>
|
|
</div>
|
|
<div class="card-ue-w33" v-if="item.type === 'cm-state'">
|
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
|
<span>
|
|
<DictTag :options="dict.ueEventCmState" :value="item.data.result" />
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="less" scoped>
|
|
.activty {
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
height: 94%;
|
|
color: #61a8ff;
|
|
font-size: 0.75rem;
|
|
& .card-ue {
|
|
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%;
|
|
white-space: nowrap;
|
|
text-align: start;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
&-w33 {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: flex-start;
|
|
& > div {
|
|
width: 33%;
|
|
}
|
|
}
|
|
}
|
|
|
|
& .card-cdr {
|
|
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 {
|
|
flex: 1;
|
|
white-space: nowrap;
|
|
text-align: start;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
}
|
|
|
|
& .active {
|
|
color: #faad14;
|
|
border: 1px #faad14 solid;
|
|
animation: backInRight 0.3s alternate;
|
|
& span {
|
|
color: #faad14;
|
|
}
|
|
}
|
|
|
|
/* 兼容当行显示字内容 */
|
|
@media (max-width: 1720px) {
|
|
& .card-cdr {
|
|
&-item {
|
|
display: block;
|
|
& > div {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
& .card-ue {
|
|
&-item {
|
|
display: block;
|
|
& > div {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 修改滚动条的样式 */
|
|
&::-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>
|