视频监控视频分布按钮添加

This commit is contained in:
扈兆增 2026-07-15 15:39:35 +08:00
parent 6e5dc9188d
commit d972a42f96
3 changed files with 309 additions and 139 deletions

View File

@ -108,9 +108,11 @@
</div> </div>
</div> </div>
<div class="record-info"> <div class="record-info">
<div class="record-name">{{ item.name }}</div> <div class="record-name">
{{ item.name || item.titleName || item.stnm }}
</div>
<div class="record-time"> <div class="record-time">
{{ dayjs(item.time).format('YYYY-MM-DD HH') }} {{ dayjs(item.time || item.tm).format('YYYY-MM-DD HH') }}
</div> </div>
</div> </div>
</div> </div>
@ -351,7 +353,7 @@ const handlePlayRecord = (record: any) => {
const videoData = { const videoData = {
flnm: record.name, flnm: record.name,
stnm: record.name, stnm: record.name,
url: record.url, url: record.url || record.flpth,
key: record.id, key: record.id,
...record ...record
}; };

View File

@ -96,6 +96,11 @@
v-for="item in anchorPointOptions" v-for="item in anchorPointOptions"
:key="item.stcd" :key="item.stcd"
:value="item.stcd" :value="item.stcd"
:title="
[item.stnm || item.ennm, item.baseName]
.filter(Boolean)
.join(',')
"
>{{ item.stnm || item.ennm }} >{{ item.stnm || item.ennm }}
{{ {{
item.baseName ? ',' + item.baseName : '' item.baseName ? ',' + item.baseName : ''

View File

@ -1,5 +1,8 @@
<template> <template>
<div class="shiPinJianKongZhuanTi-page"> <div
class="shiPinJianKongZhuanTi-page"
:class="{ 'shiPinJianKongZhuanTi-page-distribution': isDistribution }"
>
<a-tabs <a-tabs
v-model:activeKey="activeTab" v-model:activeKey="activeTab"
:tabBarGutter="32" :tabBarGutter="32"
@ -8,21 +11,34 @@
> >
<template #rightExtra> <template #rightExtra>
<a-button type="default" class="mr-2" @click="handleAction"> <a-button type="default" class="mr-2" @click="handleAction">
<template #icon><i class="iconfont icon-fenbu mr-1" /></template> <template #icon
查看分布 ><i
class="iconfont mr-1"
:class="!isDistribution ? 'icon-fenbu' : 'icon-left1'"
/></template>
{{ !isDistribution ? '视频分布' : '取消' }}
</a-button> </a-button>
</template> </template>
<a-tab-pane v-for="tab in tabs" :key="tab.key"> <a-tab-pane v-for="tab in tabs" :key="tab.key">
<template #tab> {{ tab.title }}({{ tab.data?.count_sttpCode || 0 }}) </template> <template #tab>
{{ tab.title }}({{ tab.data?.count_sttpCode || 0 }})
</template>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
<div class="tabs-content"> <JidiSelectorMod
class="shiPinJianKongZhuanTi-JidiSelectorMod"
v-if="isDistribution"
/>
<div class="tabs-content" v-show="!isDistribution">
<!-- 顶部标题和图标选择区域 --> <!-- 顶部标题和图标选择区域 -->
<div class="content-header"> <div class="content-header">
<div class="header-left"> <div class="header-left">
<span class="title"> <a-divider type="vertical"></a-divider> </span> <span class="title">
<a-divider type="vertical"></a-divider> </span
>
</div> </div>
<div class="header-right"> <div class="header-right">
<a-radio-group v-model:value="viewLayout" button-style="solid"> <a-radio-group v-model:value="viewLayout" button-style="solid">
@ -104,7 +120,11 @@
v-model:expandedKeys="expandedKeys" v-model:expandedKeys="expandedKeys"
v-model:checkedKeys="checkedKeys" v-model:checkedKeys="checkedKeys"
:tree-data="treeData" :tree-data="treeData"
:field-names="{ name: 'name', key: 'key', children: 'children' }" :field-names="{
name: 'name',
key: 'key',
children: 'children'
}"
checkable checkable
block-node block-node
:show-icon="monitorType === 'live'" :show-icon="monitorType === 'live'"
@ -115,7 +135,8 @@
<!-- 只在实时视频模式且最后一层没有children显示在线/离线图标 --> <!-- 只在实时视频模式且最后一层没有children显示在线/离线图标 -->
<template <template
v-if=" v-if="
monitorType === 'live' && (!children || children.length === 0) monitorType === 'live' &&
(!children || children.length === 0)
" "
> >
<i <i
@ -138,12 +159,16 @@
<!-- 中间视频内容区域 --> <!-- 中间视频内容区域 -->
<div class="center-panel"> <div class="center-panel">
<div class="video-grid" :class="`layout-${viewLayout}`"> <div class="video-grid" :class="`layout-${viewLayout}`">
<div v-for="index in parseInt(viewLayout)" :key="index" class="video-item"> <div
v-for="index in parseInt(viewLayout)"
:key="index"
class="video-item"
>
<LiveVideoBox <LiveVideoBox
:video-data="videoList[index - 1]" :video-data="videoList[index - 1]"
:monitor-type="monitorType" :monitor-type="monitorType"
height="100%" height="100%"
@close="(nodeKey) => removeVideo(index - 1, nodeKey)" @close="nodeKey => removeVideo(index - 1, nodeKey)"
/> />
</div> </div>
</div> </div>
@ -152,7 +177,9 @@
<!-- 右侧回放面板仅录像模式显示 --> <!-- 右侧回放面板仅录像模式显示 -->
<div v-if="monitorType === 'record'" class="right-panel"> <div v-if="monitorType === 'record'" class="right-panel">
<div class="replay-header"> <div class="replay-header">
<span class="replay-title"><a-divider type="vertical" />回放列表</span> <span class="replay-title"
><a-divider type="vertical" />回放列表</span
>
</div> </div>
<!-- 时间选择 --> <!-- 时间选择 -->
<div class="date-picker"> <div class="date-picker">
@ -168,7 +195,10 @@
<div class="record-list"> <div class="record-list">
<a-spin :spinning="recordLoading" wrapperClassName="record-spin"> <a-spin :spinning="recordLoading" wrapperClassName="record-spin">
<!-- 空状态显示 --> <!-- 空状态显示 -->
<div v-if="!recordList || recordList.length === 0" class="empty-record"> <div
v-if="!recordList || recordList.length === 0"
class="empty-record"
>
<a-empty /> <a-empty />
</div> </div>
@ -183,16 +213,18 @@
<div class="record-image-wrapper"> <div class="record-image-wrapper">
<a-image :src="item.imgPath" :preview="false" alt="" /> <a-image :src="item.imgPath" :preview="false" alt="" />
</div> </div>
<div class="sp_btn"><i class="icon iconfont icon-play"></i></div> <div class="sp_btn">
<i class="icon iconfont icon-play"></i>
</div>
<a-tooltip placement="top"> <a-tooltip placement="top">
<template #title> <template #title>
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<div>{{ dayjs(item.time).format("YYYY-MM-DD HH") }}</div> <div>{{ dayjs(item.time).format('YYYY-MM-DD HH') }}</div>
</template> </template>
<div class="record-info"> <div class="record-info">
<div class="record-name">{{ item.name }}</div> <div class="record-name">{{ item.name }}</div>
<div class="record-time"> <div class="record-time">
{{ dayjs(item.time).format("YYYY-MM-DD HH") }} {{ dayjs(item.time).format('YYYY-MM-DD HH') }}
</div> </div>
</div> </div>
</a-tooltip> </a-tooltip>
@ -207,40 +239,53 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue"; import { ref, onMounted, onUnmounted, watch } from 'vue';
import { message } from "ant-design-vue"; import { message } from 'ant-design-vue';
import { import {
baseMsstbprpt, baseMsstbprpt,
envVdTreeGetKendoListCust, envVdTreeGetKendoListCust,
envVdRunDataGetKendoList, envVdRunDataGetKendoList
} from "@/api/shiPinJianKong"; } from '@/api/shiPinJianKong';
import type { Dayjs } from "dayjs"; import type { Dayjs } from 'dayjs';
import dayjs from "dayjs"; import dayjs from 'dayjs';
import { DateSetting } from "@/utils/enumeration"; import { DateSetting } from '@/utils/enumeration';
import LiveVideoBox from "./components/LiveVideoBox.vue"; import LiveVideoBox from './components/LiveVideoBox.vue';
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
import { useUiStore } from '@/store/modules/ui';
import { useMapDataStore } from '@/modules/map/stores/map-data.store';
import { useMapStore } from '@/store/modules/map';
const uiStore = useUiStore();
const mapDataStore = useMapDataStore();
const mapStore = useMapStore();
// Tab // Tab
const tabs = ref<any[]>([]); const tabs = ref<any[]>([]);
const activeTab = ref<string>(""); const activeTab = ref<string>('');
// 1/4/6/9 // 1/4/6/9
const viewLayout = ref<"1" | "4" | "6" | "9">("4"); const viewLayout = ref<'1' | '4' | '6' | '9'>('4');
// / // /
const monitorType = ref<"live" | "record">("live"); const monitorType = ref<'live' | 'record'>('live');
// //
const searchText = ref(""); const searchText = ref('');
// 线/线 // 线/线
const statusFilter = ref<"online" | "offline">("online"); const statusFilter = ref<'online' | 'offline'>('online');
// //
const videoList = ref<any[]>(Array(9).fill(null)); const videoList = ref<any[]>(Array(9).fill(null));
// //
const pendingVideoQueue = ref<any[]>([]); const pendingVideoQueue = ref<any[]>([]);
//
const isDistribution = ref(false);
//
const VIDEO_POINT_LAYER_KEY = 'stinfo_video_point';
const originalVideoPointData = ref<any[]>([]);
// //
const removeVideo = (index: number, nodeKey?: string) => { const removeVideo = (index: number, nodeKey?: string) => {
const videoData = videoList.value[index]; const videoData = videoList.value[index];
@ -251,7 +296,7 @@ const removeVideo = (index: number, nodeKey?: string) => {
// key // key
if (keyToRemove) { if (keyToRemove) {
// checkedKeys key使 filter // checkedKeys key使 filter
checkedKeys.value = checkedKeys.value.filter((key) => key !== keyToRemove); checkedKeys.value = checkedKeys.value.filter(key => key !== keyToRemove);
// //
removeUnnecessaryParentKeys(keyToRemove); removeUnnecessaryParentKeys(keyToRemove);
@ -286,7 +331,7 @@ const addVideo = (videoData: any) => {
videoList.value.push(videoData); videoList.value.push(videoData);
} else { } else {
// //
if (!pendingVideoQueue.value.find((v) => v.key === videoData.key)) { if (!pendingVideoQueue.value.find(v => v.key === videoData.key)) {
pendingVideoQueue.value.push(videoData); pendingVideoQueue.value.push(videoData);
} }
} }
@ -299,9 +344,13 @@ watch(viewLayout, (newLayout, oldLayout) => {
// //
if (newMaxCount < oldMaxCount) { if (newMaxCount < oldMaxCount) {
for (let i = newMaxCount; i < oldMaxCount && i < videoList.value.length; i++) { for (
let i = newMaxCount;
i < oldMaxCount && i < videoList.value.length;
i++
) {
const video = videoList.value[i]; const video = videoList.value[i];
if (video && !pendingVideoQueue.value.find((v) => v.key === video.key)) { if (video && !pendingVideoQueue.value.find(v => v.key === video.key)) {
pendingVideoQueue.value.push(video); pendingVideoQueue.value.push(video);
} }
videoList.value[i] = null; videoList.value[i] = null;
@ -316,7 +365,11 @@ watch(viewLayout, (newLayout, oldLayout) => {
// //
if (newMaxCount > oldMaxCount) { if (newMaxCount > oldMaxCount) {
const availableSlots = newMaxCount - oldMaxCount; const availableSlots = newMaxCount - oldMaxCount;
for (let i = 0; i < availableSlots && pendingVideoQueue.value.length > 0; i++) { for (
let i = 0;
i < availableSlots && pendingVideoQueue.value.length > 0;
i++
) {
const emptyIndex = videoList.value.findIndex( const emptyIndex = videoList.value.findIndex(
(v, i) => i < newMaxCount && (v === null || v === undefined) (v, i) => i < newMaxCount && (v === null || v === undefined)
); );
@ -339,7 +392,7 @@ const treeLoading = ref(false);
let currentRequestId = 0; // ID let currentRequestId = 0; // ID
// 7 // 7
const dateRange = ref<[Dayjs, Dayjs]>([dayjs().subtract(7, "day"), dayjs()]); const dateRange = ref<[Dayjs, Dayjs]>([dayjs().subtract(7, 'day'), dayjs()]);
// //
const recordLoading = ref(false); const recordLoading = ref(false);
@ -383,44 +436,45 @@ const loadRecordList = async () => {
const params = { const params = {
filter: { filter: {
logic: "and", logic: 'and',
filters: [ filters: [
{ {
field: "stcd", field: 'stcd',
operator: "in", operator: 'in',
value: originalIds, value: originalIds
}, },
{ {
field: "tm", field: 'tm',
operator: "gte", operator: 'gte',
dataType: "date", dataType: 'date',
value: dateRange.value[0].format("YYYY-MM-DD 00:00:00"), value: dateRange.value[0].format('YYYY-MM-DD 00:00:00')
}, },
{ {
field: "tm", field: 'tm',
operator: "lte", operator: 'lte',
dataType: "date", dataType: 'date',
value: dateRange.value[1].format("YYYY-MM-DD 23:59:59"), value: dateRange.value[1].format('YYYY-MM-DD 23:59:59')
}, }
], ]
}, },
sort: [{ field: "tm", dir: "desc" }], sort: [{ field: 'tm', dir: 'desc' }]
}; };
const res = await envVdRunDataGetKendoList(params); const res = await envVdRunDataGetKendoList(params);
if (res?.data?.data) { if (res?.data?.data) {
recordList.value = res.data.data.map((item: any) => ({ recordList.value = res.data.data.map((item: any) => ({
name: item.name || item.stnm || "录像文件", name: item.name || item.stnm || '录像文件',
time: item.tm ? dayjs(item.tm).format("YYYY-MM-DD HH:mm:ss") : "", time: item.tm ? dayjs(item.tm).format('YYYY-MM-DD HH:mm:ss') : '',
...item, ...item
})); }));
// //
if (recordList.value.length > 0) { if (recordList.value.length > 0) {
const firstRecord = recordList.value[0]; const firstRecord = recordList.value[0];
// 使 flpth // 使 flpth
const videoPath = firstRecord.flpth || firstRecord.url || firstRecord.videoUrl; const videoPath =
firstRecord.flpth || firstRecord.url || firstRecord.videoUrl;
if (videoPath) { if (videoPath) {
// //
videoList.value = Array(9).fill(null); videoList.value = Array(9).fill(null);
@ -429,7 +483,7 @@ const loadRecordList = async () => {
flnm: firstRecord.name, flnm: firstRecord.name,
stnm: firstRecord.stnm, stnm: firstRecord.stnm,
url: videoPath, url: videoPath,
...firstRecord, ...firstRecord
}); });
} }
} }
@ -443,9 +497,76 @@ const loadRecordList = async () => {
} }
}; };
//
const cacheOriginalVideoPointData = () => {
if (originalVideoPointData.value.length > 0) return;
const currentData = mapDataStore.getPointLayerData(VIDEO_POINT_LAYER_KEY);
if (currentData.length > 0) {
originalVideoPointData.value = [...currentData];
}
};
// sttpCode sttpCode sttp
const getItemSttp = (item: any): string => {
return String(item?.sttp || item?.sttpCode || '').toUpperCase();
};
// sttpCode stinfo_video_point
const filterVideoPointBySttp = (sttpCode: string | string[]) => {
cacheOriginalVideoPointData();
const original = originalVideoPointData.value;
if (original.length === 0) return;
// tab
if (Array.isArray(sttpCode) && sttpCode[0] === 'all') {
mapStore.replacePointLayerData(VIDEO_POINT_LAYER_KEY, [...original], true);
return;
}
console.log('sttpCode', sttpCode);
console.log('original', original);
// sttpCode
let filtered: any[];
if (Array.isArray(sttpCode)) {
const codeSet = new Set(sttpCode.map((c: string) => c.toUpperCase()));
filtered = original.filter((item: any) => codeSet.has(getItemSttp(item)));
} else {
const code = sttpCode.toUpperCase();
filtered = original.filter((item: any) => getItemSttp(item) === code);
}
console.log('filtered', filtered);
mapStore.replacePointLayerData(VIDEO_POINT_LAYER_KEY, filtered, true);
};
//
const resetVideoPointFilter = () => {
if (originalVideoPointData.value.length > 0) {
mapStore.replacePointLayerData(
VIDEO_POINT_LAYER_KEY,
[...originalVideoPointData.value],
true
);
}
};
// //
const handleAction = () => { const handleAction = () => {
// TODO: isDistribution.value = !isDistribution.value;
uiStore.drawerOpen = false;
// tab
if (isDistribution.value) {
const currentTab = tabs.value.find(tab => tab.key === activeTab.value);
if (currentTab && currentTab.title === '全部') {
resetVideoPointFilter();
} else if (currentTab?.data?.sttpCode) {
filterVideoPointBySttp(currentTab.data.sttpCode);
}
} else {
// 退
resetVideoPointFilter();
}
}; };
// //
@ -456,18 +577,23 @@ const handlePlayRecord = (record: any) => {
const maxCount = parseInt(viewLayout.value); const maxCount = parseInt(viewLayout.value);
// //
const existingIndex = videoList.value.findIndex((v) => v && v.url === videoPath); const existingIndex = videoList.value.findIndex(
v => v && v.url === videoPath
);
if (existingIndex !== -1) { if (existingIndex !== -1) {
return; return;
} }
// //
const currentVideoCount = videoList.value.filter((v, i) => i < maxCount && v !== null) const currentVideoCount = videoList.value.filter(
.length; (v, i) => i < maxCount && v !== null
).length;
if (currentVideoCount >= maxCount) { if (currentVideoCount >= maxCount) {
message.warning(`视频数量已达上限(${maxCount}),请关闭已打开的视频或调整宫格布局`); message.warning(
`视频数量已达上限(${maxCount}),请关闭已打开的视频或调整宫格布局`
);
return; return;
} }
@ -476,7 +602,7 @@ const handlePlayRecord = (record: any) => {
flnm: record.name, flnm: record.name,
stnm: record.stnm, stnm: record.stnm,
url: videoPath, url: videoPath,
...record, ...record
}); });
} }
}; };
@ -484,21 +610,21 @@ const handlePlayRecord = (record: any) => {
const init = async () => { const init = async () => {
const params = { const params = {
filter: { filter: {
logic: "and", logic: 'and',
filters: [ filters: [
{ {
field: "sttpFullPath", field: 'sttpFullPath',
operator: "contains", operator: 'contains',
dataType: "string", dataType: 'string',
value: "VD,VD_", value: 'VD,VD_'
}, }
], ]
}, },
group: [ group: [
{ dir: "asc", field: "sttpCode" }, { dir: 'asc', field: 'sttpCode' },
{ dir: "asc", field: "sttpName" }, { dir: 'asc', field: 'sttpName' }
], ],
groupResultFlat: true, groupResultFlat: true
}; };
let res = await baseMsstbprpt(params); let res = await baseMsstbprpt(params);
@ -508,7 +634,7 @@ const init = async () => {
// //
res.data.data.forEach((el: any) => { res.data.data.forEach((el: any) => {
if (el?.sttpCode == "VD_EQ" || el?.sttpCode == "VD_EQS") { if (el?.sttpCode == 'VD_EQ' || el?.sttpCode == 'VD_EQS') {
const found = _list.find((item: any) => Array.isArray(item.sttpCode)); const found = _list.find((item: any) => Array.isArray(item.sttpCode));
if (found) { if (found) {
@ -521,26 +647,27 @@ const init = async () => {
...el, ...el,
sttpCode: [el?.sttpCode], sttpCode: [el?.sttpCode],
sttpCode_value: [el?.sttpCode], sttpCode_value: [el?.sttpCode],
sttpName: "生态流量", sttpName: '生态流量',
sttpName_value: "生态流量", sttpName_value: '生态流量'
}); });
} }
} else if (el?.sttpCode != "VD_FPRD") { } else if (el?.sttpCode != 'VD_FPRD') {
_list.push(el); _list.push(el);
} }
}); });
const list = const list =
_list.sort((a: any, b: any) => b?.count_sttpCode - a?.count_sttpCode) ?? []; _list.sort((a: any, b: any) => b?.count_sttpCode - a?.count_sttpCode) ??
[];
const totalCount = list.reduce((sum, item) => sum + item.count_sttpCode, 0); const totalCount = list.reduce((sum, item) => sum + item.count_sttpCode, 0);
const allObject = { const allObject = {
sttpCode: ["all"], sttpCode: ['all'],
sttpCode_value: ["all"], sttpCode_value: ['all'],
count_sttpCode: totalCount, count_sttpCode: totalCount,
count_sttpName: "全部", count_sttpName: '全部',
sttpName: "全部", sttpName: '全部',
sttpName_value: "全部", sttpName_value: '全部'
}; };
list.unshift(allObject); list.unshift(allObject);
@ -549,7 +676,7 @@ const init = async () => {
tabs.value = list.map((item: any, index: number) => ({ tabs.value = list.map((item: any, index: number) => ({
key: String(index), key: String(index),
title: item.sttpName || item.sttpName_value, title: item.sttpName || item.sttpName_value,
data: item, data: item
})); }));
// tab // tab
@ -570,7 +697,7 @@ const initTree = async () => {
const requestId = ++currentRequestId; const requestId = ++currentRequestId;
// tab // tab
const currentTab = tabs.value.find((tab) => tab.key === activeTab.value); const currentTab = tabs.value.find(tab => tab.key === activeTab.value);
if (!currentTab) return; if (!currentTab) return;
const sttpCodeValue = currentTab.data?.sttpCode_value || []; const sttpCodeValue = currentTab.data?.sttpCode_value || [];
@ -579,32 +706,32 @@ const initTree = async () => {
const filters: any[] = []; const filters: any[] = [];
// statussttpCode // statussttpCode
if (monitorType.value === "live") { if (monitorType.value === 'live') {
// status // status
const statusValue = statusFilter.value === "online" ? 1 : 0; const statusValue = statusFilter.value === 'online' ? 1 : 0;
filters.push({ filters.push({
field: "status", field: 'status',
operator: "eq", operator: 'eq',
dataType: "string", dataType: 'string',
value: statusValue, value: statusValue
}); });
} }
// ""tabsttpCode // ""tabsttpCode
if (sttpCodeValue[0] !== "all") { if (sttpCodeValue[0] !== 'all') {
filters.push({ filters.push({
field: "sttpCode", field: 'sttpCode',
operator: "in", operator: 'in',
dataType: "string", dataType: 'string',
value: [sttpCodeValue], value: [sttpCodeValue]
}); });
} }
const params = { const params = {
filter: { filter: {
logic: "and", logic: 'and',
filters, filters
}, }
}; };
// //
@ -626,7 +753,7 @@ const initTree = async () => {
// key // key
let keyCounter = 0; let keyCounter = 0;
const generateKey = (nodes: any[]) => { const generateKey = (nodes: any[]) => {
nodes.forEach((node) => { nodes.forEach(node => {
node.key = `key_${keyCounter++}`; node.key = `key_${keyCounter++}`;
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {
generateKey(node.children); generateKey(node.children);
@ -672,7 +799,7 @@ const initTree = async () => {
addParentKeys(firstLeafKey); // addParentKeys(firstLeafKey); //
// //
if (monitorType.value === "live") { if (monitorType.value === 'live') {
// //
const findNodeByKey = (nodes: any[], key: string): any => { const findNodeByKey = (nodes: any[], key: string): any => {
for (const node of nodes) { for (const node of nodes) {
@ -688,13 +815,15 @@ const initTree = async () => {
const firstLeafNode = findNodeByKey(treeData.value, firstLeafKey); const firstLeafNode = findNodeByKey(treeData.value, firstLeafKey);
if (firstLeafNode) { if (firstLeafNode) {
const videoUrl = const videoUrl =
firstLeafNode.url || firstLeafNode.videoUrl || firstLeafNode.playUrl; firstLeafNode.url ||
firstLeafNode.videoUrl ||
firstLeafNode.playUrl;
if (videoUrl) { if (videoUrl) {
addVideo({ addVideo({
flnm: firstLeafNode.name, flnm: firstLeafNode.name,
stnm: firstLeafNode.stnm, stnm: firstLeafNode.stnm,
url: videoUrl, url: videoUrl,
...firstLeafNode, ...firstLeafNode
}); });
} }
} }
@ -711,7 +840,24 @@ const initTree = async () => {
// Tab // Tab
const handleTabChange = (key: string) => { const handleTabChange = (key: string) => {
activeTab.value = key; activeTab.value = key;
const currentTab = tabs.value.find(tab => tab.key === activeTab.value);
if (currentTab) {
// tab
if (currentTab.title === '全部') {
resetVideoPointFilter();
} else {
// tab sttpCode
const sttpCode = currentTab.data?.sttpCode;
if (sttpCode) {
filterVideoPointBySttp(sttpCode);
}
}
}
initTree(); initTree();
if (isDistribution.value == true) {
}
}; };
// //
@ -722,8 +868,8 @@ watch(statusFilter, () => {
// //
const handleMonitorTypeChange = () => { const handleMonitorTypeChange = () => {
// viewLayout41 // viewLayout41
if (monitorType.value === "record") { if (monitorType.value === 'record') {
viewLayout.value = "4"; viewLayout.value = '4';
// //
videoList.value = Array(9).fill(null); videoList.value = Array(9).fill(null);
checkedKeys.value = []; checkedKeys.value = [];
@ -731,16 +877,16 @@ const handleMonitorTypeChange = () => {
} }
// 线 // 线
if (monitorType.value === "live") { if (monitorType.value === 'live') {
statusFilter.value = "online"; statusFilter.value = 'online';
// 14 // 14
if (!["4", "6", "9"].includes(viewLayout.value)) { if (!['4', '6', '9'].includes(viewLayout.value)) {
viewLayout.value = "4"; viewLayout.value = '4';
} }
} }
// //
searchText.value = ""; searchText.value = '';
// //
initTree(); initTree();
}; };
@ -748,7 +894,7 @@ const handleMonitorTypeChange = () => {
// //
const handleTreeSelect = (checkedKeysValue: any[], info: any) => { const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
// //
if (monitorType.value !== "live") return; if (monitorType.value !== 'live') return;
const nodeData = info.node; const nodeData = info.node;
@ -772,19 +918,19 @@ const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
flnm: nodeData.name, flnm: nodeData.name,
stnm: nodeData.stnm, stnm: nodeData.stnm,
url: videoUrl, url: videoUrl,
...nodeData, ...nodeData
}); });
// checkedKeys // checkedKeys
addParentKeys(nodeData.key); addParentKeys(nodeData.key);
} else { } else {
// //
if (!pendingVideoQueue.value.find((v) => v.key === nodeData.key)) { if (!pendingVideoQueue.value.find(v => v.key === nodeData.key)) {
pendingVideoQueue.value.push({ pendingVideoQueue.value.push({
flnm: nodeData.name, flnm: nodeData.name,
stnm: nodeData.stnm, stnm: nodeData.stnm,
url: videoUrl, url: videoUrl,
...nodeData, ...nodeData
}); });
} }
} }
@ -799,7 +945,7 @@ const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
if (!nodeData.children || nodeData.children.length === 0) { if (!nodeData.children || nodeData.children.length === 0) {
// //
const queueIndex = pendingVideoQueue.value.findIndex( const queueIndex = pendingVideoQueue.value.findIndex(
(v) => v.key === nodeData.key v => v.key === nodeData.key
); );
if (queueIndex !== -1) { if (queueIndex !== -1) {
// //
@ -824,7 +970,7 @@ const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
const addParentKeys = (childKey: string) => { const addParentKeys = (childKey: string) => {
const parentKeys = getParentKeys(childKey); const parentKeys = getParentKeys(childKey);
parentKeys.forEach((parentKey) => { parentKeys.forEach(parentKey => {
// //
const findNode = (nodes: any[], key: string): any => { const findNode = (nodes: any[], key: string): any => {
for (const node of nodes) { for (const node of nodes) {
@ -880,7 +1026,7 @@ const getParentKeys = (childKey: string): string[] => {
const removeUnnecessaryParentKeys = (childKey: string) => { const removeUnnecessaryParentKeys = (childKey: string) => {
const parentKeys = getParentKeys(childKey); const parentKeys = getParentKeys(childKey);
parentKeys.forEach((parentKey) => { parentKeys.forEach(parentKey => {
// //
const findNode = (nodes: any[], key: string): any => { const findNode = (nodes: any[], key: string): any => {
for (const node of nodes) { for (const node of nodes) {
@ -900,7 +1046,7 @@ const removeUnnecessaryParentKeys = (childKey: string) => {
if (!allDirectChildrenChecked) { if (!allDirectChildrenChecked) {
// //
checkedKeys.value = checkedKeys.value.filter((key) => key !== parentKey); checkedKeys.value = checkedKeys.value.filter(key => key !== parentKey);
// //
removeUnnecessaryParentKeys(parentKey); removeUnnecessaryParentKeys(parentKey);
@ -916,7 +1062,9 @@ const areAllDirectChildrenChecked = (parentNode: any): boolean => {
} }
// checkedKeys // checkedKeys
return parentNode.children.every((child: any) => checkedKeys.value.includes(child.key)); return parentNode.children.every((child: any) =>
checkedKeys.value.includes(child.key)
);
}; };
// //
@ -948,7 +1096,7 @@ const addVideosFromNodeWithLimit = (node: any) => {
const maxCount = parseInt(viewLayout.value); const maxCount = parseInt(viewLayout.value);
// key // key
checkedKeys.value = checkedKeys.value.filter((key) => key !== node.key); checkedKeys.value = checkedKeys.value.filter(key => key !== node.key);
// //
const getCurrentVideoCount = () => { const getCurrentVideoCount = () => {
@ -978,12 +1126,12 @@ const addVideosFromNodeWithLimit = (node: any) => {
if (remainingSlots <= 0) { if (remainingSlots <= 0) {
// //
allLeafNodes.forEach((leafNode: any) => { allLeafNodes.forEach((leafNode: any) => {
if (!pendingVideoQueue.value.find((v) => v.key === leafNode.key)) { if (!pendingVideoQueue.value.find(v => v.key === leafNode.key)) {
pendingVideoQueue.value.push({ pendingVideoQueue.value.push({
flnm: leafNode.name, flnm: leafNode.name,
stnm: leafNode.stnm, stnm: leafNode.stnm,
url: leafNode.url || leafNode.videoUrl || leafNode.playUrl, url: leafNode.url || leafNode.videoUrl || leafNode.playUrl,
...leafNode, ...leafNode
}); });
} }
}); });
@ -1000,7 +1148,7 @@ const addVideosFromNodeWithLimit = (node: any) => {
flnm: leafNode.name, flnm: leafNode.name,
stnm: leafNode.stnm, stnm: leafNode.stnm,
url: leafNode.url || leafNode.videoUrl || leafNode.playUrl, url: leafNode.url || leafNode.videoUrl || leafNode.playUrl,
...leafNode, ...leafNode
}); });
// key checkedKeys // key checkedKeys
@ -1012,12 +1160,12 @@ const addVideosFromNodeWithLimit = (node: any) => {
// //
if (nodesToQueue.length > 0) { if (nodesToQueue.length > 0) {
nodesToQueue.forEach((leafNode: any) => { nodesToQueue.forEach((leafNode: any) => {
if (!pendingVideoQueue.value.find((v) => v.key === leafNode.key)) { if (!pendingVideoQueue.value.find(v => v.key === leafNode.key)) {
pendingVideoQueue.value.push({ pendingVideoQueue.value.push({
flnm: leafNode.name, flnm: leafNode.name,
stnm: leafNode.stnm, stnm: leafNode.stnm,
url: leafNode.url || leafNode.videoUrl || leafNode.playUrl, url: leafNode.url || leafNode.videoUrl || leafNode.playUrl,
...leafNode, ...leafNode
}); });
} }
}); });
@ -1047,15 +1195,15 @@ const removeVideosFromNode = (node: any) => {
// key // key
const removeVideoByNodeKey = (nodeKey: string) => { const removeVideoByNodeKey = (nodeKey: string) => {
// //
const queueIndex = pendingVideoQueue.value.findIndex( const queueIndex = pendingVideoQueue.value.findIndex(v => v.key === nodeKey);
(v) => v.key === nodeKey
);
if (queueIndex !== -1) { if (queueIndex !== -1) {
pendingVideoQueue.value.splice(queueIndex, 1); pendingVideoQueue.value.splice(queueIndex, 1);
return; return;
} }
const index = videoList.value.findIndex((video) => video && video.key === nodeKey); const index = videoList.value.findIndex(
video => video && video.key === nodeKey
);
if (index !== -1) { if (index !== -1) {
videoList.value[index] = null; videoList.value[index] = null;
// //
@ -1067,7 +1215,7 @@ const removeVideoByNodeKey = (nodeKey: string) => {
watch( watch(
[checkedKeys, dateRange, monitorType], [checkedKeys, dateRange, monitorType],
([newCheckedKeys, newDateRange, newMonitorType]) => { ([newCheckedKeys, newDateRange, newMonitorType]) => {
if (newMonitorType === "record") { if (newMonitorType === 'record') {
loadRecordList(); loadRecordList();
} else { } else {
recordList.value = []; recordList.value = [];
@ -1076,13 +1224,13 @@ watch(
); );
// //
watch(searchText, (newValue) => { watch(searchText, newValue => {
filterTree(newValue); filterTree(newValue);
}); });
// //
const filterTree = (keyword: string) => { const filterTree = (keyword: string) => {
if (!keyword || keyword.trim() === "") { if (!keyword || keyword.trim() === '') {
// //
treeData.value = JSON.parse(JSON.stringify(originalTreeData.value)); treeData.value = JSON.parse(JSON.stringify(originalTreeData.value));
@ -1108,8 +1256,8 @@ const filterTree = (keyword: string) => {
const filterNodes = (nodes: any[]): any[] => { const filterNodes = (nodes: any[]): any[] => {
const filtered: any[] = []; const filtered: any[] = [];
nodes.forEach((node) => { nodes.forEach(node => {
const nodeName = (node.name || "").toLowerCase(); const nodeName = (node.name || '').toLowerCase();
const hasChildren = node.children && node.children.length > 0; const hasChildren = node.children && node.children.length > 0;
if (hasChildren) { if (hasChildren) {
@ -1120,7 +1268,8 @@ const filterTree = (keyword: string) => {
if (nodeName.includes(lowerKeyword) || filteredChildren.length > 0) { if (nodeName.includes(lowerKeyword) || filteredChildren.length > 0) {
filtered.push({ filtered.push({
...node, ...node,
children: filteredChildren.length > 0 ? filteredChildren : node.children, children:
filteredChildren.length > 0 ? filteredChildren : node.children
}); });
} }
} else { } else {
@ -1139,7 +1288,7 @@ const filterTree = (keyword: string) => {
// //
const getAllKeys = (nodes: any[]): string[] => { const getAllKeys = (nodes: any[]): string[] => {
let keys: string[] = []; let keys: string[] = [];
nodes.forEach((node) => { nodes.forEach(node => {
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {
keys.push(node.key); keys.push(node.key);
keys = keys.concat(getAllKeys(node.children)); keys = keys.concat(getAllKeys(node.children));
@ -1154,6 +1303,10 @@ const filterTree = (keyword: string) => {
onMounted(() => { onMounted(() => {
init(); init();
}); });
onUnmounted(() => {
uiStore.drawerOpen = true;
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -1173,6 +1326,17 @@ onMounted(() => {
flex-direction: column; flex-direction: column;
} }
.shiPinJianKongZhuanTi-page-distribution {
height: 50px;
}
.shiPinJianKongZhuanTi-JidiSelectorMod {
position: fixed;
left: 0;
top: 110px;
z-index: 3000;
}
.custom-tabs { .custom-tabs {
width: 100%; width: 100%;
height: 48px; height: 48px;
@ -1189,7 +1353,7 @@ onMounted(() => {
} }
.ant-tabs-ink-bar { .ant-tabs-ink-bar {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMS8wMy8yMrqNQAoAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOklEQVQImWNgQAchkx3QhZhQeEFTExj+MexnCJoyH1mYEUUBwz8kScYFDOtyEhGKMBSgKmTErQChEAA6FRM7O0rIOgAAAABJRU5ErkJggg==") background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMS8wMy8yMrqNQAoAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOklEQVQImWNgQAchkx3QhZhQeEFTExj+MexnCJoyH1mYEUUBwz8kScYFDOtyEhGKMBSgKmTErQChEAA6FRM7O0rIOgAAAABJRU5ErkJggg==')
no-repeat center bottom; no-repeat center bottom;
border-bottom: 2px solid #005293; border-bottom: 2px solid #005293;
height: 7px; height: 7px;
@ -1360,7 +1524,7 @@ onMounted(() => {
} }
&::after { &::after {
content: ""; content: '';
position: absolute; position: absolute;
bottom: -3px; bottom: -3px;
right: 0px; right: 0px;
@ -1395,7 +1559,6 @@ onMounted(() => {
justify-content: center; justify-content: center;
height: 100%; height: 100%;
min-height: 100%; min-height: 100%;
color: red;
} }
:deep(.ant-tree) { :deep(.ant-tree) {