feat: 实时视频播放实现

main
donghao 2 months ago
parent a58eba6644
commit 8018774a29

@ -49,7 +49,11 @@
}
&:hover {
color: #37DBFF;
background: linear-gradient( 90deg, rgba(30,54,88,0) 0%, #0C4FAD 53%, rgba(65,117,190,0) 100%);;
background: linear-gradient( 90deg, rgba(30,54,88,0) 0%, #0C4FAD 53%, rgba(65,117,190,0) 100%);
}
&.selected-row{
color: #37DBFF;
background: linear-gradient( 90deg, rgba(30,54,88,0) 0%, #0C4FAD 53%, rgba(65,117,190,0) 100%);
}
}
}

@ -1,5 +1,5 @@
<template>
<div class="video-player">
<div class="real-video-player">
<video ref="refPlayer" autoplay controls muted width="100%" height="100%" style="object-fit: fill;"></video>
<!-- <iframe src="http://192.168.10.113:8889/cam/" frameborder="0"></iframe> -->
</div>
@ -35,12 +35,4 @@ onUnmounted(() => {
webRtcServer.disconnect();
webRtcServer.value = null;
})
</script>
<style lang="scss">
.video-player {
position: fixed;
width: 50%;
z-index: 999999999;
}
</style>
</script>

@ -9,7 +9,7 @@
</ContentHeader>
</div>
<div class="px-[16px] device-status-content-box">
<HistoryVideoModal />
<div class="mt-[16px] bg-transparent baseTable_wrap full_table" v-loading="dataLoading"
:element-loading-svg="svg" element-loading-svg-view-box="-10, -10, 50, 50">
<template v-if="pagination.total > 0">
@ -44,9 +44,9 @@
</template>
</div>
</div>
<RealVideoModal v-model:value="isRealOpen" :info="currentRow" @close="isRealOpen = false" />
<HistoryVideoModal />
</div>
</template>
@ -54,6 +54,7 @@
import { BaseTable } from "@/components/CustomTable";
import ContentHeader from '@/components/ContentHeader.vue';
import HistoryVideoModal from './components/HistoryVideoModal.vue';
import RealVideoModal from './components/RealVideoModal.vue';
import onLineIcon from '@/assets/common/online_icon.png';
import outLineIcon from '@/assets/common/outline_icon.png';
import errorIcon from '@/assets/common/error_icon.png';
@ -96,6 +97,7 @@ const deleteModel = reactive<{
});
const currentRow = ref<Record<string, any>>({});
const isRealOpen = ref<Boolean>(false);
@ -174,13 +176,6 @@ const pagination = ref({ currentPage: 1, pageSize: 10, total: 0 });
const listData = ref([]);
// const searchValue = ref("");
// const formData = reactive({
// name: "",
// status: ""
// });
const dataLoading = ref(true);
const getList = async () => {
@ -212,6 +207,8 @@ function handleTableChange(record) {
function openCurrent(row) {
console.log(row, "openCurrent");
currentRow.value = row;
isRealOpen.value = true;
}
function openHistory(row) {

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-03-06 15:15:01
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-03-12 15:01:18
* @LastEditTime: 2025-03-12 20:57:12
* @FilePath: \vite-ai\data-dashboard\src\views\dashboard\PoleMonitor.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
@ -75,7 +75,8 @@
<template v-if="pagination.total > 0">
<BaseTable class="bg-transparent baseTable_box" :total="pagination.total"
:pageSize="pagination.pageSize" :dataSource="listData" :isFixedPagination="true"
:columns="columns" :page="pagination.currentPage" @change="handleTableChange">
:columns="columns" :page="pagination.currentPage" @change="handleTableChange" :row-class-name="handleRowClassName"
@row-click="handleRowClick">
</BaseTable>
</template>
</div>
@ -120,7 +121,8 @@ const onSwiper = (swiper) => {
const onSlideChange = () => {
console.log("slide change");
};
//
const currentRowIndex = ref(-1);
// const currentRow = ref<Record<string, any>>({});
const columns = [
{
@ -215,7 +217,16 @@ function handleTableChange(record) {
};
getList();
}
// TODO
//
const handleRowClassName = ({ rowIndex }) => {
return rowIndex === currentRowIndex.value ? 'selected-row' : '';
};
//
const handleRowClick = (row, event, rowIndex) => {
currentRowIndex.value = rowIndex;
};
onMounted(() => {
getList();
});

@ -1,47 +1,12 @@
<template>
<div class="video-player">
<video ref="refPlayer" autoplay controls muted width="100%" height="100%" style="object-fit: fill;"></video>
<!-- <iframe src="http://192.168.10.113:8889/cam/" frameborder="0"></iframe> -->
<div class="historyVideoModal-wrap">
</div>
<!-- http://192.168.10.113:8889/cam/ -->
</template>
<script setup lang="ts">
import { nextTick } from 'vue';
const webRtcServer = ref(null);
const refPlayer = ref(null);
const videoSrc = 'rtsp://192.168.10.63:8554/mystream';
<style lang="scss" scoped>
function initData() {
webRtcServer.value.connect(videoSrc || '', '', "rtptransport=tcp&timeout=60&width=320&height=0");
}
onMounted(() => {
//
// let srvUrl = 'http://127.0.0.1:8000';
nextTick(() => {
console.log(location.protocol, "refPlayer");
// TODO
webRtcServer.value = new WebRtcStreamer(refPlayer.value, `http://192.168.10.26:9988`);
nextTick(() => {
videoSrc && initData();
})
})
})
onUnmounted(() => {
webRtcServer.disconnect();
webRtcServer.value = null;
})
</script>
<style lang="scss">
.video-player {
position: fixed;
width: 50%;
z-index: 999999999;
}
</style>

@ -0,0 +1,127 @@
<template>
<el-dialog v-model="show" @close="handleClose">
<!-- 自定义标题栏 -->
<template #header="{ close, titleId, titleClass }">
<div class="flex items-center justify-between video-dialog-header">
<div class="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div>
<span>{{ info.name }}</span>
</div>
</div>
</template>
<!-- 视频播放区域 -->
<div class="video-container">
<RealPlayer />
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import RealPlayer from '@/components/videoPlayer/RealPlayer.vue'
interface Props {
/** 弹窗显隐 */
value: boolean;
info: Record<string, any>;
}
interface Emits {
(e: "update:value", val: boolean): void;
}
// const props = withDefaults(defineProps<{
// isOpen: boolean;
// info: Record<string, any>;
// }>(), {
// isOpen: false,
// info: {}
// });
const props = withDefaults(defineProps<Props>(), {
value: false,
info: {}
});
const emit = defineEmits<Emits>();
const isPlaying = ref(false);
const togglePlay = () => {
isPlaying.value = !isPlaying.value;
};
//
const handleClose = () => {
emits('close');
};
const show = computed({
get() {
return props.value;
},
set(val: boolean) {
emit("update:value", val);
}
});
</script>
<style lang="scss">
.el-dialog {
border: none;
overflow: hidden;
box-shadow: none;
background-color: transparent;
background-image: url("@/assets/common/bg_real_dialog.png");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
width: 805px;
height: 612px;
padding: 0;
.el-dialog__header.show-close {
padding: 0;
}
.el-dialog__close {
width: 56px;
height: 56px;
color: white;
font-size: 18px;
padding-top: 4px;
padding-right: 20px;
}
.video-dialog-header {
color: white;
padding: 0;
padding-top: 4px;
.header-left {
padding: 0 20px;
font-weight: bold;
font-size: 18px;
.header-icon {
margin-top: 8px;
width: 48px;
height: 48px;
background-image: url("@/assets/common/dialog_title_icon.png");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
}
}
.video-container {
padding: 24px;
// background: red;
.real-video-player {
border-radius: 0px 0px 4px 4px;
overflow: hidden;
}
}
}
</style>
Loading…
Cancel
Save