监控比例
This commit is contained in:
1 parent
4c8dc3c2a4
commit
6a25d99a3d
4 files changed
+69
-36
No files matched your search
@@ -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>
|
||||
Reference in new issue
Block a user