vue+flv.js

<template>

<div style="height: 100vh">

<el-row style="height: 100%">

<el-col :span="4" style="display: flex;flex-direction: column;">

<!-- <div style="height: 200px;border:1px solid #ccc;border-radius: 5px;">

<div style="font-weight: bold;margin-top: 10px;margin-left: 10px;margin-bottom:10px;">

视图

</div>

<div style="border-top: 1px solid #ccc;" class="onehuaStyle" @click="huaClick('1')">单画面</div>

<div class="onehuaStyle" @click="huaClick('4')">四画面</div>

<div class="onehuaStyle" @click="huaClick('9')">九画面</div>

<div style="border-bottom: 0px;" class="onehuaStyle" @click="huaClick('12')">十二画面</div>

</div> -->

<div style="flex:7;border-radius: 5px;background-color: rgb(36,48,79)">

<div style="font-weight: bold;margin-left: 10px;margin-bottom:10px;color: #ffffff;padding: 10px 0px;">

<div>设备机构名称</div>

</div>

<el-form :model="formData" ref="vForm" :rules="rules" label-width="140px" @submit.prevent class="zq-form">

<div style="width: 100%;padding: 0px 10px;">

<el-input class="el-inputStyle" v-model="filterText" placeholder="" size="small" :suffix-icon="Search" />

</div>

<el-row style="height: 60vh;overflow: auto;margin-top:10px;">

<el-col>

<el-form-item label="" label-width="10px" prop="nodeSort">

<el-tree ref="treeRef" :data="treedata" node-key="id" :props="twodefaultProps"

:filter-node-method="filterNode" @node-click="handleNodeClick" :expand-on-click-node="false"

class="sheThreeStyle" default-expand-all :auto-expand-parent="false">

<template #default="{ node, data }">

<span class="custom-tree-node">

<span>{{ node.label }}</span>

<span v-if="data.type == 'device'">

<span v-if="data.status == '0'" style="

display: inline-block;

width: 10px;

height: 10px;

border: 1rpx solid red;

border-radius: 100px;

background-color: red;

margin-left: 10px;

"></span>

<span v-if="data.status == '1'" style="

display: inline-block;

width: 10px;

height: 10px;

border: 1rpx solid green;

border-radius: 100px;

background-color: green;

margin-left: 10px;

"></span>

</span>

</span>

</template>

</el-tree>

</el-form-item>

</el-col>

</el-row>

</el-form>

</div>

<div style="flex:3;border-radius: 5px;margin-top: 10px;background-color: rgb(36,48,79)">

<div style="padding:10px 0px">

<div style="font-weight: bold;margin-top: 10px;margin-left: 10px;margin-bottom:10px;color: #ffffff;">

记忆收藏夹

</div>

</div>

<el-row style="height: 180px;overflow: auto;background-color: rgb(36,48,79)">

<el-col>

<el-form-item label="" label-width="10px" prop="nodeSort">

<el-tree :data="dataSource" node-key="id" :props="defaultProps" :expand-on-click-node="false"

@node-click="sheClick" style="background: rgb(46, 61, 97);" class="sheThreeStyle">

<template #default="{ node, data }">

<span class="custom-tree-node">

<span style="margin-right: 15px;">{{ node.label }}</span>

<span v-if="data.type == 'bookmark'">

<a @click="append(data)" style="color: green;"> 添加设备 </a>

<a style="margin-left: 8px;color: green" @click="updates(node, data)">

修改收藏夹

</a>

<a style="margin-left: 8px;color:red;" @click="remove(node, data)">

删除

</a>

</span>

<span v-if="data.type == 'device'">

<a style="margin-left: 8px;color:red;" @click="removeDevice(node, data)">

删除

</a>

<span v-if="data.status == '0'" style="

display: inline-block;

width: 10px;

height: 10px;

border: 1rpx solid red;

border-radius: 100px;

background-color: red;

margin-left: 10px;

"></span>

<span v-if="data.status == '1'" style="

display: inline-block;

