BigShow.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. <!--大屏显示组件-->
  2. <template>
  3. <div>
  4. <draggable
  5. v-for="item in currentBigshow"
  6. element="div"
  7. v-model="signalPreList"
  8. :options="dragOptions2"
  9. :class="['split_screen',
  10. bigScreenObj[item.ID].splitStatus === 0 ? 'split_screen_one' :
  11. bigScreenObj[item.ID].splitStatus === 1 ? 'split_screen_four' :
  12. bigScreenObj[item.ID].splitStatus === 2 ? 'split_screen_nine' :
  13. bigScreenObj[item.ID].splitStatus === 3 ? 'split_screen_sixteen' : '']"
  14. :style="{
  15. float:'left',
  16. width:item.Width*bigScale + 'px',
  17. height:item.Height*bigScale + 'px',
  18. left:(item.Left-window.Left)*bigScale+'px',
  19. top:(item.Top-window.Top)*bigScale+'px',
  20. zIndex:item.ZIndex,
  21. }"
  22. :id="item.ID"
  23. >
  24. <VueDragResize
  25. v-for="itemV in bigScreenObj[item.ID] ? bigScreenObj[item.ID].signalArr : []" :key="itemV.Id" class="sitem"
  26. :w="itemV.width" :h="itemV.height" :parentLimitation="false"
  27. :x="itemV.left" :y="itemV.top"
  28. @dragstop="(position) => dragStop(position,itemV,bigScreenObj,curOpeBigscreenId)"
  29. @resizestop="(size) => resizeSignal(size,itemV,bigScreenObj,curOpeBigscreenId)"
  30. >
  31. <div ref="signal" :id="itemV.ID" style="width:100%;height:100%;overflow: hidden">
  32. <VideoPlayer
  33. ref="videoPlayer"
  34. :options="videoPlayObj[itemV.sourceId]"
  35. :playsinline="true"
  36. :style="scaleFun(itemV)"
  37. />
  38. <div class="closeBtn" @click.stop="closeSignal(itemV)">×</div>
  39. </div>
  40. </VueDragResize>
  41. <div v-for="itemD in bigScreenObj[item.ID] ? bigScreenObj[item.ID].bindList : []" class="sitem2">
  42. {{itemD}}
  43. </div>
  44. </draggable>
  45. </div>
  46. </template>
  47. <script>
  48. import {mapState} from 'vuex'
  49. import draggable from 'vuedraggable'
  50. import VueDragResize from 'vue-drag-resize'
  51. import PubSub from 'pubsub-js'
  52. import '../assets/less/splitscreen.less'
  53. import {elePosition, getElementLeft, getElementTop, getStaticFile, guId} from "../../utils/tools"
  54. import {reqPreviewSourceList, reqRefreshView} from "../api"
  55. import VideoPlayer from "./player.vue"
  56. export default {
  57. data() {
  58. return {
  59. streamWindows:[], // 传递出去的信号源位置信息
  60. currentBigshow:[], // 当前显示的大屏
  61. playerOptions: { // rtmp视频流配置
  62. sources: [
  63. {
  64. "src": "rtmp://58.200.131.2:1935/livetv/hunantv",
  65. "type": "rtmp/flv"
  66. },/*{
  67. "src": "rtmp://58.200.131.2:1935/livetv/cctv1",
  68. "type": "rtmp/flv"
  69. }*/,
  70. ],
  71. aspectRatio: '482:224',
  72. techOrder: ['flash'],
  73. autoplay: true,
  74. controls: false,
  75. fluid:true,
  76. preload: 'auto',
  77. notSupportedMessage: '此视频暂无法播放,请稍后再试',
  78. },
  79. screenPosition:{}, // 大屏在视口中的位置
  80. videoPlayObj:{}, // 视频播放配置对象
  81. savePreWh:{}, // 保存旧的开窗宽高
  82. window:this.$attrs.window
  83. }
  84. },
  85. components: {
  86. draggable,
  87. VueDragResize,
  88. VideoPlayer
  89. },
  90. created() {
  91. this.initBigScreen()
  92. },
  93. updated() {
  94. // 获取大屏在视口中的位置
  95. this.currentBigshow.forEach(item => {
  96. const screenDiv = document.getElementById(item.ID)
  97. this.screenPosition[item.ID] = {
  98. top:getElementTop(screenDiv),
  99. left:getElementLeft(screenDiv)
  100. }
  101. })
  102. },
  103. beforeDestroy() {
  104. PubSub.unsubscribe(this.update_screenobj)
  105. },
  106. methods: {
  107. // 大屏开窗接口提交
  108. async refreshBigScreen(obj,Id) {
  109. if(Id){
  110. const signals = obj[Id].signalArr
  111. const streamWindows = signals.map((item,index) => ({
  112. left:item.left,
  113. top:item.top,
  114. width:item.width,
  115. height:item.height,
  116. id:index,
  117. sourceId:item.sourceId,
  118. widthScale:item.widthScale,
  119. heightScale:item.heightScale,
  120. orginRect:{}
  121. }))
  122. await reqRefreshView({
  123. bigScreenId:Id,
  124. streamWindows
  125. })
  126. }
  127. },
  128. // 拖动结束
  129. dragStop(positon,item,obj,Id) {
  130. // 深度克隆对象
  131. const newObj = JSON.parse(JSON.stringify(obj))
  132. item.left = positon.left
  133. item.top = positon.top
  134. const arr = newObj[Id].signalArr.filter(s => s.Id !== item.Id)
  135. newObj[Id].signalArr = [...arr,item]
  136. this.refreshBigScreen(newObj,Id)
  137. },
  138. // 缩放结束
  139. resizeSignal(size,item,obj,Id) {
  140. const bigScale = this.$store.state.bigScale
  141. // 深度克隆对象
  142. const newObj = JSON.parse(JSON.stringify(obj))
  143. item.width = size.width
  144. item.height = size.height
  145. item.left = size.left
  146. item.top = size.top
  147. item.widthScale = item.width/(newObj[Id].width*bigScale)
  148. item.heightScale = item.height/(newObj[Id].height*bigScale)
  149. const arr = newObj[Id].signalArr.filter(s => s.Id !== item.Id)
  150. newObj[Id].signalArr = [...arr,item]
  151. this.refreshBigScreen(newObj,Id)
  152. },
  153. // 关闭信号源
  154. closeSignal(signal) {
  155. const bigscreenId = signal.bigscreenId
  156. const bigScreenObj = this.$store.state.bigScreenObj
  157. // 1.找出是哪个大屏下的信号源发生了改变,过滤掉删除的那个
  158. const newSignalPreList = this.bigScreenObj[bigscreenId].signalArr.filter(item => item.Id !== signal.Id)
  159. // 2.重新赋值
  160. bigScreenObj[bigscreenId].signalArr = newSignalPreList
  161. this.refreshBigScreen(bigScreenObj,bigscreenId)
  162. },
  163. // 设置视频变形
  164. scaleFun:function (itemV) {
  165. // 1.算出当前视频的高度
  166. let videoHeight = itemV.width*9/16
  167. // 2.如果盒子的高度大于视频的高度,则视频的高度需要拉伸
  168. if(itemV.height>videoHeight){
  169. return `transform-origin: 0px 0px;transform:scaleY(${(itemV.height-videoHeight)/videoHeight+1})`
  170. }
  171. },
  172. // 大屏初始化
  173. async initBigScreen() {
  174. // 加载大屏json文件
  175. const bigScreenJson = await getStaticFile('EnityBigScreen.Data')
  176. // 过滤出显示的大屏
  177. this.currentBigshow = bigScreenJson.filter(item => item.WindowID === this.window.ID)
  178. if(this.currentBigshow.length){
  179. // 给大屏对象进行初始化显示
  180. const obj = {}
  181. bigScreenJson.forEach(item => {
  182. obj[item.ID] = {
  183. bindList:[],
  184. splitStatus:0,
  185. signalArr:[],
  186. width:item.Width,
  187. height:item.Height
  188. }
  189. const num = item.BindList.filter(item => item.DeviceID).length
  190. // 拼接屏数量
  191. for(let i=0;i<num;i++){
  192. obj[item.ID].bindList.push(i+1)
  193. }
  194. // 根据拼接屏数量得到分屏状态
  195. obj[item.ID].splitStatus = Math.floor(Math.sqrt(num)-1)
  196. })
  197. this.$store.dispatch('updateBigscreenObj',obj)
  198. // 获取视频播放的配置对象
  199. const preSingleList = await reqPreviewSourceList()
  200. const videoPlayObj = {}
  201. for(const item of preSingleList){
  202. videoPlayObj[item.sourceId] = {
  203. sources: [
  204. {
  205. "src": item.previewUrl,
  206. "type": "rtmp/flv"
  207. }
  208. ],
  209. techOrder: ['flash'],
  210. autoplay: true,
  211. controls: false,
  212. fluid:true,
  213. preload: 'auto',
  214. notSupportedMessage: '此视频暂无法播放,请稍后再试',
  215. }
  216. }
  217. this.videoPlayObj = videoPlayObj
  218. }
  219. }
  220. },
  221. computed: {
  222. ...mapState(['splitScreenStatus', 'bigScale','positionNum','curOpeBigscreenId','bigScreenObj','signalListJson','bigshowJson']),
  223. // 当前变动的信号源数组监控
  224. signalPreList: {
  225. get() {
  226. return this.$store.getters.currentSignalArr
  227. },
  228. set(arr) {
  229. setTimeout(() => {
  230. const bigscreenId = this.$store.state.curOpeBigscreenId
  231. const bigScreenObj = this.$store.state.bigScreenObj
  232. const bigScale = this.$store.state.bigScale
  233. const positionNum = this.$store.state.positionNum
  234. const arr2 = []
  235. arr.forEach(item => {
  236. arr2.push(JSON.parse(JSON.stringify(item)))
  237. })
  238. const newObj = arr2.filter(item => !item.Id)
  239. const otherSignals = arr2.filter(item => item.Id)
  240. newObj[0].Id = guId()
  241. newObj[0].bigscreenId = bigscreenId
  242. if(bigScreenObj[bigscreenId]){
  243. newObj[0].splitScreenStatus = bigScreenObj[bigscreenId].splitStatus + 1
  244. newObj[0].width = bigScreenObj[bigscreenId].width * bigScale / newObj[0].splitScreenStatus
  245. newObj[0].height = bigScreenObj[bigscreenId].height * bigScale / newObj[0].splitScreenStatus
  246. newObj[0].widthScale = newObj[0].width / (bigScreenObj[bigscreenId].width * bigScale)
  247. newObj[0].heightScale = newObj[0].height / (bigScreenObj[bigscreenId].height * bigScale)
  248. const positionInfo = elePosition(newObj[0].width,newObj[0].height,positionNum,this.screenPosition[bigscreenId].top,this.screenPosition[bigscreenId].left,bigScreenObj[bigscreenId].splitStatus+1)
  249. newObj[0].top = positionInfo.top - this.screenPosition[bigscreenId].top
  250. newObj[0].left = positionInfo.left - this.screenPosition[bigscreenId].left
  251. bigScreenObj[bigscreenId].signalArr = [...otherSignals,...newObj]
  252. this.refreshBigScreen(bigScreenObj,bigscreenId)
  253. }
  254. })
  255. }
  256. },
  257. // 拖拽选项配置
  258. dragOptions1() {
  259. return {
  260. animation: 0,
  261. group: {
  262. name: "description",
  263. pull: 'clone',
  264. put: false
  265. },
  266. ghostClass: "ghost",
  267. }
  268. },
  269. dragOptions2() {
  270. return {
  271. animation: 0,
  272. group: "description",
  273. disabled:false,
  274. sort:false,
  275. }
  276. },
  277. player() {
  278. return this.$refs.videoPlayer.player
  279. },
  280. },
  281. watch: {
  282. window: {
  283. handler (newV, oldV) {
  284. if(newV.ID !== oldV){
  285. // 更新大屏对象
  286. this.initBigScreen()
  287. }
  288. },
  289. deep:true
  290. }
  291. }
  292. }
  293. </script>