index.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <template>
  2. <div v-drag class="video-trail-container">
  3. <div class="video-trail-title">
  4. 视频跟随
  5. </div>
  6. <div class="video-trail-content">
  7. <div class="main-video">
  8. <video-obj
  9. v-if="videoList.length > 0"
  10. :stream="videoList[0].video.cameraLive"
  11. :key="`main-${videoList[0].key}`"
  12. />
  13. </div>
  14. <div class="trail-videos">
  15. <video-obj
  16. v-for="item in videoList"
  17. :key="item.key"
  18. :stream="item.video.cameraLive"
  19. :lastTime="0"
  20. />
  21. </div>
  22. </div>
  23. <socket-message
  24. v-if="this.fingerprint.visitorId"
  25. :onMessage="onMessage"
  26. :ws="`/pkb/uwb/trail?client=${this.fingerprint.visitorId}&deviceId=${deviceId}`"
  27. />
  28. </div>
  29. </template>
  30. <script>
  31. import VideoObj from "@/components/Video/index.vue";
  32. import SocketMessage from "@/components/WebsocketMessage/index.vue";
  33. import FingerprintJS from "@fingerprintjs/fingerprintjs";
  34. export default {
  35. components: {SocketMessage, VideoObj},
  36. name: "video-trail",
  37. props: {
  38. ws: {
  39. type: String,
  40. default: '',
  41. },
  42. },
  43. watch: {
  44. ws(val) {
  45. this.init();
  46. },
  47. },
  48. data() {
  49. return {
  50. videoList: [],
  51. fingerprint: "",
  52. deviceId: "845D3",
  53. timer: null // 新增定时器变量
  54. };
  55. },
  56. // 组件卸载前清空图层信息
  57. beforeDestroy() {
  58. if (this.timer) {
  59. clearInterval(this.timer); // 清除定时器
  60. }
  61. },
  62. created() {
  63. this.getBrowserFingerprint();
  64. this.removeOldVideos(); // 添加调用
  65. this.timer = setInterval(this.removeOldVideos, 60000); // 每分钟调用一次,并将定时器赋值给timer变量
  66. },
  67. mounted() {
  68. this.init();
  69. },
  70. methods: {
  71. init() {
  72. },
  73. onMessage(newVideo) {
  74. const {msg: video} = newVideo
  75. video.srcTimestamp = Date.now();
  76. video.key = `${video.key}_${video.fenceId}`;
  77. const videoIndex = this.videoList.findIndex(item => item.key === video.key);
  78. if (videoIndex !== -1) {
  79. this.videoList.splice(videoIndex, 1);
  80. }
  81. this.videoList.unshift(video);
  82. },
  83. removeOldVideos() {
  84. const currentTime = Date.now();
  85. while (this.videoList.length > 0 && (currentTime - this.videoList[this.videoList.length - 1].srcTimestamp) > 20 * 60 * 1000) {
  86. this.videoList.pop();
  87. }
  88. },
  89. async getBrowserFingerprint() {
  90. try {
  91. const fp = await FingerprintJS.load();
  92. this.fingerprint = await fp.get();
  93. } catch (error) {
  94. console.error('Error loading fingerprint generator:', error);
  95. }
  96. },
  97. },
  98. };
  99. </script>
  100. <style lang="scss" scoped>
  101. .video-trail-container {
  102. height: 70vh;
  103. position: absolute;
  104. top: 50px;
  105. left: 100px;
  106. background: #060624ba;
  107. .video-trail-title {
  108. height: 30px;
  109. width: 100%;
  110. background: #fefefe;
  111. padding: 0 15px;
  112. line-height: 30px;
  113. cursor: move;
  114. }
  115. .video-trail-content {
  116. width: fit-content;
  117. height: calc(100% - 30px);
  118. box-sizing: border-box;
  119. padding: 10px;
  120. display: flex;
  121. align-items: flex-start;
  122. justify-content: flex-start;
  123. .main-video {
  124. width: 40vw;
  125. height: 70vh;
  126. }
  127. .trail-videos {
  128. width: 18vw;
  129. height: 70vh;
  130. margin-left: 16px;
  131. display: flex;
  132. flex-direction: column;
  133. justify-content: flex-start;
  134. align-items: center;
  135. }
  136. }
  137. }
  138. </style>