width: 10px;

height: 10px;

border: 1rpx solid green;

border-radius: 100px;

background-color: green;

margin-left: 10px;

"></span>

</span>

</span>

</template>

</el-tree>

</el-form-item>

<div style="

color: rgb(79, 158, 254);

cursor: pointer;

font-size: 14px;

margin-right: 10px;

display: flex;

justify-content: center;

" @click="addCollect">

<div

style="width:90px;font-size:15px;border:1px solid rgb(54,121,211);color: rgb(169,175,190);text-align: center;border-radius: 5px;">

添加收藏夹

</div>

</div>

</el-col>

</el-row>

</div>

</el-col>

<el-col :span="20" style="padding:0 0 0 15px;display: flex;flex-direction: column;">

<el-row style="flex: 8;">

<!-- 点击画面循环,下标 -->

<el-col v-for="(item, index) in generatedItems" :key="index" :span="splitScreen"

style="background-color: rgb(33,37,41);" @click="generatedItemsClick(item, index, $event)">

<div class="oneMyfle" :class="Indexcol == index ? 'Indexcol' : ''">

<video :id="'myFlvVideo' + index" autoplay :controls="fasle" :class="myFlvVideo" />

<div :class="myClassName">

<div class="mar-le" :id="'shename' + index">{{ sheName(index) }}</div>

</div>

<div style="display: flex;align-items: center;">

<div style="font-size: 20px;color:red;position: absolute;right: 5px;bottom: 5px;cursor: pointer;"

@click="closeClick(index, $event)" v-if="Indexcol == index && isCloseShow">X</div>

<div style="font-size: 20px;color:red;position: absolute;right: 30px;bottom: 5px;cursor: pointer;"

@click="takeClick(index, $event)" v-if="Indexcol == index && isCloseShow">

<img src="@/assets/images/zhua.png" style="height: 20px;" alt="">

</div>

</div>

</div>

</el-col>

</el-row>

<!-- 下边图片 -->

<div style="flex:2;margin-top:10px;">

<div style="background-color: rgb(36,48,79);width: 100%;height: 100%;">

<div style="display: flex;justify-content: space-around;align-items: center;width: 100%;height: 100%;">

<img src="@/assets/images/1p.png" class="imgStyle" @click="huaClick('1')">

<img src="@/assets/images/4p.png" class="imgStyle" alt="" @click="huaClick('4')">

<img src="@/assets/images/9p.png" class="imgStyle" alt="" @click="huaClick('9')">

<img src="@/assets/images/12p.png" class="imgStyle" alt="" @click="huaClick('12')">

</div>

</div>

</div>

</el-col>

</el-row>

</div>

<AddCollect @doRefresh="resfre" ref="AddCollectRef"></AddCollect>

<EditDeviceTree @doRefresh="resfre" ref="EditDeviceTreeRef"></EditDeviceTree>

<AddDeviceTree @doRefresh="resfre" ref="AddDeviceTreeRef"></AddDeviceTree>

</template>

<script setup>

import {

defineComponent,

toRefs,

reactive,

getCurrentInstance,

ref,

onMounted,

onBeforeUnmount,

computed,

watch,

nextTick,

} from "vue";

import AddCollect from "./addCollect.vue";

import { useStore } from "@zqxx/store";

import {

videoInvokeDeviceTree,

videoInvokeBookmarkTree,

videoInvokeDele,

videoInvokeDeleDevice,

videoInvokeDeviceInfo,

} from "./api/scenicaArea";

import AddDeviceTree from "./addDeviceTree.vue";

import EditDeviceTree from "./EditDeviceTree.vue";

import { Search } from '@element-plus/icons-vue'

import { cloneObject, DateFormat } from "@zqxx/utils";

const store = useStore();

console.log(store, '999999999999999')

import flvjs from "flv.js";

let url = ref([]);

let myClassName = ref('oneoneMyfles');

let myFlvVideo = ref('myFlvVideoClass');

let oneoneMyfle = ref(true);

