index.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <div class="dot-box" :style="{ width: width ? width + 'px' : '100%', height: height ? height + 'px' : '100%' }">
  3. <div class="video-box" @click="play_now">
  4. <HikvisionPlayer
  5. v-if="!reload && (isPlaying || autoplay) && !isNoLive"
  6. ref="videoPlayer"
  7. style="width: 100%; height: 100%; object-fit: fill"
  8. @on-playing="onHkPlaying"
  9. @on-play-error="onHKPlayError"
  10. />
  11. <FlvVideo v-if="isPlaying && isNoLive" ref="FlvVideoRef" :videoUrl="dot_data.video_code"style="width: 100%; height: 100%; object-fit: fill" />
  12. <img v-if="posterVisible" class="video-play" src="@/assets/images/video/play.png" alt="" />
  13. <img v-if="posterVisible && dot_data.poster" class="video-poster" :src="dot_data.poster" />
  14. <div v-if="errBKVisible" class="err_bk">
  15. <div class="err_box">
  16. <div class="err_inner_box">
  17. <div class="err_icon"></div>
  18. <div class="err_text">视频解析错误</div>
  19. <div class="refresh_btn" @click="play">刷新</div>
  20. </div>
  21. </div>
  22. </div>
  23. </div>
  24. </div>
  25. </template>
  26. <script setup lang="ts" name="HKVideo">
  27. import HikvisionPlayer from './hikvision-h5player.vue';
  28. import { getVideoUrlById } from '@/api/videoMonitor';
  29. const props = defineProps({
  30. dot_data: Object,
  31. width: Number,
  32. height: Number,
  33. autoplay: Boolean,
  34. isNoLive: Boolean
  35. });
  36. const play = () => {
  37. play_now();
  38. };
  39. const refresh_data = () => {
  40. reload.value = true;
  41. nextTick(() => {
  42. reload.value = false;
  43. play_now();
  44. });
  45. };
  46. const emits = defineEmits(['propClick', 'videoPreviewClick', 'favorClick']);
  47. // https://blog.csdn.net/weixin_49826079/article/details/135147184
  48. const isShowTip = ref(true);
  49. const contentRef = ref(false);
  50. const wsUrl = ref('');
  51. const isPlaying = ref(false);
  52. const errBKVisible = ref(false);
  53. const posterVisible = ref(true);
  54. const isShowTooltip = async () => {
  55. if (contentRef.value.parentNode.offsetWidth > contentRef.value.offsetWidth) {
  56. isShowTip.value = true;
  57. } else {
  58. isShowTip.value = false;
  59. }
  60. };
  61. const onHkPlaying = async () => {
  62. console.log('onHkPlaying');
  63. errBKVisible.value = false;
  64. };
  65. const onHKPlayError = async () => {
  66. console.log('onHKPlayError');
  67. errBKVisible.value = true;
  68. isPlaying.value = false;
  69. };
  70. let videoPlayer = ref(null);
  71. let reload = ref(false);
  72. watch(
  73. () => props.dot_data,
  74. () => {
  75. if (!!videoPlayer.value) {
  76. videoPlayer.value.stop();
  77. }
  78. posterVisible.value = true;
  79. errBKVisible.value = false;
  80. isPlaying.value = false;
  81. if (props.autoplay) {
  82. reload.value = true;
  83. }
  84. nextTick(() => {
  85. if (props.autoplay) {
  86. reload.value = false;
  87. play_now(true);
  88. }
  89. });
  90. },
  91. {
  92. deep: true
  93. }
  94. );
  95. const play_now = async (check?: boolean) => {
  96. posterVisible.value = false;
  97. errBKVisible.value = false;
  98. isPlaying.value = true;
  99. // 视频监控数据
  100. getVideoUrlById(props.dot_data.video_code).then((res) => {
  101. wsUrl.value = res.data;
  102. videoPlayer.value.play(wsUrl.value);
  103. });
  104. console.log('play_now');
  105. };
  106. const stop_now = async () => {
  107. if (isPlaying.value) {
  108. errBKVisible.value = false;
  109. videoPlayer.value.stop();
  110. isPlaying.value = false;
  111. }
  112. posterVisible.value = true;
  113. };
  114. const handleFullScreen = (name) => {
  115. videoPlayer.value.fullScreen(name);
  116. };
  117. const handleScreenshot = (name) => {
  118. videoPlayer.value.handleScreenshot(name);
  119. };
  120. const getPlayer = (name) => {
  121. return videoPlayer.value.getPlayer(name);
  122. };
  123. defineExpose({
  124. play,
  125. refresh_data,
  126. handleScreenshot,
  127. handleFullScreen,
  128. getPlayer
  129. });
  130. onMounted(() => {
  131. if (!!props.autoplay) {
  132. play_now(true);
  133. }
  134. });
  135. </script>
  136. <style lang="scss" scoped>
  137. .dot-box {
  138. width: 100%;
  139. display: flex;
  140. justify-content: space-between;
  141. background-color: #000;
  142. }
  143. .video-box {
  144. width: 100%;
  145. height: 100%;
  146. overflow: hidden;
  147. cursor: pointer;
  148. position: relative;
  149. border-radius: 2px;
  150. //border: 1px solid #0056cf;
  151. .video-poster {
  152. width: 100%;
  153. height: 100%;
  154. cursor: pointer;
  155. }
  156. .video-play {
  157. width: 25px;
  158. height: 25px;
  159. position: absolute;
  160. top: 50%;
  161. left: 50%;
  162. transform: translate(-50%, -50%);
  163. cursor: pointer;
  164. }
  165. .err_bk {
  166. z-index: 900;
  167. left: 0;
  168. top: 0;
  169. background: #000;
  170. position: absolute;
  171. width: 100%;
  172. height: 100%;
  173. .err_box {
  174. display: flex;
  175. justify-content: center;
  176. align-items: center;
  177. width: 100%;
  178. height: 100%;
  179. .err_inner_box {
  180. display: flex;
  181. flex-direction: column;
  182. justify-content: space-between;
  183. display: inline-flex;
  184. justify-content: center;
  185. align-items: center;
  186. .err_icon {
  187. width: 18px;
  188. height: 20px;
  189. background: url('@/assets/images/video/err_video.png') no-repeat;
  190. background-size: 100% 100%;
  191. }
  192. .err_text {
  193. font-size: 14px;
  194. color: #ffffffb3;
  195. margin-bottom: 4px;
  196. }
  197. .refresh_btn {
  198. width: 70px;
  199. height: 25px;
  200. border: 1px solid #001b41;
  201. background: #006affcc;
  202. cursor: pointer;
  203. color: #ffffff;
  204. text-align: center;
  205. font-size: 14px;
  206. font-style: normal;
  207. font-weight: 400;
  208. line-height: 25px;
  209. }
  210. }
  211. }
  212. }
  213. }
  214. .img {
  215. width: 100%;
  216. height: 170px;
  217. }
  218. </style>