videowallbak2.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <template>
  2. <el-row>
  3. <el-col :span="4">
  4. <div class="box">
  5. <el-scrollbar>
  6. <basic-container>
  7. <el-input
  8. placeholder="输入关键字进行过滤"
  9. v-model="filterText">
  10. </el-input>
  11. <el-tree ref="tree" class="filter-tree" :props="treeProps" :data="treeData" @node-click="handleNodeClick"
  12. lazy :load="treeLoad":filter-node-method="filterNode">
  13. <span class="custom-tree-node" slot-scope="{ node, data }">
  14. <span>{{ node.label }}</span>
  15. <span v-if="node.isLeaf">
  16. <el-button
  17. type="text"
  18. size="mini"
  19. @click="() => clickPlay(data)">
  20. 播放
  21. </el-button>
  22. <el-button
  23. style="color:red"
  24. type="text"
  25. size="mini"
  26. @click="() => clickStop(node, data)">
  27. 停止
  28. </el-button>
  29. </span>
  30. </span>
  31. </el-tree>
  32. </basic-container>
  33. </el-scrollbar>
  34. </div>
  35. </el-col>
  36. <el-col :span="20">
  37. <basic-container>
  38. <div style="margin-bottom: 20px">
  39. <el-radio-group v-model="screen" size="mini" @change="screenChange">
  40. <el-radio-button :label="4">四屏</el-radio-button>
  41. <el-radio-button :label="6">六分屏</el-radio-button>
  42. <el-radio-button :label="9">九分屏</el-radio-button>
  43. <el-radio-button :label="16">十六分屏</el-radio-button>
  44. </el-radio-group>
  45. </div>
  46. <el-row :gutter="4">
  47. <div class="item4" v-for="(item,index) in data4" :key="index" v-if="screen == 4">
  48. <div align="center">{{item.name}}</div>
  49. <video :id="'videoId' + index" controls="true" width="100%" height="100%">
  50. </video>
  51. </div>
  52. <el-col :span="screenSpan" v-for="(item,index) in screenData" :key="screen + index" v-if="item.display">
  53. <player style="position:sticky;overflow: hidden;" :jessibucaId="'jessibucaId' + index" :container="'container' + index" :buttonsBoxId="'buttonsBoxId' + index" :ref="'videoPlayer' + index" :hasaudio="hasaudio" fluent autoplay live ></player>
  54. </el-col>
  55. </el-row>
  56. </div>
  57. </basic-container>
  58. </el-col>
  59. </el-row>
  60. </template>
  61. <script>
  62. import {getGbChannelLazyTree, startPlay, stopPlay} from "@/api/device/gb/gbdevicechannel";
  63. import player from './jessibuca.vue'
  64. export default {
  65. name: "videowall",
  66. components: {player},
  67. data () {
  68. return {
  69. // itemClass: {
  70. // width: '500px',
  71. // overflow: 'hidden',
  72. // borderRadius: '5px',
  73. // margin: '5px',
  74. // position: 'sticky'
  75. // },
  76. screenSpan: 4,
  77. screen: 4,
  78. screenData:[],
  79. playerRef: "4videoPlayer",
  80. filterText: '',
  81. treeData : [],
  82. treeProps:{
  83. labelText: '标题',
  84. label: 'label',
  85. parentLabel: 'parentLabelName',
  86. children: 'children',
  87. isLeaf: "leaf"
  88. },
  89. form:{},
  90. data4:[],
  91. data6:[],
  92. data9:[],
  93. data16:[],
  94. loading:true,
  95. data:[],
  96. }
  97. },
  98. watch: {
  99. filterText(val) {
  100. this.$refs.tree.filter(val);
  101. }
  102. },
  103. created(){
  104. this.initData();
  105. },
  106. methods:{
  107. initData(){
  108. for(let i = 0; i < 16; i++){
  109. let item = null;
  110. if(i <= 3){
  111. item = {name:"", isPlay:false, index:i, channelId:null, display:true};
  112. }else{
  113. item = {name:"", isPlay:false, index:i, channelId:null, display:false};
  114. }
  115. this.screenData.push(item);
  116. // if(i <= 3){
  117. // this.data4.push(item);
  118. // this.data6.push(item);
  119. // this.data9.push(item);
  120. // this.data16.push(item);
  121. // }else if(i > 3 && i <= 5){
  122. // this.data6.push(item);
  123. // this.data9.push(item);
  124. // this.data16.push(item);
  125. // }else if(i > 5 && i <= 8){
  126. // this.data9.push(item);
  127. // this.data16.push(item);
  128. // }else if(i > 8 && i <= 15){
  129. // this.data16.push(item);
  130. // }
  131. }
  132. },
  133. screenChange(value){
  134. if(value === 4){
  135. this.screenSpan = 12;
  136. for(let i=0; i<16; i++){
  137. if(i < 4){
  138. this.screenData[i].display = true;
  139. }else{
  140. this.screenData[i].display = false;
  141. }
  142. }
  143. }else if(value === 6){
  144. this.screenSpan = 8;
  145. for(let i=4; i<16; i++){
  146. if(i < 6){
  147. this.screenData[i].display = true;
  148. }else{
  149. this.screenData[i].display = false;
  150. }
  151. }
  152. }else if(value === 9){
  153. this.screenSpan = 8;
  154. for(let i=6; i<9; i++){
  155. if(i < 9){
  156. this.screenData[i].display = true;
  157. }else{
  158. this.screenData[i].display = false;
  159. }
  160. this.screenData[i].display = true;
  161. }
  162. }else if(value === 16){
  163. this.screenSpan = 6;
  164. for(let i=4; i<16; i++){
  165. this.screenData[i].display = true;
  166. }
  167. }
  168. },
  169. treeLoad(node, resolve){
  170. const parentId = (node.level === 0) ? null : node.data.id;
  171. let parentColumn = null;
  172. const tenantId = localStorage.getItem("tenantId");
  173. if(tenantId === "000000"){
  174. if(node.level === 0){
  175. parentColumn = "0";
  176. }else if(node.level === 1){
  177. parentColumn = "agency";
  178. }else if(node.level === 2){
  179. parentColumn = "residential";
  180. }else if(node.level === 3){
  181. parentColumn = "building";
  182. }else if(node.level === 4){
  183. parentColumn = "floor";
  184. }else{
  185. parentColumn = null;
  186. }
  187. }else{
  188. if(node.level === 0){
  189. parentColumn = "0";
  190. }else if(node.level === 1){
  191. parentColumn = "residential";
  192. }else if(node.level === 2){
  193. parentColumn = "building";
  194. }else if(node.level === 3){
  195. parentColumn = "floor";
  196. }else{
  197. parentColumn = null;
  198. }
  199. }
  200. getGbChannelLazyTree(parentColumn, parentId).then(res => {
  201. resolve(res.data.data.map(item => {
  202. return {
  203. ...item,
  204. leaf: !item.hasChildren
  205. }
  206. }))
  207. });
  208. },
  209. filterNode(value, data) {
  210. if (!value) return true;
  211. return data.label.indexOf(value) !== -1;
  212. },
  213. handleNodeClick(node, resolve){},
  214. clickPlay(data){
  215. this.$message.success("开始调取视频");
  216. //找到第一个没有播放的屏幕
  217. let emptyIndex = this.screenData.findIndex((item) => item.isPlay == false);
  218. if(emptyIndex >= 0){ //表示找到
  219. this.playVideo(data, emptyIndex);
  220. this.screenData[emptyIndex].isPlay = true;
  221. this.screenData[emptyIndex].channelId = data.channelId;
  222. return false;
  223. }else{
  224. this.playVideo(data, 0);
  225. this.screenData[0].isPlay = true;
  226. this.screenData[0].channelId = data.channelId;
  227. }
  228. },
  229. playVideo(treeItem, index){
  230. let deviceId = treeItem.deviceId;
  231. let channelId = treeItem.channelId;
  232. console.log(this.$refs[this.playerRef + index]);
  233. startPlay(deviceId, channelId).then(res => {
  234. if (res.data.data) {
  235. let streamInfo = res.data.data;
  236. this.$refs[this.playerRef + index][0].play(streamInfo.ws_flv);
  237. // try {
  238. // let videoElement = document.getElementById("videoId" + index);
  239. // let flvPlayer = flvjs.createPlayer({
  240. // type: 'flv',
  241. // url: streamInfo.ws_flv
  242. // });
  243. // flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {});
  244. // flvPlayer.on(flvjs.Events.MEDIA_SOURCE_CLOSE || flvjs.Events.MEDIA_SOURCE_ENDED, () => {});
  245. // flvPlayer.attachMediaElement(videoElement);
  246. // flvPlayer.load();
  247. // flvPlayer.play();
  248. // treeItem.isPlay = true;
  249. // } catch (e) {
  250. // console.log(e);
  251. // }
  252. }
  253. });
  254. },
  255. clickStop(node, treeItem){
  256. this.$message.warning("正在停止");
  257. let screenData = null;
  258. let deviceId = treeItem.deviceId;
  259. let channelId = treeItem.channelId;
  260. let channelVideoIndex = this.screenData.findIndex((item,index) => {return item.channelId == treeItem.channelId});
  261. this.$refs[this.playerRef + channelVideoIndex][0].pause();
  262. // stopPlay(deviceId, channelId).then(res => {
  263. // this.$message.success("停止成功");
  264. // this.screenData[channelVideoIndex].isPlay = false;
  265. // this.screenData[channelVideoIndex].channelId = null;
  266. // });
  267. }
  268. },
  269. }
  270. </script>
  271. <style lang="less">
  272. .box {
  273. height: 800px;
  274. }
  275. .el-scrollbar {
  276. height: 100%;
  277. }
  278. .box .el-scrollbar__wrap {
  279. overflow: scroll;
  280. }
  281. #videoSurveillance {
  282. width: 100%;
  283. height: 100%;
  284. display: flex;
  285. flex-wrap: wrap;
  286. box-sizing: border-box;
  287. .item4 {
  288. width: calc(~"49%");
  289. overflow: hidden;
  290. border-radius: 5px;
  291. margin: 5px;
  292. position: sticky;
  293. }
  294. .item6 {
  295. width: calc(~"32%");
  296. overflow: hidden;
  297. border-radius: 5px;
  298. margin: 5px;
  299. position: sticky;
  300. }
  301. .item9 {
  302. width: calc(~"32%");
  303. overflow: hidden;
  304. border-radius: 5px;
  305. margin: 5px;
  306. position: sticky;
  307. }
  308. .item16 {
  309. width: calc(~"24%");
  310. overflow: hidden;
  311. border-radius: 5px;
  312. margin: 5px;
  313. position: sticky;
  314. }
  315. }
  316. .custom-tree-node {
  317. flex: 1;
  318. display: flex;
  319. align-items: center;
  320. justify-content: space-between;
  321. font-size: 14px;
  322. padding-right: 8px;
  323. }
  324. </style>