feat(screen): 在地图工具提示中添加视频监控功能
为支持视频的实体(如应急中心、储备中心和预设点)在MapTooltip组件中添加视频图标按钮。包含VideoModal集成,用于显示带控制功能的视频流。
This commit is contained in:
parent
8fdc23d76d
commit
58fe72f717
Binary file not shown.
|
After Width: | Height: | Size: 863 B |
@ -65,6 +65,20 @@
|
|||||||
>
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
|
<!-- 视频图标按钮 -->
|
||||||
|
<button
|
||||||
|
v-if="showVideoIcon && videoIconSrc"
|
||||||
|
type="button"
|
||||||
|
class="map-tooltip__video-btn"
|
||||||
|
:aria-label="videoIconAriaLabel"
|
||||||
|
@click.stop="emit('video-icon-click')"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="videoIconSrc"
|
||||||
|
alt=""
|
||||||
|
class="map-tooltip__video-icon"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
@ -197,6 +211,30 @@ const props = defineProps({
|
|||||||
closable: {
|
closable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在标题右侧显示视频图标
|
||||||
|
*/
|
||||||
|
showVideoIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频图标的图片路径
|
||||||
|
*/
|
||||||
|
videoIconSrc: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频图标的无障碍标签
|
||||||
|
*/
|
||||||
|
videoIconAriaLabel: {
|
||||||
|
type: String,
|
||||||
|
default: '打开视频监控'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -211,7 +249,11 @@ const emit = defineEmits([
|
|||||||
/**
|
/**
|
||||||
* 支持 v-model:visible 双向绑定
|
* 支持 v-model:visible 双向绑定
|
||||||
*/
|
*/
|
||||||
'update:visible'
|
'update:visible',
|
||||||
|
/**
|
||||||
|
* 用户点击视频图标时触发
|
||||||
|
*/
|
||||||
|
'video-icon-click'
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -354,6 +396,47 @@ const handleClose = () => {
|
|||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频图标按钮
|
||||||
|
* 显示在标题右侧,用于打开视频监控
|
||||||
|
*/
|
||||||
|
.map-tooltip__video-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: vw(24);
|
||||||
|
height: vw(24);
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.15);
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--primary-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-tooltip__video-icon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
display: block;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭按钮
|
* 关闭按钮
|
||||||
* 使用纯 CSS 实现 X 图标,避免额外的图片资源
|
* 使用纯 CSS 实现 X 图标,避免额外的图片资源
|
||||||
|
|||||||
@ -116,6 +116,9 @@
|
|||||||
:title="mapTooltip.title"
|
:title="mapTooltip.title"
|
||||||
:icon="mapTooltip.icon"
|
:icon="mapTooltip.icon"
|
||||||
:z-index="mapTooltip.zIndex"
|
:z-index="mapTooltip.zIndex"
|
||||||
|
:show-video-icon="mapTooltip.data && mapTooltip.data.supportVideo"
|
||||||
|
:video-icon-src="mediaIcon"
|
||||||
|
@video-icon-click="handleVideoIconClick"
|
||||||
@close="handleMapTooltipClose"
|
@close="handleMapTooltipClose"
|
||||||
>
|
>
|
||||||
<!-- Tooltip 内容插槽 - 根据实际业务数据渲染 -->
|
<!-- Tooltip 内容插槽 - 根据实际业务数据渲染 -->
|
||||||
@ -168,6 +171,14 @@
|
|||||||
@close="showCenterDetail = false"
|
@close="showCenterDetail = false"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 视频监控弹窗 -->
|
||||||
|
<VideoModal
|
||||||
|
v-if="showVideoModal"
|
||||||
|
:visible="showVideoModal"
|
||||||
|
:monitor="selectedVideoMonitor"
|
||||||
|
@close="handleVideoModalClose"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 智能应急方案弹窗 -->
|
<!-- 智能应急方案弹窗 -->
|
||||||
<StretchableModal
|
<StretchableModal
|
||||||
v-model:visible="showStretchableModal"
|
v-model:visible="showStretchableModal"
|
||||||
@ -203,6 +214,7 @@ import MapViewer from "./components/MapViewer/index.vue";
|
|||||||
import RightPanel from "./components/RightPanel/index.vue";
|
import RightPanel from "./components/RightPanel/index.vue";
|
||||||
import PersonnelDetail from "./components/Popups/PersonnelDetail.vue";
|
import PersonnelDetail from "./components/Popups/PersonnelDetail.vue";
|
||||||
import EmergencyCenterDetail from "./components/Popups/EmergencyCenterDetail.vue";
|
import EmergencyCenterDetail from "./components/Popups/EmergencyCenterDetail.vue";
|
||||||
|
import VideoModal from "./components/RightPanel/VideoModal.vue";
|
||||||
import MapTooltip from "./components/shared/MapTooltip.vue";
|
import MapTooltip from "./components/shared/MapTooltip.vue";
|
||||||
import SceneLabel from "./components/SceneLabel.vue";
|
import SceneLabel from "./components/SceneLabel.vue";
|
||||||
import StretchableModal from "./components/shared/StretchableModal.vue";
|
import StretchableModal from "./components/shared/StretchableModal.vue";
|
||||||
@ -224,6 +236,7 @@ import soldierIcon from "./assets/images/SketchPngfbec927027ff9e49207749ebaafd22
|
|||||||
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
|
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
|
||||||
import emergencyBaseIcon from "./assets/images/应急基地.png";
|
import emergencyBaseIcon from "./assets/images/应急基地.png";
|
||||||
import reserveCenterIcon from "./assets/images/储备中心.png";
|
import reserveCenterIcon from "./assets/images/储备中心.png";
|
||||||
|
import mediaIcon from "./assets/images/media.png";
|
||||||
|
|
||||||
// 折叠按钮图标
|
// 折叠按钮图标
|
||||||
import collapseLeftArrow from "./assets/images/折叠面板左箭头.png";
|
import collapseLeftArrow from "./assets/images/折叠面板左箭头.png";
|
||||||
@ -459,6 +472,9 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
let title = '';
|
let title = '';
|
||||||
const fields = [];
|
const fields = [];
|
||||||
const actions = [];
|
const actions = [];
|
||||||
|
let supportVideo = false;
|
||||||
|
let videoTitle = '';
|
||||||
|
const videoSrc = 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4';
|
||||||
|
|
||||||
if (type === 'soldier') {
|
if (type === 'soldier') {
|
||||||
// 应急人员
|
// 应急人员
|
||||||
@ -510,6 +526,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
{ label: '隶属单位', value: '交通公路部门' },
|
{ label: '隶属单位', value: '交通公路部门' },
|
||||||
{ label: '位置信息', value: `目前为止距离现场${distance}公里` }
|
{ label: '位置信息', value: `目前为止距离现场${distance}公里` }
|
||||||
);
|
);
|
||||||
|
supportVideo = true;
|
||||||
|
videoTitle = '应急中心';
|
||||||
} else {
|
} else {
|
||||||
// 其他养护站显示 tooltip
|
// 其他养护站显示 tooltip
|
||||||
title = '养护站';
|
title = '养护站';
|
||||||
@ -525,6 +543,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
{ label: '名称', value: properties.name?.getValue() || '-' },
|
{ label: '名称', value: properties.name?.getValue() || '-' },
|
||||||
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
||||||
);
|
);
|
||||||
|
supportVideo = true;
|
||||||
|
videoTitle = '储备中心';
|
||||||
} else if (type === 'presetPoint') {
|
} else if (type === 'presetPoint') {
|
||||||
// 预置点
|
// 预置点
|
||||||
title = '预置点';
|
title = '预置点';
|
||||||
@ -532,6 +552,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
{ label: '名称', value: properties.name?.getValue() || '-' },
|
{ label: '名称', value: properties.name?.getValue() || '-' },
|
||||||
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
||||||
);
|
);
|
||||||
|
supportVideo = true;
|
||||||
|
videoTitle = '预置点';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示 Tooltip,使用实体的屏幕坐标
|
// 显示 Tooltip,使用实体的屏幕坐标
|
||||||
@ -540,7 +562,13 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
y: canvasPosition.y,
|
y: canvasPosition.y,
|
||||||
title,
|
title,
|
||||||
icon,
|
icon,
|
||||||
data: { fields, actions: actions.length > 0 ? actions : undefined }
|
data: {
|
||||||
|
fields,
|
||||||
|
actions: actions.length > 0 ? actions : undefined,
|
||||||
|
supportVideo,
|
||||||
|
videoTitle,
|
||||||
|
videoSrc
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 保存当前实体,用于相机移动时更新位置
|
// 保存当前实体,用于相机移动时更新位置
|
||||||
@ -989,6 +1017,7 @@ const handleMapToolChange = async ({ tool, active }) => {
|
|||||||
const showPersonnelDetail = ref(false);
|
const showPersonnelDetail = ref(false);
|
||||||
const showCenterDetail = ref(false);
|
const showCenterDetail = ref(false);
|
||||||
const showStretchableModal = ref(false);
|
const showStretchableModal = ref(false);
|
||||||
|
const showVideoModal = ref(false);
|
||||||
|
|
||||||
// 选中的数据
|
// 选中的数据
|
||||||
const selectedPersonnel = ref({
|
const selectedPersonnel = ref({
|
||||||
@ -1007,6 +1036,16 @@ const selectedCenter = ref({
|
|||||||
image: null,
|
image: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const selectedVideoMonitor = ref({
|
||||||
|
id: '',
|
||||||
|
title: '',
|
||||||
|
videoSrc: '',
|
||||||
|
dateRange: '',
|
||||||
|
hasMegaphone: false,
|
||||||
|
hasAudio: true,
|
||||||
|
hasDirectionControl: false
|
||||||
|
});
|
||||||
|
|
||||||
// 返回驾驶舱
|
// 返回驾驶舱
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
console.log("返回驾驶舱");
|
console.log("返回驾驶舱");
|
||||||
@ -1080,6 +1119,33 @@ const handleMapTooltipClose = () => {
|
|||||||
mapTooltip.value.visible = false;
|
mapTooltip.value.visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频图标点击事件
|
||||||
|
* 打开视频弹窗并设置视频源
|
||||||
|
*/
|
||||||
|
const handleVideoIconClick = () => {
|
||||||
|
const { data } = mapTooltip.value;
|
||||||
|
if (data && data.supportVideo) {
|
||||||
|
selectedVideoMonitor.value = {
|
||||||
|
id: Date.now().toString(),
|
||||||
|
title: data.videoTitle || '视频监控',
|
||||||
|
videoSrc: data.videoSrc || '',
|
||||||
|
dateRange: new Date().toLocaleDateString(),
|
||||||
|
hasMegaphone: false,
|
||||||
|
hasAudio: true,
|
||||||
|
hasDirectionControl: false
|
||||||
|
};
|
||||||
|
showVideoModal.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频弹窗关闭事件
|
||||||
|
*/
|
||||||
|
const handleVideoModalClose = () => {
|
||||||
|
showVideoModal.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
// 路径线实体引用
|
// 路径线实体引用
|
||||||
const pathLineEntities = ref([]);
|
const pathLineEntities = ref([]);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user