index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <template>
  2. <div class="camera-page">
  3. <div class="nav">双预防视频监控平台</div>
  4. <div class="camera-container">
  5. <div class="video-container" v-for="(item,key) in items" :key="key" >
  6. <div class="name">{{ item.deviceName }}</div>
  7. <div :id="`video-`+item.deviceSerial" style="width:100%;height:100%;" v-if="key<18"></div>
  8. <iframe width="210" height="160" allowfullscreen :src="getIframeSrc(item.deviceSerial)" v-if="key>17"></iframe>
  9. <div class="camera-show-handle" @click.stop="showModel(item,2)" v-if="key>17"></div>
  10. <div class="camera-show-handle" @click.stop="showModel(item)" v-if="key<18"></div>
  11. </div>
  12. <!-- flv-video -->
  13. <!-- <div class="video-container" v-for="(item,key) in flvsItem" :key="key" >
  14. <div class="name">{{ item.name }}</div>
  15. <video class="flv-video" :id="item.id" style="width:100%;height:100%;"></video>
  16. </div> -->
  17. <div id="camera-model" v-show="device.model">
  18. <div id="camera-box">
  19. <div class="title">
  20. <a :href="'https://open.ys7.com/ezopen/h5/iframe?url=ezopen://open.ys7.com/'+device.deviceSerial+'/1.rec&autoplay=1&accessToken='+accessToken" target="_blank"><span>{{ device.deviceName }}</span></a>
  21. 【<span style="padding: 10px;color:#000;cursor: pointer;" @click="showRecView">{{devicePlayIsRec?'录像':"查看录像"}}</span> 】
  22. <div class="close" @click="close">X</div>
  23. </div>
  24. <div id="camera-deviceSerial"></div>
  25. </div>
  26. </div>
  27. </div>
  28. </div>
  29. </template>
  30. <script>
  31. import "@/assets/js/ezuikit.js"
  32. import cameras from '@/assets/js/cameras.js';
  33. import axios from 'axios';
  34. export default {
  35. data() {
  36. return {
  37. items:[],
  38. flvsItem:[],
  39. accessToken:undefined,
  40. devicePlayIsRec:false,
  41. device:{
  42. model:false,
  43. deviceName:""
  44. },
  45. timer:null
  46. }
  47. },
  48. mounted() {
  49. this.init()
  50. setTimeout(()=>{
  51. window.location.reload()
  52. },1000*60*30)
  53. },
  54. methods: {
  55. init(){
  56. axios({
  57. url:'https://open.ys7.com/api/lapp/token/get',
  58. method:"POST",
  59. params:{
  60. appKey:"edbf9171037f4908abdaa5c8215c0b06",
  61. appSecret:"3c271fe7e2d0c13a03b2acc297ff146f"
  62. }
  63. }).then((res)=>{
  64. this.accessToken=res.data.data.accessToken
  65. this.getData()
  66. // this.getDevicelist()
  67. })
  68. },
  69. showModel(item,type){
  70. if(type!==2){
  71. var destroyPromise = item.player.destroy();
  72. destroyPromise.then((data) => {
  73. console.log("销毁-promise 获取 数据", data)
  74. })
  75. event.stopPropagation()
  76. }
  77. let device={
  78. ...item,
  79. model:true,
  80. id:"camera-deviceSerial",
  81. width:900,
  82. height:700
  83. }
  84. this.device=device
  85. this.render(device)
  86. },
  87. close(){
  88. this.device.player.destroy()
  89. this.device.player.stop()
  90. this.device={}
  91. this.devicePlayIsRec=false;
  92. document.getElementById('camera-deviceSerial').innerHTML=""
  93. },
  94. changePlayUrl(){
  95. let type=this.devicePlayIsRec?'live':'rec'
  96. this.device.player.changePlayUrl({
  97. url: `ezopen://open.ys7.com/${this.device.deviceSerial}/1.${type}`,
  98. }).then(()=>{
  99. this.devicePlayIsRec=!this.devicePlayIsRec
  100. })
  101. },
  102. showRecView(){
  103. if(this.devicePlayIsRec)return
  104. this.device.player.changePlayUrl({
  105. url: `ezopen://open.ys7.com/${this.device.deviceSerial}/1.rec`,
  106. }).then(()=>{
  107. this.devicePlayIsRec=true
  108. })
  109. },
  110. async getDevicelist(){
  111. var devicelist=[]
  112. const pageSize=20//最大50
  113. const res=await axios({
  114. url:'https://open.ys7.com/api/lapp/device/list',
  115. method:"POST",
  116. params:{
  117. accessToken:this.accessToken,
  118. pageSize
  119. }
  120. })
  121. devicelist=devicelist.concat(res.data.data)
  122. let total=res.data.page.total-pageSize
  123. for(let i=0;i<total/pageSize;i++){
  124. let result= await axios({
  125. url:'https://open.ys7.com/api/lapp/device/list',
  126. method:"POST",
  127. params:{
  128. accessToken:this.accessToken,
  129. pageStart:i+1,
  130. pageSize
  131. }
  132. })
  133. devicelist=devicelist.concat(result.data.data)
  134. }
  135. let online=devicelist.filter((item)=>item.status===1)
  136. let offline=devicelist.filter((item)=>item.status===0)
  137. let items=online.concat(offline)
  138. this.items=items
  139. for(let i=0;i<20;i++){
  140. await this.sleep(300)
  141. this.$nextTick(()=>{
  142. delete items[i].id
  143. this.render(items[i],function(item){
  144. if(i<21){
  145. setTimeout(()=>{
  146. item.player.capturePicture('default',function(data){
  147. item.file=data
  148. })
  149. },1500)
  150. }
  151. })
  152. })
  153. }
  154. },
  155. // 固定数据渲染处理 根据老板需求相同名字的放在一起 等一系列特殊需求
  156. async getData(){
  157. let items=[]
  158. for(let i=0;i<cameras.length;i++){
  159. items.push({
  160. ...cameras[i]
  161. })
  162. }
  163. this.items=items
  164. for(let i=0;i<18;i++){
  165. await this.sleep(500)
  166. this.$nextTick(()=>{
  167. this.render(items[i],function(item){
  168. setTimeout(()=>{
  169. item.player.capturePicture('default',function(data){
  170. item.file=data
  171. })
  172. },3000)
  173. })
  174. })
  175. }
  176. },
  177. getIframeSrc(deviceSerial){
  178. return `https://open.ys7.com/ezopen/h5/iframe?url=ezopen://open.ys7.com/${deviceSerial}/1.live&autoplay=1&accessToken=${this.accessToken}`
  179. },
  180. sleep(time=1000){
  181. return new Promise((resolve)=>{
  182. setTimeout(resolve,time)
  183. })
  184. },
  185. render(item={},callback){
  186. let accessToken=this.accessToken;
  187. let type=item.type==='rec'?'rec':'live'
  188. item.player = new EZUIKit.EZUIKitPlayer({
  189. id: item.id||`video-${item.deviceSerial}`,
  190. // autoplay: false,
  191. url: `ezopen://open.ys7.com/${item.deviceSerial}/1.${type}`,
  192. accessToken: accessToken,
  193. plugin: ['talk'],
  194. width: item.width||210,
  195. height: item.height||160,
  196. audio:0,
  197. // useHardDev: true, //开启高性能模式
  198. themeData:{
  199. "autoFocus": 5,
  200. "poster":item.deviceCover||"https://resource.eziot.com/group1/M00/00/89/CtwQEmLl8r-AZU7wAAETKlvgerU237.png",
  201. "header": {
  202. "color": "#1890ff",
  203. "activeColor": "#FFFFFF",
  204. "backgroundColor": "#000000",
  205. "btnList": []
  206. },
  207. "footer": {
  208. "color": "#FFFFFF",
  209. "activeColor": "#1890FF",
  210. "backgroundColor": "#00000021",
  211. "btnList": [
  212. {
  213. "iconId": "play",
  214. "part": "left",
  215. "defaultActive": 1,
  216. "memo": "播放",
  217. "isrender": 0
  218. },
  219. {
  220. "iconId": "sound",
  221. "part": "left",
  222. "defaultActive": 0,
  223. "memo": "声音按钮",
  224. "isrender": 1
  225. },
  226. {
  227. "iconId": "pantile",
  228. "part": "left",
  229. "defaultActive": 1,
  230. "memo": "云台控制按钮",
  231. "isrender": 1
  232. },
  233. {
  234. "iconId": "talk",
  235. "part": "left",
  236. "defaultActive": 0,
  237. "memo": "对讲按钮",
  238. "isrender": 1
  239. },
  240. {
  241. "iconId": "expend",
  242. "part": "right",
  243. "defaultActive": 0,
  244. "memo": "全局全屏按钮",
  245. "isrender": 1
  246. }
  247. ]
  248. }
  249. },
  250. handleError: (res)=> {
  251. console.log('捕获到错误', res)
  252. if(res.retcode!==5404){
  253. item.player.stop()
  254. item.player.destroy();
  255. item.player.play()
  256. }
  257. },
  258. handleSuccess: function() {
  259. console.log("播放成功回调函数,此处可执行播放成功后续动作");
  260. if(callback){
  261. callback(item)
  262. }
  263. },
  264. capturePictureCallBack: function(data){
  265. item.player.play()
  266. item.player.setPoster(item.file.base64)
  267. // item.player.stop()
  268. // item.player.destroy();
  269. // document.getElementById(data.id).innerHTML=`<img src="${item.file.base64}" style="width:100%;height:100%;display:block;">`
  270. }
  271. });
  272. // item.player.play()
  273. },
  274. renderflvitems(){
  275. function initVideo({id,url}){
  276. const video = document.getElementById(id);
  277. var flvPlayer = flvjs.createPlayer({
  278. type: 'flv', // 媒体类型,默认是 flv,
  279. isLive: true, // 是否是直播流
  280. // hasAudio: ture, // 是否有音频
  281. // hanVideo: ture, // 是否有视频
  282. url // 流地址
  283. },{
  284. // 其他的配置项可以根据项目实际情况参考 api 去配置
  285. autoCleanupMinBackwardDuration: true, // 清除缓存 对 SourceBuffer 进行自动清理
  286. })
  287. flvPlayer.attachMediaElement(video);
  288. flvPlayer.load();
  289. flvPlayer.play();
  290. return flvPlayer;
  291. }
  292. let flvs=[
  293. {
  294. id:"flv-video-1",
  295. name:"尧柏室外" ,
  296. url: 'https://rtmp01open.ys7.com:9188/v3/openlive/D17867806_1_1.flv?expire=1727866323&id=631202165163040768&t=b38d44dd320b261cbd4b49714d3bc5c77dce2f941cc749ef5d7cba1305ada9f8&ev=100'
  297. },
  298. {
  299. id:"flv-video-2",
  300. name:'尧柏室内',
  301. url:'https://rtmp01open.ys7.com:9188/v3/openlive/D21357992_1_1.flv?expire=1727866347&id=631202266972758016&t=213001a96c71218df4eb35a3ccfcc3e4e0477ebd88dd1277ce6de864325bd758&ev=100'
  302. }
  303. ]
  304. this.flvsItem=flvs
  305. this.$nextTick(()=>{
  306. for(let i=0;i<flvs.length;i++){
  307. initVideo({
  308. id:flvs[i].id,
  309. url:flvs[i].url
  310. })
  311. }
  312. })
  313. }
  314. },
  315. destroyed() {
  316. this.items.map(item=>{
  317. if(item.player&&item.player.destroy){
  318. var destroyPromise = item.player.destroy();
  319. destroyPromise.then((data) => {
  320. console.log("promise 获取 数据", data)
  321. })
  322. }
  323. })
  324. },
  325. }
  326. </script>
  327. <style>
  328. .flv-video{
  329. object-fit:fill;
  330. background-color: #ccc;
  331. }
  332. .camera-page{
  333. width: 100%;
  334. min-height: 100vh;
  335. background-color: #042B5A;
  336. }
  337. .nav{
  338. height: 50px;
  339. background-image: url('../../assets/images/head.png');
  340. background-size: 100% 100%;
  341. text-align: center;
  342. color: #fff;
  343. line-height: 35px;
  344. font-size: 24px;
  345. font-weight: 600;
  346. letter-spacing: 8px;
  347. }
  348. .camera-container{
  349. width: 100%;
  350. display: flex;
  351. align-items: center;
  352. justify-content: center;
  353. flex-wrap: wrap;
  354. padding: 10px;
  355. box-sizing: border-box;
  356. }
  357. .video-container{
  358. width:210px;
  359. height: 170px;
  360. box-sizing: border-box;
  361. margin: 6px;
  362. position: relative;
  363. overflow: hidden;
  364. cursor: pointer;
  365. }
  366. .video-container iframe{
  367. border: 0;
  368. box-sizing: border-box;
  369. display: block;
  370. }
  371. .video-container .name{
  372. color: #fff;
  373. padding: 3px 0;
  374. background-color: rgba(0,0,0,0.6);
  375. text-indent: 14px;
  376. font-size: 14px;
  377. text-overflow: ellipsis;
  378. white-space: nowrap;
  379. overflow: hidden;
  380. }
  381. .video-container .camera-show-handle{
  382. position: absolute;
  383. width: 100%;
  384. height: 100%;
  385. bottom: 36px;
  386. left: 0;
  387. z-index: 999;
  388. }
  389. .footer-controls{
  390. display: flex;
  391. justify-content: center;
  392. align-items: center;
  393. font-size: 28px;
  394. }
  395. #camera-model{
  396. position: fixed;
  397. left: 0;
  398. top: 0;
  399. bottom: 0;
  400. right: 0;
  401. background-color: rgba(0,0,0,0.6);
  402. z-index: 9999;
  403. }
  404. #camera-box{
  405. width: 900px;
  406. height: 750px;
  407. max-width: 100%;
  408. background-color: #fff;
  409. margin: 50px auto;
  410. border-radius: 10px;
  411. box-shadow: 1px 1px 6px rgba(0,0,0,0.6);
  412. overflow: hidden;
  413. padding: 10px;
  414. }
  415. #camera-box .title{
  416. widows: 100%;
  417. height: 50px;
  418. line-height: 50px;
  419. font-weight: 600;
  420. font-size: 20px;
  421. background-color: #fff;
  422. color: #333;
  423. border-bottom: 1px solid #eaeaea;
  424. position: relative;
  425. text-align: center;
  426. }
  427. #camera-box .title .close{
  428. width: 50px;
  429. height: 50px;
  430. color: #6e6c6c;
  431. text-align: center;
  432. line-height: 50px;
  433. position: absolute;
  434. right: 0;
  435. top: 0;
  436. cursor: pointer;
  437. font-size: 30px;
  438. }
  439. #camera-deviceSerial{
  440. width: 900px;
  441. height: 700px;
  442. background-color: #3333;
  443. }
  444. </style>