13 changed files with 335 additions and 124 deletions
@ -0,0 +1,28 @@ |
|||||
|
<template> |
||||
|
<video controls class="video-stream" v-bind="$attrs" ref="videoContainerRef" /> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { openVideoStream } from "./videoStream.js" |
||||
|
|
||||
|
export default { |
||||
|
name: 'Video', |
||||
|
props: { |
||||
|
camId: { |
||||
|
type: String, |
||||
|
default: null |
||||
|
}, |
||||
|
url: { |
||||
|
type: String, |
||||
|
default: null |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
openVideoStream(this.$refs.videoContainerRef, { camId: this.camId, url: this.url }) |
||||
|
}, |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang='scss' scoped> |
||||
|
.video-stream {} |
||||
|
</style> |
@ -0,0 +1,41 @@ |
|||||
|
import flvJs from "flv.js"; |
||||
|
import { getCameraStream } from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js"; |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param {HTMLElement} container 容器 |
||||
|
* @param {{camId?: string; url?: string}?} options {camId: 相机ID; url: 直播地址} |
||||
|
* @returns |
||||
|
*/ |
||||
|
export async function openVideoStream(container, { camId, url } = {}) { |
||||
|
if (camId) { |
||||
|
const { code, data } = await getCameraStream(camId).catch(() => ({})); |
||||
|
|
||||
|
if (code != 200) return; |
||||
|
|
||||
|
url = data.liveUrl; |
||||
|
} |
||||
|
|
||||
|
if (!url) return; |
||||
|
|
||||
|
const flvPlayer = flvJs.createPlayer({ |
||||
|
type: "flv", |
||||
|
url: url, |
||||
|
isLive: true, |
||||
|
hasVideo: true, |
||||
|
hasAudio: true, |
||||
|
}); |
||||
|
|
||||
|
console.log( |
||||
|
"%c [ flvPlayer ]-26-「videoStream.js」", |
||||
|
"font-size:15px; background:#b2b540; color:#f6f984;", |
||||
|
flvPlayer |
||||
|
); |
||||
|
|
||||
|
flvPlayer.attachMediaElement(container); |
||||
|
|
||||
|
flvPlayer.load(); |
||||
|
flvPlayer.play(); |
||||
|
|
||||
|
return flvPlayer; |
||||
|
} |
@ -1,47 +0,0 @@ |
|||||
import flvJs from "flv.js"; |
|
||||
import { getCameraStream } from "./httpList"; |
|
||||
|
|
||||
/** |
|
||||
* |
|
||||
* @param {string} camId 相机ID |
|
||||
* @param {HTMLElement} container 容器 |
|
||||
* @param {DPlayerOptions?} options 配置项 |
|
||||
* @returns |
|
||||
*/ |
|
||||
export async function openVideoStream(camId, container) { |
|
||||
const { code, data } = await getCameraStream(camId).catch(() => ({})); |
|
||||
|
|
||||
if (code != 200) return; |
|
||||
|
|
||||
const flvPlayer = flvJs.createPlayer({ |
|
||||
type: "flv", |
|
||||
url: data.liveUrl, |
|
||||
isLive: true, |
|
||||
hasVideo: true, |
|
||||
hasAudio: true, |
|
||||
}); |
|
||||
|
|
||||
console.log( |
|
||||
"%c [ flvPlayer ]-26-「videoStream.js」", |
|
||||
"font-size:15px; background:#b2b540; color:#f6f984;", |
|
||||
flvPlayer |
|
||||
); |
|
||||
|
|
||||
flvPlayer.attachMediaElement(container); |
|
||||
|
|
||||
flvPlayer.load(); |
|
||||
flvPlayer.play(); |
|
||||
|
|
||||
return flvPlayer; |
|
||||
// return new DPlayer({
|
|
||||
// container,
|
|
||||
// autoplay: true,
|
|
||||
// ...options,
|
|
||||
// hotkey: false,
|
|
||||
// video: {
|
|
||||
// url: data.liveUrl,
|
|
||||
// type: "hls",
|
|
||||
// // type: "flv",
|
|
||||
// },
|
|
||||
// });
|
|
||||
} |
|
@ -1,20 +1,37 @@ |
|||||
<template> |
<template> |
||||
<Card class='RealTimeVideo' title="实时视频"> |
<Card class='RealTimeVideo' title="实时视频"> |
||||
RealTimeVideo |
<Video class="item-video" /> |
||||
|
<Video class="item-video" /> |
||||
</Card> |
</Card> |
||||
</template> |
</template> |
||||
|
|
||||
<script> |
<script> |
||||
import Card from "./../../components/Card.vue" |
import Card from "./../../components/Card.vue"; |
||||
|
import Video from "@screen/components/Video" |
||||
export default { |
export default { |
||||
name: 'RealTimeVideo', |
name: 'RealTimeVideo', |
||||
components: { |
components: { |
||||
Card |
Card, |
||||
|
Video |
||||
} |
} |
||||
} |
} |
||||
</script> |
</script> |
||||
|
|
||||
<style lang='scss' scoped> |
<style lang='scss' scoped> |
||||
.RealTimeVideo {} |
.RealTimeVideo { |
||||
|
::v-deep { |
||||
|
.content { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
gap: 9px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.item-video { |
||||
|
flex: 1; |
||||
|
width: calc(50% - 4.5px); |
||||
|
height: 100%; |
||||
|
} |
||||
|
} |
||||
</style> |
</style> |
||||
|
@ -0,0 +1,150 @@ |
|||||
|
div.el-popper { |
||||
|
background: #123542; |
||||
|
box-shadow: 2px 2px 8px 0px rgba(82, 90, 102, 0.08), |
||||
|
1px 1px 2px 0px rgba(82, 90, 102, 0.04); |
||||
|
border-radius: 4px 4px 4px 4px; |
||||
|
opacity: 1; |
||||
|
border: 0; |
||||
|
|
||||
|
.el-select-dropdown__list { |
||||
|
.el-select-dropdown__item { |
||||
|
font-size: 15px; |
||||
|
font-family: PingFang SC, PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #ffffff; |
||||
|
/** |
||||
|
-webkit-background-clip: text; |
||||
|
-webkit-text-fill-color: transparent; |
||||
|
*/ |
||||
|
&:hover { |
||||
|
background: #0d5f79; |
||||
|
} |
||||
|
&.hover { |
||||
|
background: #0d5f79; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&[x-placement^="top"] { |
||||
|
div.popper__arrow { |
||||
|
border-top-color: #00799f; |
||||
|
|
||||
|
&::after { |
||||
|
border-top-color: #00799f; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&[x-placement^="left"] { |
||||
|
div.popper__arrow { |
||||
|
border-left-color: #00799f; |
||||
|
|
||||
|
&::after { |
||||
|
border-left-color: #00799f; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&[x-placement^="right"] { |
||||
|
div.popper__arrow { |
||||
|
border-right-color: #00799f; |
||||
|
|
||||
|
&::after { |
||||
|
border-right-color: #00799f; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&[x-placement^="bottom"] { |
||||
|
div.popper__arrow { |
||||
|
border-bottom-color: #00799f; |
||||
|
|
||||
|
&::after { |
||||
|
border-bottom-color: #00799f; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&.el-select-dropdown { |
||||
|
&[x-placement^="top"] { |
||||
|
div.popper__arrow { |
||||
|
border-top-color: #1a3442; |
||||
|
|
||||
|
&::after { |
||||
|
border-top-color: #1a3442; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&[x-placement^="left"] { |
||||
|
div.popper__arrow { |
||||
|
border-left-color: #1a3442; |
||||
|
|
||||
|
&::after { |
||||
|
border-left-color: #1a3442; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&[x-placement^="right"] { |
||||
|
div.popper__arrow { |
||||
|
border-right-color: #1a3442; |
||||
|
|
||||
|
&::after { |
||||
|
border-right-color: #1a3442; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&[x-placement^="bottom"] { |
||||
|
div.popper__arrow { |
||||
|
border-bottom-color: #1a3442; |
||||
|
|
||||
|
&::after { |
||||
|
border-bottom-color: #1a3442; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
div.el-scrollbar { |
||||
|
.el-scrollbar__wrap { |
||||
|
/** |
||||
|
overflow: auto; |
||||
|
*/ |
||||
|
overflow-x: hidden; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
body { |
||||
|
input.el-input__inner { |
||||
|
background-color: #0d5f79; |
||||
|
color: #fff; |
||||
|
border-radius: 2px; |
||||
|
border: 0; |
||||
|
height: 100%; |
||||
|
min-height: fit-content; |
||||
|
line-height: unset; |
||||
|
|
||||
|
&::placeholder { |
||||
|
color: #fff; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
div.el-input { |
||||
|
input.el-input__inner { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
} |
||||
|
div.el-textarea { |
||||
|
textarea.el-textarea__inner { |
||||
|
background: #0a3e54; |
||||
|
border-radius: 5px; |
||||
|
opacity: 1; |
||||
|
border: 1px solid rgba(98, 224, 254, 0.6); |
||||
|
} |
||||
|
|
||||
|
.el-input__count { |
||||
|
background-color: rgba(0, 0, 0, 0); |
||||
|
font-size: 12px; |
||||
|
font-family: PingFang SC, PingFang SC; |
||||
|
font-weight: 400; |
||||
|
color: #3de8ff; |
||||
|
line-height: 14px; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
@import url(./el-reset.scss); |
||||
|
|
||||
|
body { |
||||
|
input, |
||||
|
textarea { |
||||
|
caret-color: white; |
||||
|
} |
||||
|
|
||||
|
div { |
||||
|
/* 滚动条整体部分 */ |
||||
|
&::-webkit-scrollbar { |
||||
|
width: 6px !important; |
||||
|
height: 6px !important; |
||||
|
padding: 15px; |
||||
|
} |
||||
|
|
||||
|
/* 滚动条的轨道 */ |
||||
|
&::-webkit-scrollbar-track { |
||||
|
background: rgba(17, 72, 90, 0.4); |
||||
|
border-radius: 4px; |
||||
|
} |
||||
|
|
||||
|
/* 滚动条的滑块按钮 */ |
||||
|
&::-webkit-scrollbar-thumb { |
||||
|
background: #3785a0; |
||||
|
border-radius: 4px; |
||||
|
} |
||||
|
|
||||
|
/* 上下箭头 */ |
||||
|
&::-webkit-scrollbar-button { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/* 滚动条角 */ |
||||
|
&::-webkit-scrollbar-corner { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue