视频监控视频分布按钮添加
This commit is contained in:
parent
6e5dc9188d
commit
d972a42f96
@ -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
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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 : ''
|
||||||
|
|||||||
@ -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[] = [];
|
||||||
|
|
||||||
// 录像模式不传status,只传sttpCode
|
// 录像模式不传status,只传sttpCode
|
||||||
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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不是"全部"tab,才添加sttpCode筛选
|
// 如果不是"全部"tab,才添加sttpCode筛选
|
||||||
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 = () => {
|
||||||
// 切换到录像模式时,设置viewLayout为4,隐藏1宫格
|
// 切换到录像模式时,设置viewLayout为4,隐藏1宫格
|
||||||
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';
|
||||||
// 如果当前是1宫格,保持不变;否则设置为4
|
// 如果当前是1宫格,保持不变;否则设置为4
|
||||||
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) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user