emergencyEvacuationBig.vue 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. <!--应急疏散大屏-->
  2. <template>
  3. <div class="emergencyEvacuationBig scrollbar-box">
  4. <div class="top-max-title-box">
  5. <p>{{title}}<span>{{minTitle}}</span></p>
  6. <!--<p class="inquire-button-one" @click="clickClosure">{{evacuationType?'执行疏散':'结束疏散'}}</p>-->
  7. <p></p>
  8. <p></p>
  9. <p class="reset-button-one" v-if="buttonType" @click="goAllBig"><i class="el-icon-full-screen" style="margin-right:10px;"></i>全屏</p>
  10. <p class="reset-button-one" v-if="!buttonType" @click="clickBack"><i class="el-icon-full-screen" style="margin-right:10px;"></i>退出全屏</p>
  11. <p class="reset-button-one" style="margin-left:20px;" v-if="buttonType" @click="backButton">返回</p>
  12. </div>
  13. <div class="video-max-box">
  14. <div class="video-for-box" v-for="(item,index) in videoList" :key="index">
  15. <div class="video-for-title-box">
  16. <div class="video-for-title">{{item.name}}</div>
  17. <div class="video-for-button" @click="videoFullScreen(index)">
  18. <img src="@/assets/newImages/icon_monitor_enlarge.png">
  19. </div>
  20. </div>
  21. <video class="video-box" :id="item.divId" ref="videoRef" autoplay controls muted width="610px" height="429px"></video>
  22. </div>
  23. </div>
  24. <pagination
  25. layout="total, prev, pager, next, jumper"
  26. style="margin:0 40px 50px;"
  27. v-show="videoMaxNum>0"
  28. :page-sizes="[4]"
  29. :total="videoMaxNum"
  30. :page.sync="videoPage"
  31. :limit.sync="videoPageSize"
  32. @pagination="videoPageNumButton"
  33. />
  34. <div class="map-max-box">
  35. <div class="map-left-box">
  36. <!--<div class="max-title-box">-->
  37. <!--<p>{{minTitle}}</p>-->
  38. <!--<p>疏散路径:</p>-->
  39. <!--<el-select v-model="value" placeholder="请选择" @change="lineEvacuate">-->
  40. <!--<el-option-->
  41. <!--v-for="item in routeList"-->
  42. <!--:key="item.id"-->
  43. <!--:label="item.name"-->
  44. <!--:value="item.id">-->
  45. <!--</el-option>-->
  46. <!--</el-select>-->
  47. <!--</div>-->
  48. <div class="map-big-box">
  49. <div class="map-min-box">
  50. <div class="map-min-for-box" :class="item.subjectId == subId?'map-min-for-box-color':''"
  51. v-for="(item,index) in fjList" :key="index">
  52. {{item.room}}
  53. </div>
  54. <img class="map-min-img" src="@/assets/ZDimages/icon_sjt.gif" v-show="lightList[0].type">
  55. <img class="map-min-img" src="@/assets/ZDimages/icon_yjt.gif" v-show="lightList[1].type">
  56. <img class="map-min-img" src="@/assets/ZDimages/icon_zjt.gif" v-show="lightList[2].type">
  57. <img class="map-min-img" src="@/assets/ZDimages/icon_yjt.gif" v-show="lightList[3].type">
  58. <img class="map-min-img" src="@/assets/ZDimages/icon_zjt.gif" v-show="lightList[4].type">
  59. <img class="map-min-img" src="@/assets/ZDimages/icon_yjt.gif" v-show="lightList[5].type">
  60. </div>
  61. </div>
  62. </div>
  63. <div class="map-right-box">
  64. <div class="bottom-max-box">
  65. <div class="select-button-box">
  66. <p class="select-button-title">疏散路径:</p>
  67. <div class="select-button-min-box">
  68. <el-select v-model="value" placeholder="请选择" @change="lineEvacuate" style="flex:1;">
  69. <el-option
  70. v-for="item in routeList"
  71. :key="item.id"
  72. :label="item.name"
  73. :value="item.id">
  74. </el-option>
  75. </el-select>
  76. <p class="inquire-button-one" @click="clickClosure">{{evacuationType?'执行疏散':'结束疏散'}}</p>
  77. </div>
  78. </div>
  79. <div class="select-button-box">
  80. <p class="select-button-title">疏散喇叭:</p>
  81. <div class="top-for-max-box">
  82. <div class="top-for-min-box" @click="trumpetClick(item)"
  83. :class="item.type?'for-color-a':'for-color-b'"
  84. v-for="(item,index) in trumpetList" :key="index">
  85. {{item.name}}
  86. <img v-if="item.type" src="@/assets/ZDimages/icon_30.png">
  87. </div>
  88. </div>
  89. </div>
  90. <div class="scrollbar-list scrollbar-box">
  91. <div class="for-scrollbar-box" v-for="(item,index) in informationList" :key="index">
  92. <p>{{item.date}}</p>
  93. <p>{{item.text}}</p>
  94. </div>
  95. <p v-if="!informationList[0]" style="line-height:40px;text-align: center;color:#999;font-size:14px;">暂无喇叭数据</p>
  96. </div>
  97. <div class="bottom-input-text-box">
  98. <el-input
  99. type="textarea"
  100. :rows="4"
  101. resize='none'
  102. maxLength="100"
  103. placeholder="请输入播报内容"
  104. v-model="textarea">
  105. </el-input>
  106. </div>
  107. <p class="bottom-button-p" @click="textParseUrlIps">发送</p>
  108. </div>
  109. </div>
  110. </div>
  111. </div>
  112. </template>
  113. <script>
  114. import { lablayout, lineEvacuateTow } from "@/api/laboratory/emergencyEvacuation";
  115. import { getListStatus } from '@/api/bigData/index.js'
  116. import flvjs from 'flv.js'
  117. import { evacuate, closure, lineEvacuate, IntelligentGuidance,getRedis,getDeviceList,textParseUrlIps,getCameraByFloor,startUrl } from '@/api/executeThePlan.js'
  118. import mqtt from 'mqtt'
  119. import { subjectInfo } from "@/api/laboratory/subject";
  120. export default {
  121. name: 'emergencyEvacuationBig',
  122. props:{
  123. routerType:{},
  124. },
  125. data() {
  126. return {
  127. mtopic:"lab/exit/line",
  128. client:{},
  129. buttonType:false,
  130. subId:"",
  131. type:"",
  132. value:"0",
  133. title:"",
  134. minTitle:"环境学院-祈福楼 环境与气象研究所",
  135. //疏散方向数据
  136. routeList:[
  137. {
  138. id:"1",
  139. name:"向左疏散",
  140. },
  141. {
  142. id:"2",
  143. name:"向右疏散",
  144. },
  145. {
  146. id:"0",
  147. name:"两侧疏散",
  148. },
  149. ],
  150. //监控列表
  151. videoNewList:[],
  152. videoList:[],
  153. //房间列表
  154. fjList:[],
  155. //灯列表
  156. lightList:[
  157. {
  158. id:"5",
  159. type:false,
  160. },
  161. {
  162. id:"2",
  163. type:false,
  164. },
  165. {
  166. id:"3",
  167. type:false,
  168. },
  169. {
  170. id:"4",
  171. type:false,
  172. },
  173. {
  174. id:"1",
  175. type:false,
  176. },
  177. {
  178. id:"6",
  179. type:false,
  180. },
  181. ],
  182. //喇叭列表
  183. trumpetList:[],
  184. //消息列表
  185. informationList:[],
  186. textarea:"",
  187. evacuationType:false,
  188. //视频数据
  189. videoMaxNum:0,
  190. videoPage:1,
  191. videoPageSize:4,
  192. videoPageList:[],
  193. }
  194. },
  195. created(){
  196. this.getRedis();
  197. //判断入口是否全屏路由地址
  198. if(this.routerType){
  199. //应急疏散页面进入
  200. this.buttonType = true;
  201. }else {
  202. //预案报警进入
  203. this.buttonType = false;
  204. }
  205. this.lablayout();
  206. },
  207. mounted(){
  208. this.subscriptionMQTT();
  209. },
  210. methods:{
  211. //获取实验室的疏散数据
  212. lineEvacuateTow(id,type){
  213. lineEvacuateTow(id,type).then(response => {
  214. this.initialization(response.data);
  215. });
  216. },
  217. getCameraByFloor(){
  218. getCameraByFloor({floorId:5}).then(response => {
  219. let videoList = response.data;
  220. subjectInfo(this.subId,0).then(res => {
  221. if (res.data.labHardwareVOList){
  222. for(let i=0;i<res.data.labHardwareVOList.length;i++){
  223. if(res.data.labHardwareVOList[i].hardwareTypeEnum.enumName == 'VIDEO_MONITOR'){
  224. videoList.unshift(res.data.labHardwareVOList[i].hardwareNUM);
  225. }
  226. }
  227. }
  228. videoList = [...new Set(videoList)]
  229. if (videoList[0]){
  230. this.startUrl(videoList);
  231. }
  232. })
  233. });
  234. },
  235. //文字转语音播放
  236. textParseUrlIps(){
  237. let self = this;
  238. let num = 0;
  239. let newList = [];
  240. for(let i=0;i<self.trumpetList.length;i++){
  241. if(self.trumpetList[i].type){
  242. let obj = {
  243. sn:self.trumpetList[i].deviceSn,
  244. port:self.trumpetList[i].port,
  245. deviceIp:self.trumpetList[i].deviceIp,
  246. type:"",
  247. name:"",
  248. speed:"",
  249. params:{
  250. tid:"",
  251. vol:self.trumpetList[i].deviceVol,
  252. urls:[]
  253. }
  254. };
  255. newList.push(obj);
  256. num++
  257. }
  258. }
  259. if(num == 0){
  260. this.msgError("请选择要播放的喇叭")
  261. return
  262. }
  263. if(!this.textarea){
  264. this.msgError("请输入要播放的内容")
  265. return
  266. }
  267. textParseUrlIps(newList,this.textarea).then(response => {
  268. this.textarea = "";
  269. let newObj = {
  270. date:response.data.date,
  271. text:response.data.text,
  272. };
  273. this.informationList.push(newObj);
  274. this.msgSuccess("操作成功")
  275. });
  276. },
  277. //喇叭选中
  278. trumpetClick(item){
  279. item.type = !item.type;
  280. if(item.type==true){
  281. this.trumpetList.forEach(function(item2) {
  282. if(item2.deviceSn==item.deviceSn){
  283. item2.type=true
  284. }else{
  285. item2.type=false
  286. }
  287. })
  288. }
  289. },
  290. //获取喇叭列表
  291. getDeviceList(){
  292. let obj ={
  293. subId:this.subId,
  294. floorId:5,
  295. page:1,
  296. pageSize:100,
  297. };
  298. getDeviceList(obj).then(response => {
  299. for(let i=0;i<response.data.length;i++){
  300. response.data[i].type = false;
  301. }
  302. this.$set(this,'trumpetList',response.data)
  303. });
  304. },
  305. //MQTT订阅
  306. subscriptionMQTT(){
  307. let self = this;
  308. this.client = mqtt.connect(localStorage.getItem('mqttUrl'), {
  309. username: localStorage.getItem('mqttUser'),
  310. password: localStorage.getItem('mqttPassword')
  311. });
  312. this.client.on("connect", e =>{
  313. this.client.subscribe(this.mtopic, (err) => {
  314. if (!err) {
  315. }
  316. });
  317. });
  318. this.client.on("message", (topic, message) => {
  319. if (message){
  320. let data = JSON.parse(message)
  321. if(topic == this.mtopic){
  322. //应急疏散数据变更
  323. if(data.data.EXIT_LINE_MESSAGE){
  324. this.evacuate();
  325. self.evacuationType = false;
  326. }else{
  327. if(self.evacuationType){
  328. self.msgSuccess("应急疏散已结束");
  329. }
  330. self.evacuationType = true;
  331. // self.$router.push({
  332. // path: "/emergencyManagement/evacuation/performEvacuation"
  333. // })
  334. // this.$parent.backPage();
  335. }
  336. }
  337. }
  338. });
  339. },
  340. //获取当前疏散状态
  341. getRedis(){
  342. let self = this;
  343. getRedis().then( data => {
  344. if(data.data){
  345. this.subId = data.data.subId;
  346. this.title = data.data.subName;
  347. this.evacuationType = false;
  348. this.evacuate();
  349. this.getDeviceList();
  350. }else{
  351. if(localStorage.getItem('evacuationSubId')){
  352. this.subId = localStorage.getItem('evacuationSubId');
  353. this.title = localStorage.getItem('evacuationTitel');
  354. localStorage.removeItem('evacuationSubId')
  355. localStorage.removeItem('evacuationTitel')
  356. }else{
  357. this.subId = this.$route.query.subId;
  358. this.title = this.$route.query.text;
  359. }
  360. this.evacuationType = true;
  361. this.lineEvacuateTow(this.subId,0);
  362. this.getDeviceList();
  363. }
  364. });
  365. },
  366. //获取实验室数据
  367. lablayout(){
  368. let self = this;
  369. let id = 137;
  370. lablayout(id).then(response => {
  371. for(let i=0;i<response.data.length;i++){
  372. if(response.data[i].id == 5){
  373. self.fjList = response.data[i].list;
  374. }
  375. }
  376. });
  377. },
  378. //执行预案
  379. evacuate(){
  380. let self = this;
  381. evacuate(this.subId).then( data => {
  382. if(data.code == 200){
  383. if(data.data){
  384. this.initialization(data.data);
  385. }
  386. }
  387. });
  388. },
  389. //结束预案
  390. clickClosure(){
  391. let self = this;
  392. if (this.evacuationType){
  393. this.$confirm('是否确认执行疏散?', "警告", {
  394. confirmButtonText: "确定",
  395. cancelButtonText: "取消",
  396. type: "warning"
  397. }).then(function() {
  398. self.lineEvacuate(0);
  399. }).then(() => {
  400. }).catch(() => {});
  401. } else {
  402. this.$confirm('是否确认结束疏散?', "警告", {
  403. confirmButtonText: "确定",
  404. cancelButtonText: "取消",
  405. type: "warning"
  406. }).then(function() {
  407. self.closure();
  408. }).then(() => {
  409. }).catch(() => {});
  410. }
  411. },
  412. closure(){
  413. let self = this;
  414. closure(this.subId).then( data => {
  415. if(data.code == 200){
  416. this.evacuationType = true;
  417. self.msgSuccess("操作成功")
  418. // self.$router.push({
  419. // path: "/emergencyManagement/evacuation/performEvacuation"
  420. // })
  421. // this.$parent.backPage();
  422. }
  423. });
  424. },
  425. //切换线路
  426. lineEvacuate(e){
  427. let self = this;
  428. lineEvacuate(this.subId,e).then( data => {
  429. if(data.code == 200){
  430. self.msgSuccess("操作成功")
  431. if(data.data){
  432. this.initialization(data.data);
  433. this.evacuationType = false;
  434. }
  435. }
  436. });
  437. },
  438. //灯初始化
  439. initialization(list){
  440. let self = this;
  441. let newList = [
  442. {
  443. id:"5",
  444. type:false,
  445. },
  446. {
  447. id:"2",
  448. type:false,
  449. },
  450. {
  451. id:"3",
  452. type:false,
  453. },
  454. {
  455. id:"4",
  456. type:false,
  457. },
  458. {
  459. id:"1",
  460. type:false,
  461. },
  462. {
  463. id:"6",
  464. type:false,
  465. },
  466. ];
  467. for(let i=0;i<list.length;i++){
  468. for(let o=0;o<newList.length;o++){
  469. if(list[i].lightId == newList[o].id){
  470. newList[o].type = true;
  471. }
  472. }
  473. }
  474. this.lightList = newList;
  475. this.getCameraByFloor();
  476. },
  477. goAllBig(){
  478. this.$router.push({
  479. path: "/emergencyEvacuationBig",
  480. query: {
  481. subId: this.subId,
  482. text:this.title,
  483. type:"2",
  484. }
  485. })
  486. },
  487. //返回方法
  488. clickBack(){
  489. let self = this;
  490. self.$router.push({
  491. path: "/emergencyManagement/evacuation/performEvacuation",
  492. query: {
  493. subId: self.subId,
  494. text:self.title,
  495. }
  496. })
  497. },
  498. //返回按钮
  499. backButton(){
  500. let self = this;
  501. for(let i=0;i<self.videoNewList.length;i++){
  502. self.videoNewList[i].flvPlayer.pause();
  503. self.videoNewList[i].flvPlayer.unload();
  504. self.videoNewList[i].flvPlayer.detachMediaElement();
  505. self.videoNewList[i].flvPlayer.destroy();
  506. self.videoNewList[i].flvPlayer = null
  507. }
  508. this.$set(this,'videoNewList',[]);
  509. this.$parent.goPage(1);
  510. },
  511. //视屏全屏方法
  512. videoFullScreen(index){
  513. this.$refs.videoRef[index].webkitRequestFullScreen();
  514. },
  515. //获取摄像头地址
  516. async startUrl(rows){
  517. let self = this;
  518. let list = "";
  519. for(let i=0;i<rows.length;i++){
  520. list = list + rows[i]+","
  521. }
  522. let obj = {
  523. page:"1",
  524. count:"100",
  525. deviceIds:list,
  526. };
  527. let urlText = window.location.href;
  528. if(urlText.indexOf(localStorage.getItem('ipIdentify')) != -1){
  529. const { data } = await startUrl(obj);
  530. if(data){
  531. self.videoPageList = [];
  532. for(let i=0;i<data.length;i++){
  533. let obj = {
  534. divId:'divId'+i,
  535. hasAudio:false,
  536. height:false,
  537. videoError:"",
  538. videoUrl:data[i].result.body.data.ws_flv,
  539. }
  540. self.videoPageList.push(obj)
  541. }
  542. this.videoMaxNum = this.videoPageList.length
  543. this.videoPageNumButton({page:1,limit:4});
  544. }
  545. } else {
  546. const { data } = await startUrl(obj);
  547. if(data){
  548. self.videoPageList = [];
  549. for(let i=0;i<data.length;i++){
  550. let text = localStorage.getItem('cameraUrl');
  551. let url = data[i].result.body.data.ws_flv;
  552. url = url.split("rtp/");
  553. let newUrl = text+'rtp/'+url[1];
  554. let obj = {
  555. divId:'divId'+i,
  556. hasAudio:false,
  557. height:false,
  558. videoError:"",
  559. videoUrl:newUrl,
  560. }
  561. self.videoPageList.push(obj)
  562. }
  563. this.videoMaxNum = this.videoPageList.length
  564. this.videoPageNumButton({page:1,limit:4});
  565. }
  566. }
  567. },
  568. //视频翻页处理
  569. videoPageNumButton(val){
  570. this.loading = true;
  571. let self = this;
  572. //清除已有播放流
  573. if(self.videoNewList[0]){
  574. for(let i=0;i<self.videoNewList.length;i++){
  575. self.videoNewList[i].flvPlayer.pause();
  576. self.videoNewList[i].flvPlayer.unload();
  577. self.videoNewList[i].flvPlayer.detachMediaElement();
  578. self.videoNewList[i].flvPlayer.destroy();
  579. self.videoNewList[i].flvPlayer = null;
  580. }
  581. self.videoNewList = [];
  582. }
  583. //计算新数据
  584. let num = 0;
  585. let numMax = val.page * val.limit;
  586. if(val.page!=0){
  587. num = ( val.page - 1 ) * val.limit
  588. }
  589. if(numMax>self.videoPageList.length){
  590. numMax = self.videoPageList.length;
  591. }
  592. let list = [];
  593. for(let i=num;i<numMax;i++){
  594. list.push(self.videoPageList[i]);
  595. }
  596. this.$set(this,'videoList',list);
  597. setTimeout(function(){
  598. self.videoPlay();
  599. },500);
  600. },
  601. videoPlay(){
  602. let self = this;
  603. this.loading = false;
  604. for(let i=0;i<self.videoList.length;i++){
  605. let obj = {
  606. player :{},
  607. flvPlayer:{}
  608. };
  609. obj.player = document.getElementById(self.videoList[i].divId);
  610. obj.flvPlayer = flvjs.createPlayer(
  611. {
  612. // isLive: true, //=> 是否为直播流
  613. // hasAudio: false, //=> 是否开启声音
  614. type: 'flv', //媒体类型 flv 或 mp4
  615. url: self.videoList[i].videoUrl //视频流地址
  616. },
  617. {
  618. enableStashBuffer: true,//启用 IO 存储缓冲区。 如果您需要实时流播放(最小延迟),请设置为 false,但如果存在网络抖动,则可能会停止。
  619. stashInitialSize: 128,//IO 存储缓冲区初始大小。 默认值为 384KB。 指示合适的大小可以改善视频加载/搜索时间。
  620. isLive: true,//是否是直播
  621. lazyLoadRecoverDuration: 30,//指示以秒为单位的lazyLoad 恢复时间边界。
  622. autoCleanupSourceBuffer: true,//进行自动清理
  623. autoCleanupMaxBackwardDuration: 3 * 60,//3 * 60 当向后缓冲持续时间超过这个值(以秒为单位)时,对 SourceBuffer 进行自动清理
  624. autoCleanupMinBackwardDuration: 2 * 60,//2 * 60 指示在执行自动清理时为后向缓冲区保留的持续时间(以秒为单位)。
  625. }
  626. );
  627. self.videoNewList.push(obj);
  628. // }
  629. }
  630. for(let i=0;i<self.videoNewList.length;i++){
  631. self.videoNewList[i].flvPlayer.attachMediaElement(self.videoNewList[i].player);
  632. self.videoNewList[i].flvPlayer.load(); //加载
  633. self.videoNewList[i].flvPlayer.play(); //加载
  634. }
  635. },
  636. videoFunction(){
  637. let self = this;
  638. // self.videoList = [];
  639. for(let i=0;i<self.checkedSubject.videoData.length;i++){
  640. let obj = {
  641. player :{},
  642. flvPlayer:{}
  643. };
  644. obj.player = document.getElementById(self.checkedSubject.videoData[i].divId);
  645. // if (flvjs.isSupported()) {
  646. obj.flvPlayer = flvjs.createPlayer(
  647. {
  648. // isLive: true, //=> 是否为直播流
  649. // hasAudio: false, //=> 是否开启声音
  650. type: self.checkedSubject.videoData[i].videoType, //媒体类型 flv 或 mp4
  651. url: self.checkedSubject.videoData[i].url //视频流地址
  652. },
  653. {
  654. enableStashBuffer: true,//启用 IO 存储缓冲区。 如果您需要实时流播放(最小延迟),请设置为 false,但如果存在网络抖动,则可能会停止。
  655. stashInitialSize: 128,//IO 存储缓冲区初始大小。 默认值为 384KB。 指示合适的大小可以改善视频加载/搜索时间。
  656. isLive: true,//是否是直播
  657. lazyLoadRecoverDuration: 30,//指示以秒为单位的lazyLoad 恢复时间边界。
  658. autoCleanupSourceBuffer: true,//进行自动清理
  659. autoCleanupMaxBackwardDuration: 3 * 60,//3 * 60 当向后缓冲持续时间超过这个值(以秒为单位)时,对 SourceBuffer 进行自动清理
  660. autoCleanupMinBackwardDuration: 2 * 60,//2 * 60 指示在执行自动清理时为后向缓冲区保留的持续时间(以秒为单位)。
  661. }
  662. );
  663. self.videoList.push(obj);
  664. // }
  665. }
  666. for(let i=0;i<self.videoList.length;i++){
  667. self.videoList[i].flvPlayer.attachMediaElement(self.videoList[i].player);
  668. self.videoList[i].flvPlayer.load(); //加载
  669. self.videoList[i].flvPlayer.play(); //加载
  670. }
  671. },
  672. //取消订阅关闭MQTT连接
  673. offMQTT(){
  674. this.client.unsubscribe(this.mtopic, error => {
  675. if (error) {
  676. }
  677. })
  678. this.client.end();
  679. this.client = {};
  680. },
  681. },
  682. beforeDestroy() {
  683. //清除定时器
  684. let self = this;
  685. self.offMQTT();
  686. },
  687. }
  688. </script>
  689. <style scoped lang="scss">
  690. .emergencyEvacuationBig{
  691. height:100%;
  692. width:100%;
  693. display: flex !important;
  694. flex-direction: column;
  695. box-shadow: 0 0 8px 2px rgba(0, 0, 0, 0.1);
  696. overflow-y:scroll;
  697. p{
  698. margin:0;
  699. }
  700. .top-max-title-box{
  701. display: flex;
  702. padding:0 30px;
  703. p{
  704. margin:27px 0;
  705. }
  706. p:nth-child(1){
  707. font-size:18px;
  708. font-weight:700;
  709. color:#0045AF;
  710. line-height:40px;
  711. span{
  712. color:#999;
  713. font-size:14px;
  714. margin-left:20px;
  715. }
  716. }
  717. p:nth-child(2){
  718. margin-left:70px;
  719. width:120px;
  720. }
  721. p:nth-child(3){
  722. flex:1;
  723. }
  724. p:nth-child(4){
  725. width:120px;
  726. }
  727. }
  728. .video-max-box{
  729. .video-for-box{
  730. display: inline-block;
  731. width:348px;
  732. /*height:260px;*/
  733. height:196px;
  734. position: relative;
  735. margin:0 0 30px 30px;
  736. .video-for-title-box{
  737. position: absolute;
  738. top:0;
  739. left:0;
  740. width:348px;
  741. height:40px;
  742. background: rgba(0,0,0,0.2);
  743. display: flex;
  744. z-index:10;
  745. .video-for-title{
  746. flex:1;
  747. color:#fff;
  748. font-size:14px;
  749. line-height:40px;
  750. display: block;
  751. overflow:hidden;
  752. text-overflow:ellipsis;
  753. white-space:nowrap;
  754. padding:0 17px;
  755. }
  756. .video-for-button{
  757. width:40px;
  758. height:40px;
  759. cursor: pointer;
  760. img{
  761. height:20px;
  762. width:20px;
  763. margin:10px;
  764. }
  765. }
  766. }
  767. .video-box{
  768. /*height:260px;*/
  769. height:196px;
  770. width:348px;
  771. }
  772. }
  773. }
  774. .pagination-container{
  775. margin:0;
  776. }
  777. .map-max-box{
  778. flex:1;
  779. margin-left:18px;
  780. display: flex;
  781. .map-left-box{
  782. width:1143px;
  783. .max-title-box{
  784. display: flex;
  785. margin:0 0 25px;
  786. p:nth-child(1){
  787. line-height:40px;
  788. font-size:18px;
  789. font-weight:700;
  790. color:#094CB2;
  791. }
  792. p:nth-child(2){
  793. flex:1;
  794. line-height:40px;
  795. text-align: right;
  796. font-size:16px;
  797. }
  798. }
  799. .map-big-box{
  800. width:1143px;
  801. height:610px;
  802. border:1px solid #E0E0E0;
  803. margin-bottom:20px;
  804. overflow: hidden;
  805. .map-min-box{
  806. height:505px;
  807. width:1133px;
  808. margin:50px auto;
  809. background: url("../assets/ZDimages/icon_bj_syspmtcy_jinan.png");
  810. position: relative;
  811. .map-min-for-box{
  812. overflow: hidden;
  813. display: inline-block;
  814. line-height:150px;
  815. text-align: center;
  816. }
  817. .map-min-for-box-color{
  818. background: rgba(0,189,255,0.3);
  819. }
  820. .map-min-for-box:nth-child(1){
  821. margin:4px 143px 0 0;
  822. width:162px;
  823. height:162px;
  824. }
  825. .map-min-for-box:nth-child(2){
  826. margin:4px 0 0 0;
  827. width:101px;
  828. height:162px;
  829. }
  830. .map-min-for-box:nth-child(3){
  831. margin:4px 0 0 0;
  832. width:101px;
  833. height:162px;
  834. }
  835. .map-min-for-box:nth-child(4){
  836. margin:4px 0 0 0;
  837. width:100px;
  838. height:162px;
  839. }
  840. .map-min-for-box:nth-child(5){
  841. margin:4px 0 0 0;
  842. width:100px;
  843. height:162px;
  844. }
  845. .map-min-for-box:nth-child(6){
  846. margin:4px 0 0 0;
  847. width:100px;
  848. height:162px;
  849. }
  850. .map-min-for-box:nth-child(7){
  851. margin:4px 0 0 0;
  852. width:100px;
  853. height:162px;
  854. }
  855. .map-min-for-box:nth-child(8){
  856. margin:4px 60px 0 0;
  857. width:100px;
  858. height:162px;
  859. }
  860. .map-min-for-box:nth-child(9){
  861. margin: 90px 0 0 0;
  862. width: 92px;
  863. height: 240px;
  864. line-height:230px;
  865. }
  866. .map-min-for-box:nth-child(10){
  867. margin: 90px 0 0 0;
  868. width: 107px;
  869. height: 240px;
  870. line-height:230px;
  871. }
  872. .map-min-for-box:nth-child(11){
  873. margin: 90px 0 0 0;
  874. width: 107px;
  875. height: 240px;
  876. line-height:230px;
  877. }
  878. .map-min-for-box:nth-child(12){
  879. margin: 90px 0 0 0;
  880. width: 100px;
  881. height: 240px;
  882. line-height:230px;
  883. }
  884. .map-min-for-box:nth-child(13){
  885. margin: 90px 0 0 0;
  886. width: 100px;
  887. height: 240px;
  888. line-height:230px;
  889. }
  890. .map-min-for-box:nth-child(14){
  891. margin: 90px 0 0 0;
  892. width: 100px;
  893. height: 240px;
  894. line-height:230px;
  895. }
  896. .map-min-for-box:nth-child(15){
  897. margin: 90px 0 0 0;
  898. width: 100px;
  899. height: 240px;
  900. line-height:230px;
  901. }
  902. .map-min-for-box:nth-child(16){
  903. margin: 90px 0 0 0;
  904. width: 100px;
  905. height: 240px;
  906. line-height:230px;
  907. }
  908. .map-min-for-box:nth-child(17){
  909. margin: 90px 0 0 0;
  910. width: 100px;
  911. height: 240px;
  912. line-height:230px;
  913. }
  914. .map-min-for-box:nth-child(18){
  915. margin: 90px 60px 0 0;
  916. width: 100px;
  917. height: 240px;
  918. line-height:230px;
  919. }
  920. .map-min-img{
  921. position: absolute;
  922. width:40px;
  923. height:28px;
  924. }
  925. .map-min-img:nth-child(19){
  926. top: 128px;
  927. left: 175px;
  928. }
  929. .map-min-img:nth-child(20){
  930. top: 194px;
  931. left: 231px;
  932. }
  933. .map-min-img:nth-child(21){
  934. top: 194px;
  935. left: 540px;
  936. }
  937. .map-min-img:nth-child(22){
  938. top: 194px;
  939. left: 630px;
  940. }
  941. .map-min-img:nth-child(23){
  942. top: 194px;
  943. left: 940px;
  944. }
  945. .map-min-img:nth-child(24){
  946. top: 194px;
  947. left: 1030px;
  948. }
  949. }
  950. }
  951. }
  952. .map-right-box{
  953. flex:1;
  954. display: flex;
  955. flex-direction: column;
  956. height:610px;
  957. overflow: hidden;
  958. margin:0 10px 20px;
  959. .top-for-max-box{
  960. margin-left:15px;
  961. .top-for-min-box{
  962. width:110px;
  963. height:40px;
  964. line-height:40px;
  965. font-size:14px;
  966. padding:0 10px;
  967. display: inline-block;
  968. margin:0 13px 18px 0;
  969. border-radius:4px;
  970. cursor: pointer;
  971. position: relative;
  972. overflow: hidden;
  973. img{
  974. width:25px;
  975. height:25px;
  976. position: absolute;
  977. right:0;
  978. bottom:0;
  979. }
  980. }
  981. .for-color-a{
  982. border:1px solid #0183FA;
  983. color:#0183FA;
  984. }
  985. .for-color-b{
  986. border:1px solid #CCCCCC;
  987. color:#CCCCCC;
  988. }
  989. }
  990. .bottom-max-box{
  991. flex:1;
  992. display: flex;
  993. flex-direction: column;
  994. border:1px solid #E0E0E0;
  995. overflow: hidden;
  996. .select-button-box{
  997. font-weight:500;
  998. .select-button-title{
  999. font-size:14px;
  1000. margin-left:15px;
  1001. line-height:40px;
  1002. color:#333;
  1003. }
  1004. .select-button-min-box{
  1005. display: flex;
  1006. margin-left:15px;
  1007. .inquire-button-one{
  1008. margin:0 20px;
  1009. width:100px;
  1010. font-size:14px;
  1011. line-height:40px;
  1012. height:40px;
  1013. }
  1014. }
  1015. }
  1016. .scrollbar-list{
  1017. flex:1;
  1018. .for-scrollbar-box{
  1019. font-size:14px;
  1020. margin:0 15px;
  1021. p:nth-child(1){
  1022. line-height:40px;
  1023. text-align: center;
  1024. color:#999;
  1025. font-weight:500;
  1026. }
  1027. p:nth-child(2){
  1028. color:#666;
  1029. line-height:18px;
  1030. font-weight:500;
  1031. }
  1032. }
  1033. }
  1034. .bottom-input-text-box{
  1035. height:96px;
  1036. margin:20px 20px 0;
  1037. }
  1038. .bottom-button-p{
  1039. background:#0183FA;
  1040. color:#fff;
  1041. font-size:16px;
  1042. text-align: center;
  1043. line-height:40px;
  1044. border-radius:10px;
  1045. margin:20px 40px;
  1046. cursor: pointer;
  1047. }
  1048. }
  1049. }
  1050. }
  1051. }
  1052. </style>