WholeProcessPlatform/frontend/src/modules/rightSearchDrawer/monitoringTable/components/VideoInfo.vue
2026-08-20 16:55:09 +08:00

190 lines
4.7 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.

<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>