emergencyEvacuationBig.vue 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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. // console.log('response',response);
  269. this.textarea = "";
  270. let newObj = {
  271. date:response.data.date,
  272. text:response.data.text,
  273. };
  274. this.informationList.push(newObj);
  275. this.msgSuccess("操作成功")
  276. });
  277. },
  278. //喇叭选中
  279. trumpetClick(item){
  280. item.type = !item.type;
  281. if(item.type==true){
  282. this.trumpetList.forEach(function(item2) {
  283. if(item2.deviceSn==item.deviceSn){
  284. item2.type=true
  285. }else{
  286. item2.type=false
  287. }
  288. })
  289. }
  290. },
  291. //获取喇叭列表
  292. getDeviceList(){
  293. let obj ={
  294. subId:this.subId,
  295. floorId:5,
  296. page:1,
  297. pageSize:100,
  298. };
  299. getDeviceList(obj).then(response => {
  300. for(let i=0;i<response.data.length;i++){
  301. response.data[i].type = false;
  302. }
  303. this.$set(this,'trumpetList',response.data)
  304. });
  305. },
  306. //MQTT订阅
  307. subscriptionMQTT(){
  308. let self = this;
  309. this.client = mqtt.connect(localStorage.getItem('mqttUrl'), {
  310. username: localStorage.getItem('mqttUser'),
  311. password: localStorage.getItem('mqttPassword')
  312. });
  313. this.client.on("connect", e =>{
  314. console.log("连接成功");
  315. this.client.subscribe(this.mtopic, (err) => {
  316. if (!err) {
  317. console.log("订阅成功:" + this.mtopic);
  318. }
  319. });
  320. });
  321. this.client.on("message", (topic, message) => {
  322. if (message){
  323. let data = JSON.parse(message)
  324. if(topic == this.mtopic){
  325. console.log("应急疏散数据变更",data);
  326. //应急疏散数据变更
  327. if(data.data.EXIT_LINE_MESSAGE){
  328. this.evacuate();
  329. self.evacuationType = false;
  330. }else{
  331. if(self.evacuationType){
  332. self.msgSuccess("应急疏散已结束");
  333. }
  334. self.evacuationType = true;
  335. // self.$router.push({
  336. // path: "/emergencyManagement/evacuation/performEvacuation"
  337. // })
  338. // this.$parent.backPage();
  339. }
  340. }
  341. }
  342. });
  343. },
  344. //获取当前疏散状态
  345. getRedis(){
  346. let self = this;
  347. getRedis().then( data => {
  348. if(data.data){
  349. this.subId = data.data.subId;
  350. this.title = data.data.subName;
  351. this.evacuationType = false;
  352. this.evacuate();
  353. this.getDeviceList();
  354. }else{
  355. if(localStorage.getItem('evacuationSubId')){
  356. this.subId = localStorage.getItem('evacuationSubId');
  357. this.title = localStorage.getItem('evacuationTitel');
  358. localStorage.removeItem('evacuationSubId')
  359. localStorage.removeItem('evacuationTitel')
  360. }else{
  361. this.subId = this.$route.query.subId;
  362. this.title = this.$route.query.text;
  363. }
  364. this.evacuationType = true;
  365. this.lineEvacuateTow(this.subId,0);
  366. this.getDeviceList();
  367. }
  368. });
  369. },
  370. //获取实验室数据
  371. lablayout(){
  372. let self = this;
  373. let id = 137;
  374. lablayout(id).then(response => {
  375. for(let i=0;i<response.data.length;i++){
  376. if(response.data[i].id == 5){
  377. self.fjList = response.data[i].list;
  378. }
  379. }
  380. });
  381. },
  382. //执行预案
  383. evacuate(){
  384. let self = this;
  385. evacuate(this.subId).then( data => {
  386. if(data.code == 200){
  387. if(data.data){
  388. this.initialization(data.data);
  389. }
  390. }
  391. });
  392. },
  393. //结束预案
  394. clickClosure(){
  395. let self = this;
  396. if (this.evacuationType){
  397. this.$confirm('是否确认执行疏散?', "警告", {
  398. confirmButtonText: "确定",
  399. cancelButtonText: "取消",
  400. type: "warning"
  401. }).then(function() {
  402. self.lineEvacuate(0);
  403. }).then(() => {
  404. }).catch(() => {});
  405. } else {
  406. this.$confirm('是否确认结束疏散?', "警告", {
  407. confirmButtonText: "确定",
  408. cancelButtonText: "取消",
  409. type: "warning"
  410. }).then(function() {
  411. self.closure();
  412. }).then(() => {
  413. }).catch(() => {});
  414. }
  415. },
  416. closure(){
  417. let self = this;
  418. closure(this.subId).then( data => {
  419. if(data.code == 200){
  420. this.evacuationType = true;
  421. self.msgSuccess("操作成功")
  422. // self.$router.push({
  423. // path: "/emergencyManagement/evacuation/performEvacuation"
  424. // })
  425. // this.$parent.backPage();
  426. console.log("结束",data)
  427. }
  428. });
  429. },
  430. //切换线路
  431. lineEvacuate(e){
  432. let self = this;
  433. lineEvacuate(this.subId,e).then( data => {
  434. if(data.code == 200){
  435. self.msgSuccess("操作成功")
  436. if(data.data){
  437. this.initialization(data.data);
  438. this.evacuationType = false;
  439. }
  440. }
  441. });
  442. },
  443. //灯初始化
  444. initialization(list){
  445. let self = this;
  446. let newList = [
  447. {
  448. id:"5",
  449. type:false,
  450. },
  451. {
  452. id:"2",
  453. type:false,
  454. },
  455. {
  456. id:"3",
  457. type:false,
  458. },
  459. {
  460. id:"4",
  461. type:false,
  462. },
  463. {
  464. id:"1",
  465. type:false,
  466. },
  467. {
  468. id:"6",
  469. type:false,
  470. },
  471. ];
  472. for(let i=0;i<list.length;i++){
  473. for(let o=0;o<newList.length;o++){
  474. if(list[i].lightId == newList[o].id){
  475. newList[o].type = true;
  476. }
  477. }
  478. }
  479. this.lightList = newList;
  480. this.getCameraByFloor();
  481. },
  482. goAllBig(){
  483. this.$router.push({
  484. path: "/emergencyEvacuationBig",
  485. query: {
  486. subId: this.subId,
  487. text:this.title,
  488. type:"2",
  489. }
  490. })
  491. },
  492. //返回方法
  493. clickBack(){
  494. let self = this;
  495. self.$router.push({
  496. path: "/emergencyManagement/evacuation/performEvacuation",
  497. query: {
  498. subId: self.subId,
  499. text:self.title,
  500. }
  501. })
  502. },
  503. //返回按钮
  504. backButton(){
  505. let self = this;
  506. for(let i=0;i<self.videoNewList.length;i++){
  507. self.videoNewList[i].flvPlayer.pause();
  508. self.videoNewList[i].flvPlayer.unload();
  509. self.videoNewList[i].flvPlayer.detachMediaElement();
  510. self.videoNewList[i].flvPlayer.destroy();
  511. self.videoNewList[i].flvPlayer = null
  512. }
  513. this.$set(this,'videoNewList',[]);
  514. this.$parent.goPage(1);
  515. },
  516. //视屏全屏方法
  517. videoFullScreen(index){
  518. this.$refs.videoRef[index].webkitRequestFullScreen();
  519. },
  520. //获取摄像头地址
  521. async startUrl(rows){
  522. let self = this;
  523. let list = "";
  524. for(let i=0;i<rows.length;i++){
  525. list = list + rows[i]+","
  526. }
  527. let obj = {
  528. page:"1",
  529. count:"100",
  530. deviceIds:list,
  531. };
  532. let urlText = window.location.href;
  533. if(urlText.indexOf(localStorage.getItem('ipIdentify')) != -1){
  534. const { data } = await startUrl(obj);
  535. if(data){
  536. self.videoPageList = [];
  537. for(let i=0;i<data.length;i++){
  538. let obj = {
  539. divId:'divId'+i,
  540. hasAudio:false,
  541. height:false,
  542. videoError:"",
  543. videoUrl:data[i].result.body.data.ws_flv,
  544. }
  545. self.videoPageList.push(obj)
  546. }
  547. this.videoMaxNum = this.videoPageList.length
  548. this.videoPageNumButton({page:1,limit:4});
  549. }
  550. } else {
  551. const { data } = await startUrl(obj);
  552. if(data){
  553. self.videoPageList = [];
  554. for(let i=0;i<data.length;i++){
  555. let text = localStorage.getItem('cameraUrl');
  556. let url = data[i].result.body.data.ws_flv;
  557. url = url.split("rtp/");
  558. let newUrl = text+'rtp/'+url[1];
  559. let obj = {
  560. divId:'divId'+i,
  561. hasAudio:false,
  562. height:false,
  563. videoError:"",
  564. videoUrl:newUrl,
  565. }
  566. self.videoPageList.push(obj)
  567. }
  568. this.videoMaxNum = this.videoPageList.length
  569. this.videoPageNumButton({page:1,limit:4});
  570. }
  571. }
  572. },
  573. //视频翻页处理
  574. videoPageNumButton(val){
  575. this.loading = true;
  576. let self = this;
  577. //清除已有播放流
  578. if(self.videoNewList[0]){
  579. for(let i=0;i<self.videoNewList.length;i++){
  580. self.videoNewList[i].flvPlayer.pause();
  581. self.videoNewList[i].flvPlayer.unload();
  582. self.videoNewList[i].flvPlayer.detachMediaElement();
  583. self.videoNewList[i].flvPlayer.destroy();
  584. self.videoNewList[i].flvPlayer = null;
  585. }
  586. self.videoNewList = [];
  587. }
  588. //计算新数据
  589. let num = 0;
  590. let numMax = val.page * val.limit;
  591. if(val.page!=0){
  592. num = ( val.page - 1 ) * val.limit
  593. }
  594. if(numMax>self.videoPageList.length){
  595. numMax = self.videoPageList.length;
  596. }
  597. let list = [];
  598. for(let i=num;i<numMax;i++){
  599. list.push(self.videoPageList[i]);
  600. }
  601. this.$set(this,'videoList',list);
  602. setTimeout(function(){
  603. self.videoPlay();
  604. },500);
  605. },
  606. videoPlay(){
  607. let self = this;
  608. this.loading = false;
  609. for(let i=0;i<self.videoList.length;i++){
  610. let obj = {
  611. player :{},
  612. flvPlayer:{}
  613. };
  614. obj.player = document.getElementById(self.videoList[i].divId);
  615. obj.flvPlayer = flvjs.createPlayer(
  616. {
  617. // isLive: true, //=> 是否为直播流
  618. // hasAudio: false, //=> 是否开启声音
  619. type: 'flv', //媒体类型 flv 或 mp4
  620. url: self.videoList[i].videoUrl //视频流地址
  621. },
  622. {
  623. enableStashBuffer: true,//启用 IO 存储缓冲区。 如果您需要实时流播放(最小延迟),请设置为 false,但如果存在网络抖动,则可能会停止。
  624. stashInitialSize: 128,//IO 存储缓冲区初始大小。 默认值为 384KB。 指示合适的大小可以改善视频加载/搜索时间。
  625. isLive: true,//是否是直播
  626. lazyLoadRecoverDuration: 30,//指示以秒为单位的lazyLoad 恢复时间边界。
  627. autoCleanupSourceBuffer: true,//进行自动清理
  628. autoCleanupMaxBackwardDuration: 3 * 60,//3 * 60 当向后缓冲持续时间超过这个值(以秒为单位)时,对 SourceBuffer 进行自动清理
  629. autoCleanupMinBackwardDuration: 2 * 60,//2 * 60 指示在执行自动清理时为后向缓冲区保留的持续时间(以秒为单位)。
  630. }
  631. );
  632. self.videoNewList.push(obj);
  633. // }
  634. console.log("i",i)
  635. }
  636. for(let i=0;i<self.videoNewList.length;i++){
  637. self.videoNewList[i].flvPlayer.attachMediaElement(self.videoNewList[i].player);
  638. self.videoNewList[i].flvPlayer.load(); //加载
  639. self.videoNewList[i].flvPlayer.play(); //加载
  640. }
  641. },
  642. videoFunction(){
  643. let self = this;
  644. // self.videoList = [];
  645. for(let i=0;i<self.checkedSubject.videoData.length;i++){
  646. let obj = {
  647. player :{},
  648. flvPlayer:{}
  649. };
  650. obj.player = document.getElementById(self.checkedSubject.videoData[i].divId);
  651. // if (flvjs.isSupported()) {
  652. obj.flvPlayer = flvjs.createPlayer(
  653. {
  654. // isLive: true, //=> 是否为直播流
  655. // hasAudio: false, //=> 是否开启声音
  656. type: self.checkedSubject.videoData[i].videoType, //媒体类型 flv 或 mp4
  657. url: self.checkedSubject.videoData[i].url //视频流地址
  658. },
  659. {
  660. enableStashBuffer: true,//启用 IO 存储缓冲区。 如果您需要实时流播放(最小延迟),请设置为 false,但如果存在网络抖动,则可能会停止。
  661. stashInitialSize: 128,//IO 存储缓冲区初始大小。 默认值为 384KB。 指示合适的大小可以改善视频加载/搜索时间。
  662. isLive: true,//是否是直播
  663. lazyLoadRecoverDuration: 30,//指示以秒为单位的lazyLoad 恢复时间边界。
  664. autoCleanupSourceBuffer: true,//进行自动清理
  665. autoCleanupMaxBackwardDuration: 3 * 60,//3 * 60 当向后缓冲持续时间超过这个值(以秒为单位)时,对 SourceBuffer 进行自动清理
  666. autoCleanupMinBackwardDuration: 2 * 60,//2 * 60 指示在执行自动清理时为后向缓冲区保留的持续时间(以秒为单位)。
  667. }
  668. );
  669. self.videoList.push(obj);
  670. // }
  671. console.log("i",i)
  672. }
  673. for(let i=0;i<self.videoList.length;i++){
  674. self.videoList[i].flvPlayer.attachMediaElement(self.videoList[i].player);
  675. self.videoList[i].flvPlayer.load(); //加载
  676. self.videoList[i].flvPlayer.play(); //加载
  677. }
  678. },
  679. //取消订阅关闭MQTT连接
  680. offMQTT(){
  681. this.client.unsubscribe(this.mtopic, error => {
  682. if (error) {
  683. console.log('Unsubscribe error', error)
  684. }
  685. })
  686. this.client.end();
  687. this.client = {};
  688. },
  689. },
  690. beforeDestroy() {
  691. //清除定时器
  692. let self = this;
  693. self.offMQTT();
  694. console.log("beforeDestroy");
  695. },
  696. }
  697. </script>
  698. <style scoped lang="scss">
  699. .emergencyEvacuationBig{
  700. height:100%;
  701. width:100%;
  702. display: flex !important;
  703. flex-direction: column;
  704. box-shadow: 0 0 8px 2px rgba(0, 0, 0, 0.1);
  705. overflow-y:scroll;
  706. p{
  707. margin:0;
  708. }
  709. .top-max-title-box{
  710. display: flex;
  711. padding:0 30px;
  712. p{
  713. margin:27px 0;
  714. }
  715. p:nth-child(1){
  716. font-size:18px;
  717. font-weight:700;
  718. color:#0045AF;
  719. line-height:40px;
  720. span{
  721. color:#999;
  722. font-size:14px;
  723. margin-left:20px;
  724. }
  725. }
  726. p:nth-child(2){
  727. margin-left:70px;
  728. width:120px;
  729. }
  730. p:nth-child(3){
  731. flex:1;
  732. }
  733. p:nth-child(4){
  734. width:120px;
  735. }
  736. }
  737. .video-max-box{
  738. .video-for-box{
  739. display: inline-block;
  740. width:348px;
  741. /*height:260px;*/
  742. height:196px;
  743. position: relative;
  744. margin:0 0 30px 30px;
  745. .video-for-title-box{
  746. position: absolute;
  747. top:0;
  748. left:0;
  749. width:348px;
  750. height:40px;
  751. background: rgba(0,0,0,0.2);
  752. display: flex;
  753. z-index:10;
  754. .video-for-title{
  755. flex:1;
  756. color:#fff;
  757. font-size:14px;
  758. line-height:40px;
  759. display: block;
  760. overflow:hidden;
  761. text-overflow:ellipsis;
  762. white-space:nowrap;
  763. padding:0 17px;
  764. }
  765. .video-for-button{
  766. width:40px;
  767. height:40px;
  768. cursor: pointer;
  769. img{
  770. height:20px;
  771. width:20px;
  772. margin:10px;
  773. }
  774. }
  775. }
  776. .video-box{
  777. /*height:260px;*/
  778. height:196px;
  779. width:348px;
  780. }
  781. }
  782. }
  783. .pagination-container{
  784. margin:0;
  785. }
  786. .map-max-box{
  787. flex:1;
  788. margin-left:18px;
  789. display: flex;
  790. .map-left-box{
  791. width:1143px;
  792. .max-title-box{
  793. display: flex;
  794. margin:0 0 25px;
  795. p:nth-child(1){
  796. line-height:40px;
  797. font-size:18px;
  798. font-weight:700;
  799. color:#094CB2;
  800. }
  801. p:nth-child(2){
  802. flex:1;
  803. line-height:40px;
  804. text-align: right;
  805. font-size:16px;
  806. }
  807. }
  808. .map-big-box{
  809. width:1143px;
  810. height:610px;
  811. border:1px solid #E0E0E0;
  812. margin-bottom:20px;
  813. overflow: hidden;
  814. .map-min-box{
  815. height:505px;
  816. width:1133px;
  817. margin:50px auto;
  818. background: url("../assets/ZDimages/icon_bj_syspmtcy_jinan.png");
  819. position: relative;
  820. .map-min-for-box{
  821. overflow: hidden;
  822. display: inline-block;
  823. line-height:150px;
  824. text-align: center;
  825. }
  826. .map-min-for-box-color{
  827. background: rgba(0,189,255,0.3);
  828. }
  829. .map-min-for-box:nth-child(1){
  830. margin:4px 143px 0 0;
  831. width:162px;
  832. height:162px;
  833. }
  834. .map-min-for-box:nth-child(2){
  835. margin:4px 0 0 0;
  836. width:101px;
  837. height:162px;
  838. }
  839. .map-min-for-box:nth-child(3){
  840. margin:4px 0 0 0;
  841. width:101px;
  842. height:162px;
  843. }
  844. .map-min-for-box:nth-child(4){
  845. margin:4px 0 0 0;
  846. width:100px;
  847. height:162px;
  848. }
  849. .map-min-for-box:nth-child(5){
  850. margin:4px 0 0 0;
  851. width:100px;
  852. height:162px;
  853. }
  854. .map-min-for-box:nth-child(6){
  855. margin:4px 0 0 0;
  856. width:100px;
  857. height:162px;
  858. }
  859. .map-min-for-box:nth-child(7){
  860. margin:4px 0 0 0;
  861. width:100px;
  862. height:162px;
  863. }
  864. .map-min-for-box:nth-child(8){
  865. margin:4px 60px 0 0;
  866. width:100px;
  867. height:162px;
  868. }
  869. .map-min-for-box:nth-child(9){
  870. margin: 90px 0 0 0;
  871. width: 92px;
  872. height: 240px;
  873. line-height:230px;
  874. }
  875. .map-min-for-box:nth-child(10){
  876. margin: 90px 0 0 0;
  877. width: 107px;
  878. height: 240px;
  879. line-height:230px;
  880. }
  881. .map-min-for-box:nth-child(11){
  882. margin: 90px 0 0 0;
  883. width: 107px;
  884. height: 240px;
  885. line-height:230px;
  886. }
  887. .map-min-for-box:nth-child(12){
  888. margin: 90px 0 0 0;
  889. width: 100px;
  890. height: 240px;
  891. line-height:230px;
  892. }
  893. .map-min-for-box:nth-child(13){
  894. margin: 90px 0 0 0;
  895. width: 100px;
  896. height: 240px;
  897. line-height:230px;
  898. }
  899. .map-min-for-box:nth-child(14){
  900. margin: 90px 0 0 0;
  901. width: 100px;
  902. height: 240px;
  903. line-height:230px;
  904. }
  905. .map-min-for-box:nth-child(15){
  906. margin: 90px 0 0 0;
  907. width: 100px;
  908. height: 240px;
  909. line-height:230px;
  910. }
  911. .map-min-for-box:nth-child(16){
  912. margin: 90px 0 0 0;
  913. width: 100px;
  914. height: 240px;
  915. line-height:230px;
  916. }
  917. .map-min-for-box:nth-child(17){
  918. margin: 90px 0 0 0;
  919. width: 100px;
  920. height: 240px;
  921. line-height:230px;
  922. }
  923. .map-min-for-box:nth-child(18){
  924. margin: 90px 60px 0 0;
  925. width: 100px;
  926. height: 240px;
  927. line-height:230px;
  928. }
  929. .map-min-img{
  930. position: absolute;
  931. width:40px;
  932. height:28px;
  933. }
  934. .map-min-img:nth-child(19){
  935. top: 128px;
  936. left: 175px;
  937. }
  938. .map-min-img:nth-child(20){
  939. top: 194px;
  940. left: 231px;
  941. }
  942. .map-min-img:nth-child(21){
  943. top: 194px;
  944. left: 540px;
  945. }
  946. .map-min-img:nth-child(22){
  947. top: 194px;
  948. left: 630px;
  949. }
  950. .map-min-img:nth-child(23){
  951. top: 194px;
  952. left: 940px;
  953. }
  954. .map-min-img:nth-child(24){
  955. top: 194px;
  956. left: 1030px;
  957. }
  958. }
  959. }
  960. }
  961. .map-right-box{
  962. flex:1;
  963. display: flex;
  964. flex-direction: column;
  965. height:610px;
  966. overflow: hidden;
  967. margin:0 10px 20px;
  968. .top-for-max-box{
  969. margin-left:15px;
  970. .top-for-min-box{
  971. width:110px;
  972. height:40px;
  973. line-height:40px;
  974. font-size:14px;
  975. padding:0 10px;
  976. display: inline-block;
  977. margin:0 13px 18px 0;
  978. border-radius:4px;
  979. cursor: pointer;
  980. position: relative;
  981. overflow: hidden;
  982. img{
  983. width:25px;
  984. height:25px;
  985. position: absolute;
  986. right:0;
  987. bottom:0;
  988. }
  989. }
  990. .for-color-a{
  991. border:1px solid #0183FA;
  992. color:#0183FA;
  993. }
  994. .for-color-b{
  995. border:1px solid #CCCCCC;
  996. color:#CCCCCC;
  997. }
  998. }
  999. .bottom-max-box{
  1000. flex:1;
  1001. display: flex;
  1002. flex-direction: column;
  1003. border:1px solid #E0E0E0;
  1004. overflow: hidden;
  1005. .select-button-box{
  1006. font-weight:500;
  1007. .select-button-title{
  1008. font-size:14px;
  1009. margin-left:15px;
  1010. line-height:40px;
  1011. color:#333;
  1012. }
  1013. .select-button-min-box{
  1014. display: flex;
  1015. margin-left:15px;
  1016. .inquire-button-one{
  1017. margin:0 20px;
  1018. width:100px;
  1019. font-size:14px;
  1020. line-height:40px;
  1021. height:40px;
  1022. }
  1023. }
  1024. }
  1025. .scrollbar-list{
  1026. flex:1;
  1027. .for-scrollbar-box{
  1028. font-size:14px;
  1029. margin:0 15px;
  1030. p:nth-child(1){
  1031. line-height:40px;
  1032. text-align: center;
  1033. color:#999;
  1034. font-weight:500;
  1035. }
  1036. p:nth-child(2){
  1037. color:#666;
  1038. line-height:18px;
  1039. font-weight:500;
  1040. }
  1041. }
  1042. }
  1043. .bottom-input-text-box{
  1044. height:96px;
  1045. margin:20px 20px 0;
  1046. }
  1047. .bottom-button-p{
  1048. background:#0183FA;
  1049. color:#fff;
  1050. font-size:16px;
  1051. text-align: center;
  1052. line-height:40px;
  1053. border-radius:10px;
  1054. margin:20px 40px;
  1055. cursor: pointer;
  1056. }
  1057. }
  1058. }
  1059. }
  1060. }
  1061. </style>