WholeProcessPlatform/frontend/src/modules/rightSearchDrawer/monitoringTable/components/VideoInfo.vue

190 lines
4.7 KiB
Vue
Raw Normal View History

<template>
<SidePanelItem :title="title" :shrink="false">
<template #title-right-content>
<a-select
v-model:value="currentStcd"
:options="videoOptions"
:loading="loading"
show-search
:placeholder="placeholder"
size="small"
style="width: 200px"
:filter-option="filterOption"
@change="handleSelectVideo"
/>
</template>
<div class="video-wrapper">
<a-spin :spinning="loading">
<LiveVideoBox
v-if="currentVideo"
:video-data="currentVideo"
monitor-type="live"
:show-title="false"
height="100%"
/>
<a-empty
v-else-if="!loading"
description="暂无数据"
class="flex align-center justify-center h-full flex-col"
/>
</a-spin>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { getVideoList } from '@/api/mapModal';
import { useModelStore } from '@/store/modules/model';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import LiveVideoBox from '@/views/shiPinJianKong/components/LiveVideoBox.vue';
const modelStore = useModelStore();
const loading = ref(false);
const videoList = ref<any[]>([]);
const currentStcd = ref<string | undefined>(undefined);
const currentVideo = ref<any>(null);
const props = defineProps({
title: {
type: String,
default: '实时视频'
},
placeholder: {
type: String,
default: '请选择视频'
}
});
// 下拉框选项label 显示站名value 使用 stcd
const videoOptions = computed(() =>
videoList.value.map(item => ({ label: item.stnm, value: item.stcd }))
);
const filterOption = (input: string, option?: any) => {
return (option?.label ?? '').toLowerCase().includes(input.toLowerCase());
};
// 组装 LiveVideoBox 需要的视频数据
const buildVideoData = (item: any) => ({
flnm: item.stnm,
stnm: item.stnm,
url: item.url,
key: item.stcd,
...item
});
// 拉取视频列表(查询参数取 modelStore.selectedAnchorPoint
const fetchVideoList = async () => {
const stcd = modelStore.selectedAnchorPoint?.stcd;
if (!stcd) {
videoList.value = [];
currentVideo.value = null;
currentStcd.value = undefined;
return;
}
loading.value = true;
try {
const params = {
filter: {
logic: 'and',
filters: [
{ field: 'sttpCode', operator: 'startswith', value: 'VD_' },
{
logic: 'or',
filters: [
{
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: stcd
},
{
field: 'stcd',
operator: 'eq',
dataType: 'string',
value: stcd
},
{
field: 'fhstcd',
operator: 'eq',
dataType: 'string',
value: stcd
},
{
field: 'stCode',
operator: 'eq',
dataType: 'string',
value: stcd
}
]
}
]
},
select: ['stcd', 'stnm', 'sttpCode', 'sttpName', 'playWay', 'url'],
sort: [{ field: 'stnm', dir: 'asc' }]
};
const res: any = await getVideoList(params);
const list = res?.data?.data || [];
videoList.value = list;
// 默认选中第一条并播放
if (list.length > 0) {
const first = list[0];
currentStcd.value = first.stcd;
currentVideo.value = buildVideoData(first);
} else {
currentStcd.value = undefined;
currentVideo.value = null;
}
} catch (error) {
console.error('获取视频列表失败:', error);
videoList.value = [];
currentVideo.value = null;
currentStcd.value = undefined;
} finally {
loading.value = false;
}
};
// 下拉框切换视频
const handleSelectVideo = (stcd: string) => {
const item = videoList.value.find(v => v.stcd === stcd);
if (item) currentVideo.value = buildVideoData(item);
};
// 选中点位变化时重新拉取视频列表;初始已有点位时立即加载
watch(
() => modelStore.selectedAnchorPoint?.stcd,
(newStcd, oldStcd) => {
if (!newStcd) {
videoList.value = [];
currentVideo.value = null;
currentStcd.value = undefined;
return;
}
if (newStcd !== oldStcd) fetchVideoList();
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
.video-wrapper {
width: 100%;
height: 240px;
border-radius: 4px;
overflow: hidden;
:deep(.ant-spin-nested-loading) {
height: 100%;
.ant-spin-container {
height: 100%;
}
}
}
</style>