let twoMyfle = ref(false);

let threeMyfle = ref(false);

let fiveMyfle = ref(false);

let twourl = ref([]);

onMounted(() => {

getdeviceTree();

getInvokeBookmarkTree();

// 进入页面折叠菜单

store.app.setIsCollapseChange(true)

});

onBeforeUnmount(() => { });

// 收藏夹树

const getInvokeBookmarkTree = async () => {

let res = await videoInvokeBookmarkTree();

dataSource.value = res.data;

console.log(res, "ssssss");

};

let treedata = ref([]);

const getdeviceTree = async () => {

let res = await videoInvokeDeviceTree();

treedata.value = res.data;

};

let huaNum = ref("1");

const huaClick = (value) => {

huaNum.value = value;

Indexcol.value = '0'

if (value == "1") {

myClassName.value = 'oneoneMyfles'

myFlvVideo.value = 'myFlvVideoClass'

} else if (value == "4") {

myClassName.value = 'twoMyfles'

myFlvVideo.value = 'twomyFlvVideoClass'

} else if (value == "9") {

myClassName.value = 'threeMyfles'

myFlvVideo.value = 'threemyFlvVideoClass'

} else if (value == "12") {

myClassName.value = 'fiveMyfles'

myFlvVideo.value = 'fivemyFlvVideoClass'

}

};

const splitScreen = computed(() => {

switch (huaNum.value) {

case "1":

return 24;

break;

case "4":

return 12;

break;

case "9":

return 8;

break;

case "12":

return 8;

break;

}

});

const generatedItems = computed(() => [

...Array(parseInt(huaNum.value)).keys(),

]);

const isCloseShow = computed(() => {

console.log(Indexcol.value, "Indexcol.value");

return url.value.some(item => item.index == Indexcol.value)

})

const sheName = computed(() => {

return function (index) {

return url.value.find((item) => item.index == index)?.shename ?? null

}

})

const closeClick = (index, e) => {

url.value.splice(url.value.findIndex(item => (item.index == index)), 1)

destoryVideo(flvPlayer.value.find(item => item.index == index)["player"])

flvPlayer.value.splice(flvPlayer.value.findIndex(item => (item.index == index)), 1)

}

const takeClick = (index, e) => {

const url=[

{

id:'1',

aa:'2',

index:'0'

},

{

id:'2',

aa:'33',

index:'2'

}

]

const item = url.find(item => item.index == index)

console.log(item, 'item')

}

let flvPlayer = ref([]);

let arr = ref([])

const init = (i, id) => {

console.log(i, id, "i-id");

if (url.value && url.value.length) {

// 拿到点击的树形id那一项和数组里url一项id匹配

const item = url.value.find(item => item.id == id)

console.log(url.value, "init url");

console.log(item);

let player = null;

var videoElement = document.getElementById("myFlvVideo" + i);

console.log(videoElement, "videoElement");

player = flvjs.createPlayer(

{

type: "flv",

url: item["url"],

},

{

cors: true, // 是否跨域

enableWorker: false,

autoCleanupSourceBuffer: true, //对SourceBuffer进行自动清理缓存

enableStashBuffer: false, //关闭IO隐藏缓冲区

stashInitialSize: 128, //减少首帧显示等待时长

fixAudioTimestampGap: false, //音频同步

}

);

player.attachMediaElement(videoElement);

player.load();

setTimeout(function () {

player.play() // 播放数据流

}, 300)

player.on(flvjs.Events.ERROR, (errorInfo, errType, errDetail) => {

if (errorInfo.code == 404) {

this.$message.error('流媒体代理服务未找到,请检查');

}

// if (player) {

// destoryVideo(player)

// console.log(player, 'player')

// }

});

flvPlayer.value = flvPlayer.value.filter(item => item.index != i)

flvPlayer.value.push({ "id": id, "player": player, "index": i })

console.log(flvPlayer.value, 'flvPlayer.valueflvPlayer.valueflvPlayer.value')

}

}

