index.vue 16 KB

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