监控比例

This commit is contained in:
dzc committed 2026-08-21 16:54:34 +08:00
1 parent 4c8dc3c2a4
commit 6a25d99a3d
4 files changed
+69 -36

No files matched your search

+13 -19
View File
@@ -1,12 +1,11 @@
<template>
<el-tree-select class="stafftree" :class="{ 'stafftree--allow-device': props.allowDevice }" :props="{
<el-tree-select class="channel-tree-select" :class="{ 'channel-tree-select--allow-device': props.allowDevice }" :props="{
label: 'treeLabel',
children: 'deviceChannelList',
}" node-key="treeValue" v-model="state.selectId" :placeholder="props.placeholder" :clearable="props.clearable"
}" node-key="treeValue" v-model="selectId" :placeholder="props.placeholder" :clearable="props.clearable"
:disabled="props.disabled" :loading="state.loading" :data="state.options" :render-after-expand="true"
:check-strictly="props.allowDevice" show-checkbox multiple
show-checkbox multiple
style="width: 100%" filterable :filter-node-method="filterNode"
@change="handleChange"
@visible-change="(e: boolean) => e && getOptions(true)">
<template #default="{ data, node }">
<div v-if="node.level == 1" class="flex items-center gap-2">
@@ -36,7 +35,7 @@ type Props = {
clearable?: boolean
autoFirst?: boolean
apiParams?: any
/** 是否允许选择设备节点,默认仅选择设备下的通道 */
/** 是否显示录像机复选框;勾选录像机时联动选择其全部通道 */
allowDevice?: boolean
}
@@ -58,7 +57,6 @@ const queryForm = reactive<any>({
const state = reactive<any>({
loading: false,
selectId: selectId,
options: [],
type: [],
loaded: false,
@@ -101,19 +99,15 @@ const getSelectedNodes = (values: unknown) => {
return flattenOptions(state.options).filter((item) => selectedSet.has(String(item.treeValue)))
}
/** 同时返回选中值和节点详情,兼容原有只接收第一个参数的使用方式。 */
const handleChange = (values: unknown) => {
emit("change", values, getSelectedNodes(values))
}
watch(
selectId,
(newVal, oldValue) => {
async (newVal, oldValue) => {
if (newVal == oldValue) return
state.selectId = newVal
if (shouldLoadOptionsOnInit(newVal)) {
void ensureOptionsLoaded()
await ensureOptionsLoaded()
}
if (oldValue === undefined && !hasSelectedValue(newVal)) return
emit("change", newVal, getSelectedNodes(newVal))
},
{ immediate: true, deep: true },
)
@@ -160,8 +154,8 @@ async function ensureOptionsLoaded(force = false) {
state.options = JSON.parse(cached)
state.loaded = true
if (props.autoFirst && state.options.length != 0) {
state.selectId = state.options[0].id
emit("change", state.selectId)
selectId.value = state.options[0].id
emit("change", selectId.value)
}
return
}
@@ -197,8 +191,8 @@ async function getOptions(force = false) {
}
if (props.autoFirst && state.options.length != 0) {
state.selectId = state.options[0].id
emit("change", state.selectId)
selectId.value = state.options[0].id
emit("change", selectId.value)
}
} finally {
state.loading = false
@@ -207,7 +201,7 @@ async function getOptions(force = false) {
</script>
<style lang="scss">
.stafftree:not(.stafftree--allow-device)>.el-tree-node>.el-tree-node__content .el-checkbox {
.channel-tree-select:not(.channel-tree-select--allow-device)>.el-tree-node>.el-tree-node__content .el-checkbox {
display: none;
}
@@ -821,15 +821,16 @@ defineExpose({
</script>
<style scoped>
.video-container {
/* 底层播放器统一保持监控画面常用的 16:9,避免被外层不规则高度拉伸。 */
flex: 0 0 auto;
.video-container {
/* 原生插件按此节点的实际矩形创建窗口,宽度变化时由比例计算高度。 */
flex: 0 1 auto;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
min-width: 0;
height: auto;
aspect-ratio: 16 / 9;
position: relative;
@@ -1,7 +1,7 @@
<template>
<el-dialog destroy-on-close v-model="state.dialogVisible" title="预览" width="80%" append-to-body
:before-close="handleClose">
<div class="flex justify-center items-start">
<div class="dialog-video-layout">
<div class="min-w-[25%]">
<el-tree :data="channel.treeList" :props="{
label: 'name',
@@ -14,8 +14,8 @@
</template>
</el-tree>
</div>
<div class="flex-1 overflow-hidden video-container">
<RtspPluginVideo ref="previewVideoRef" style="height: 500px;" @changePage="videoChangePage" />
<div class="dialog-video-player">
<RtspPluginVideo ref="previewVideoRef" @changePage="videoChangePage" />
</div>
</div>
<template #footer>
@@ -202,16 +202,24 @@ defineExpose({
</script>
<style lang="scss" scoped>
.video-container {
.dialog-video-layout {
display: flex;
justify-content: center;
align-items: center;
min-height: 60vh;
align-items: flex-start;
min-width: 0;
}
#ws-real-player {
width: 100%;
height: 100%;
.dialog-video-player {
flex: 1 1 auto;
min-width: 0;
min-height: 0;
display: flex;
justify-content: center;
overflow: hidden;
}
.dialog-video-player :deep(.video-container) {
flex: 0 1 auto;
max-width: min(100%, calc((100vh - 180px) * 16 / 9));
}
.dialog-footer {
@@ -1,6 +1,6 @@
<template>
<el-dialog destroy-on-close v-model="state.dialogVisible" title="回放" width="80%" :before-close="handleClose">
<div class="flex justify-center items-start">
<div class="dialog-video-layout">
<div v-if="state.type == 'device'" class="min-w-[25%]">
<el-tree :data="channel.treeList" :props="{
label: 'name',
@@ -13,7 +13,7 @@
</template>
</el-tree>
</div>
<div class="flex-1 flex flex-col overflow-hidden video-container">
<div class="dialog-video-content">
<el-form :model="queryForm" ref="queryRef" :inline="true" @keyup.enter="doSearch">
<el-form-item style="width: 450px;" label="录像时间" prop="videoDateList">
<el-date-picker v-model="queryForm.videoDateList" date-format="YYYY-MM-DD HH:mm:ss"
@@ -35,8 +35,8 @@
</el-button>
</el-form-item>
</el-form>
<div class="flex-1 overflow-hidden video-container" style="height: 500px;">
<RtspPluginVideo ref="replayVideoRef" style="height: 500px;" @changePage="videoChangePage" />
<div class="dialog-video-player">
<RtspPluginVideo ref="replayVideoRef" @changePage="videoChangePage" />
</div>
</div>
</div>
@@ -367,3 +367,33 @@ defineExpose({
openDialog
});
</script>
<style lang="scss" scoped>
.dialog-video-layout {
display: flex;
align-items: flex-start;
min-width: 0;
}
.dialog-video-content {
flex: 1 1 auto;
min-width: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
.dialog-video-player {
flex: 1 1 auto;
min-width: 0;
min-height: 0;
display: flex;
justify-content: center;
overflow: hidden;
}
.dialog-video-player :deep(.video-container) {
flex: 0 1 auto;
max-width: min(100%, calc((100vh - 250px) * 16 / 9));
}
</style>