const destoryVideo = (flvPlayer) => {

console.log(flvPlayer, 'flvPlayer1')

if (flvPlayer && flvPlayer !== null) {

try {

flvPlayer.unload();

flvPlayer.detachMediaElement();

flvPlayer.destroy();

console.log("销毁销毁销毁销毁");

} catch (error) {

}

}

};

let Indexcol = ref(0)

const generatedItemsClick = (item, index, e) => {

Indexcol.value = index

console.log("当前的INDEX", Indexcol.value);

};

const filterText = ref("");

const treeRef = ref("");

watch(filterText, (val) => {

treeRef.value?.filter(val);

});

const filterNode = (value, data, node) => {

let names = getParents(node, node.data.name, 'name');

let isName = names.indexOf(value) !== -1;

return !value || isName ? true : false

};

const getParents = (node, name, key) => {

if (node.parent && node.parent.data[key]) {

name += node.parent.data[key]

return getParents(node.parent, name, key)

}

return name

}

const onClickAddNew = (row) => {

handleAddPage(row);

};

let shename = ref([]);

let Gonetree = ref([]);

let gonVis = ref(false);

const handleNodeClick = async (data) => {

if (data && data.type == "device") {

sheClick(data)

}

};

const deviceInfo = async (data, index) => {

// 监控设备

console.log(data, "data22222222222222");

let params = {

deviceId: data.deviceId,

id: data.id,

name: data.name,

parentName: data.parentName,

};

let res = await videoInvokeDeviceInfo(params);

url.value = url.value.filter(item => item.index != index)

url.value.push({ "url": res.data.cameraImages[0].FlvUrl, "id": res.data.id, "shename": res.data.name, "index": index });

};

const sheClick = async (data) => {

if (data && data.type == "device" && data.status == "1") {

// 获取树形id

const id = data.id

console.log(url.value, 'value99')

// 默认设置索引Indexcol----0

await deviceInfo(data, parseInt(Indexcol.value));

if (huaNum.value == '1') {

try {

console.log(flvPlayer.value, 'flvValue')

destoryVideo(flvPlayer.value[0]["player"])

} catch (error) {

}

flvPlayer.value = []

console.log(url.value, '2222222222222')

url.value = [url.value[url.value.length - 1]]

init(0, id)

} else {

const item = flvPlayer.value.find(item => item.index == Indexcol.value

)

console.log(item, "console.log(item);");

if (item && item.hasOwnProperty("player") && item["player"]) {

destoryVideo(item["player"])

}

init(Indexcol.value, id)

}

}

};

const resfre = () => {

getInvokeBookmarkTree();

};

const defaultProps = ref({

children: "children",

label: "name",

id: "id",

});

const twodefaultProps = ref({

children: "children",

label: "name",

id: "id",

});

let formData = ref({});

let AddCollectRef = ref("");

// 收藏

const addCollect = () => {

AddCollectRef.value.show();

};

let AddDeviceTreeRef = ref("");

const append = async (data) => {

AddDeviceTreeRef.value.show(data);

};

let EditDeviceTreeRef = ref("");

const updates = (node, data) => {

EditDeviceTreeRef.value.show(data);

};

const remove = (node, data) => {

console.log(node, "node");

console.log(data, "data");

ElMessageBox.confirm(

"确定要删除收藏夹?如果删除该收藏夹下收藏的设备也会被删除",

{

confirmButtonText: "确定",

cancelButtonText: "取消",

}

)

.then(() => {

videoInvokeDele(data.id).then((res) => {

if (res.code == 200) {

getInvokeBookmarkTree();

}

});

})

.catch(() => {

ElMessage({

type: "info",

message: "已取消",

});

});

};

const removeDevice = (node, data) => {

ElMessageBox.confirm("确定删除该设备?", {

confirmButtonText: "确定",

cancelButtonText: "取消",

})

.then(() => {

videoInvokeDeleDevice(data.id).then((res) => {

if (res.code == 200) {

getInvokeBookmarkTree();

}

});

})

.catch(() => {

ElMessage({

type: "info",

message: "已取消",

});

});

};

