101 lines
3.3 KiB
Vue
101 lines
3.3 KiB
Vue
<script setup lang="ts">
|
|
import { getAllPushApi, type NdmServerResultVO, type Station } from '@/apis';
|
|
import { DEVICE_TYPE_LITERALS, tryGetDeviceType } from '@/enums';
|
|
import { useSettingStore } from '@/stores';
|
|
import { useQuery, useQueryClient } from '@tanstack/vue-query';
|
|
import { NCard, NCollapse, NCollapseItem, NFlex, NTag, NText } from 'naive-ui';
|
|
import { storeToRefs } from 'pinia';
|
|
import { computed, toRefs, watch } from 'vue';
|
|
|
|
const props = defineProps<{
|
|
ndmDevice: NdmServerResultVO;
|
|
station: Station;
|
|
}>();
|
|
|
|
const settingStore = useSettingStore();
|
|
const { activeRequests } = storeToRefs(settingStore);
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
const { ndmDevice, station } = toRefs(props);
|
|
|
|
const deviceType = computed(() => tryGetDeviceType(ndmDevice.value.deviceType));
|
|
|
|
const showCard = computed(() => deviceType.value === DEVICE_TYPE_LITERALS.ndmMediaServer);
|
|
|
|
const SERVER_STREAM_PUSH_KEY = 'server-stream-push-query';
|
|
|
|
const { data: streamPushes } = useQuery({
|
|
queryKey: computed(() => [SERVER_STREAM_PUSH_KEY, ndmDevice.value.id, ndmDevice.value.lastDiagTime]),
|
|
enabled: computed(() => activeRequests.value && showCard.value),
|
|
refetchInterval: 30 * 1000,
|
|
gcTime: 0,
|
|
queryFn: async ({ signal }) => {
|
|
const streamPushes = await getAllPushApi({ stationCode: station.value.code, signal });
|
|
return streamPushes;
|
|
},
|
|
});
|
|
watch(activeRequests, (active) => {
|
|
if (!active) {
|
|
queryClient.cancelQueries({ queryKey: [SERVER_STREAM_PUSH_KEY] });
|
|
}
|
|
});
|
|
|
|
interface StreamPushStat {
|
|
ip: string;
|
|
port: number | null;
|
|
ssrc: string | null;
|
|
channelIds: string[];
|
|
}
|
|
const streamPushStat = computed(() => {
|
|
const stat: StreamPushStat[] = [];
|
|
streamPushes.value?.forEach((push) => {
|
|
if (!push.ip || !push.channelId) return;
|
|
const existIndex = stat.findIndex((item) => item.ip === push.ip);
|
|
if (existIndex === -1) {
|
|
stat.push({ ip: push.ip, port: push.port, ssrc: push.ssrc, channelIds: [push.channelId] });
|
|
} else {
|
|
const statItem = stat[existIndex];
|
|
if (!statItem) return;
|
|
statItem.channelIds.push(push.channelId);
|
|
}
|
|
});
|
|
return stat;
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<NCard v-if="showCard" hoverable size="small">
|
|
<template #header>
|
|
<span>推流统计</span>
|
|
</template>
|
|
<template #default>
|
|
<template v-if="!activeRequests">
|
|
<span>-</span>
|
|
</template>
|
|
<template v-else>
|
|
<NFlex vertical>
|
|
<NText depth="3">共 {{ streamPushStat.length }} 个推流目标</NText>
|
|
<NCollapse v-if="streamPushStat.length > 0">
|
|
<NCollapseItem v-for="{ ip, port, ssrc, channelIds } in streamPushStat" :key="`${ip}:${port}:${ssrc}`" :name="`${ip}:${port}:${ssrc}`">
|
|
<template #header>
|
|
<span>{{ ip }}</span>
|
|
</template>
|
|
<template #header-extra>
|
|
<span>{{ channelIds.length }} 路</span>
|
|
</template>
|
|
<template #default>
|
|
<NFlex>
|
|
<NTag v-for="channelId in channelIds" :key="channelId" size="small" type="info" :bordered="false">{{ channelId }}</NTag>
|
|
</NFlex>
|
|
</template>
|
|
</NCollapseItem>
|
|
</NCollapse>
|
|
</NFlex>
|
|
</template>
|
|
</template>
|
|
</NCard>
|
|
</template>
|
|
|
|
<style scoped lang="scss"></style>
|