const dataSource = ref([]);

</script>

<style lang="scss" scoped>

.Indexcol {

border: 4px solid rgb(11, 63, 234);

height: 100%;

}

video:not(video[src]) {

background-image: url("@/assets/images/notavailable.png");

background-repeat: no-repeat;

background-size: 45px;

background-position: center

}

.onehuaStyle {

border-bottom: 1px solid #ccc;

display: flex;

padding: 10px;

justify-content: center;

align-items: center;

font-weight: bold;

cursor: pointer;

}

.onehuaStyle:hover {

color: rgb(79, 158, 254);

}

.displayheader {

display: flex;

justify-content: space-between;

align-items: center;

}

::v-deep {

.el-tree-node:focus>.el-tree-node__content {

background: rgb(59, 101, 199) !important;

}

.sheThreeStyle {

background-color: rgb(46, 61, 79, 0.6);

color: rgb(78, 149, 252);

width: 100%;

}

.sheThreeStyle .el-tree-node__content:hover {

background: rgb(59, 101, 199);

}

.sheThreeStyle .el-tree-node__content {

background: rgb(46, 61, 97);

}

.sheThreeStyle .el-tree-node__content :focus {

background: red;

}

.el-inputStyle .el-input__inner {

background: rgb(46, 61, 79);

color: white;

}

.el-inputStyle .el-input__suffix-inner {

background: rgb(78, 149, 252);

color: white;

}

.el-inputStyle .el-input__wrapper {

background: rgb(78, 149, 252);

}

.imgStyle:hover {

transform: scale(1.7);

transition: all 0.3s ease-in-out;

}

.imgStyle {

height: 55px;

cursor: pointer;

}

.myFlvVideoClass {

width: 100%;

height: 80vh;

object-fit: fill;

border: 5px solid #cccccc1c;

}

.twomyFlvVideoClass {

width: 100%;

height: 40vh;

object-fit: fill;

border: 5px solid #cccccc1c;

}

.threemyFlvVideoClass {

width: 100%;

height: 26.6vh;

object-fit: fill;

border: 5px solid #cccccc1c;

}

.fivemyFlvVideoClass {

width: 100%;

height: 20vh;

object-fit: fill;

border: 5px solid #cccccc1c;

}

.el-card__body {

height: 250px;

overflow: auto;

}

.el-tree__empty-text {

display: none;

}

::-webkit-scrollbar {

width: 0px;

height: 0px;

}

::-webkit-scrollbar-thumb {

background-color: #ccc;

}

}

.point {

width: 12rpx;

height: 12rpx;

border: 1rpx solid red;

border-radius: 100px;

background-color: red;

}

.twopoint {

width: 12rpx;

height: 12rpx;

border: 1rpx solid green;

border-radius: 100px;

background-color: green;

}

.oneMyfle {

position: relative;

margin: 0px 3px;

}

.oneoneMyfles {

display: flex;

align-items: center;

position: absolute;

top: 35px;

margin-left: 25px;

font-size: 25px;

}

.mar-le {

margin-left: 10px;

font-weight: bold;

color: white;

}

.twoMyfles {

display: flex;

align-items: center;

position: absolute;

top: 20px;

margin-left: 10px;

font-size: 18px;

}

.threeMyfles {

display: flex;

align-items: center;

position: absolute;

top: 10px;

margin-left: 5px;

font-size: 10px;

}

.fiveMyfles {

display: flex;

align-items: center;

position: absolute;

top: 10px;

margin-left: 5px;

font-size: 10px;

}

video::-webkit-media-controls-enclosure {

display: none;

}

.normal {

background-color: red;

}

.box-card {}

</style>

相关推荐
王哈哈^_^42 分钟前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie1 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic2 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿2 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具2 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
清灵xmf3 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据3 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161773 小时前
防抖函数--应用场景及示例
前端·javascript
334554324 小时前
element动态表头合并表格
开发语言·javascript·ecmascript