Ver código fonte

添加 ws 记录视频播放进度

reghao 2 anos atrás
pai
commit
035a12e4e0

+ 4 - 3
src/components/VideoPlayer.vue

@@ -5,6 +5,7 @@
 
 <script>
 import { videoUrl } from '@/api/video'
+import SocketInstance from '@/utils/ws/socket-instance'
 
 const DPlayer = require('dplayer')
 const flv = require('flv.js')
@@ -64,7 +65,7 @@ export default {
     }*/
   },
   mounted() {
-    // SocketInstance.connect()
+    SocketInstance.connect()
     const videoId = this.videoProp.videoId
     if (this.getUrl) {
       this.getVideoUrl(videoId)
@@ -126,11 +127,11 @@ export default {
       // 跳转到上次看到的位置
       player.seek(pos)
       player.on('progress', function() {
-        // SocketInstance.send({ videoId: videoId, currentTime: player.video.currentTime })
+        SocketInstance.send({ videoId: videoId, currentTime: player.video.currentTime })
       })
 
       player.on('ended', () => {
-        // SocketInstance.send({ videoId: videoId, currentTime: player.video.currentTime })
+        SocketInstance.send({ videoId: videoId, currentTime: player.video.currentTime })
         // TODO 当前视频播放完成后判断是否继续播放相关推荐中的视频
         console.log('视频播放完成')
         if (this.autoPlayList) {

+ 99 - 0
src/utils/ws/socket-instance.js

@@ -0,0 +1,99 @@
+import WsSocket from '@/utils/ws/ws-socket'
+import { Notification } from 'element-ui'
+
+/**
+ * SocketInstance 连接实例
+ *
+ * 注释: 所有 WebSocket 消息接收处理在此实例中处理
+ */
+class SocketInstance {
+  /**
+   * WsSocket 实例
+   */
+  socket
+
+  /**
+   * SocketInstance 初始化实例
+   */
+  constructor() {
+    this.socket = new WsSocket(
+      () => {
+        const token = '1234567890'
+        if (token === null || token === '') {
+          return null
+        } else {
+          return 'wss://api.reghao.cn/ws/progress?token=' + token
+        }
+      },
+      {
+        onError: evt => {
+          console.log('Websocket 连接失败回调方法')
+        },
+        // Websocket 连接成功回调方法
+        onOpen: evt => {
+          // 更新 WebSocket 连接状态
+          console.log('ws 连接成功')
+        },
+        // Websocket 断开连接回调方法
+        onClose: evt => {
+          // 更新 WebSocket 连接状态
+          console.log('ws 连接断开')
+        }
+      }
+    )
+
+    this.registerEvents()
+  }
+
+  // 连接 WebSocket 服务
+  connect() {
+    this.socket.connection()
+  }
+
+  /**
+   * 注册回调消息处理事件
+   */
+  registerEvents() {
+    this.socket.on('heartbeat', data => {})
+
+    this.socket.on('censorVideo', data => {
+      console.log('----------')
+      console.log(data)
+      Notification({
+        title: '友情提示',
+        message: data,
+        type: 'warning',
+        duration: 3000
+      })
+    })
+
+    this.socket.on('event_error', data => {
+      Notification({
+        title: '友情提示',
+        message: data.message,
+        type: 'warning'
+      })
+    })
+  }
+
+  /**
+   * 聊天发送数据
+   *
+   * @param {Object} mesage
+   */
+  send(mesage) {
+    this.socket.send(mesage)
+  }
+
+  /**
+   * 推送消息
+   *
+   * @param {String} event 事件名
+   * @param {Object} data 数据
+   */
+  emit(event, data) {
+    this.socket.emit(event, data)
+  }
+}
+
+export default new SocketInstance()

+ 236 - 0
src/utils/ws/ws-socket.js

@@ -0,0 +1,236 @@
+class WsSocket {
+  /**
+   * Websocket 连接
+   *
+   * @var Websocket
+   */
+  connect = null
+
+  /**
+   * 配置信息
+   *
+   * @var Object
+   */
+  config = {
+    heartbeat: {
+      setInterval: null,
+      pingInterval: 20000,
+      pingTimeout: 60000
+    },
+    reconnect: {
+      lockReconnect: false,
+      setTimeout: null, // 计时器对象
+      time: 5000, // 重连间隔时间
+      number: 1000 // 重连次数
+    }
+  }
+
+  // 最后心跳时间
+  lastTime = 0
+
+  /**
+   * 自定义绑定消息事件
+   *
+   * @var Array
+   */
+  onCallBacks = []
+
+  defaultEvent = {
+    onError: evt => {},
+    onOpen: evt => {},
+    onClose: evt => {}
+  }
+
+  /**
+   * 创建 WsSocket 的实例
+   *
+   * @param {Function} urlCallBack url闭包函数
+   * @param {Object} events 原生 WebSocket 绑定事件
+   */
+  constructor(urlCallBack, events) {
+    this.urlCallBack = urlCallBack
+
+    // 定义 WebSocket 原生方法
+    this.events = Object.assign({}, this.defaultEvent, events)
+
+    this.on('connect', data => {
+      this.config.heartbeat.pingInterval = data.ping_interval * 1000
+      this.config.heartbeat.pingTimeout = data.ping_timeout * 1000
+      this.heartbeat()
+    })
+  }
+
+  /**
+   * 事件绑定
+   *
+   * @param {String} event 事件名
+   * @param {Function} callBack 回调方法
+   */
+  on(event, callBack) {
+    this.onCallBacks[event] = callBack
+    return this
+  }
+
+  /**
+   * 加载 WebSocket
+   */
+  loadSocket() {
+    const url = this.urlCallBack()
+    const connect = new WebSocket(url)
+    connect.onerror = this.onError.bind(this)
+    connect.onopen = this.onOpen.bind(this)
+    connect.onmessage = this.onMessage.bind(this)
+    connect.onclose = this.onClose.bind(this)
+    this.connect = connect
+  }
+
+  /**
+   * 连接 Websocket
+   */
+  connection() {
+    this.connect === null && this.loadSocket()
+  }
+
+  /**
+   * 掉线重连 Websocket
+   */
+  reconnect() {
+    // 没连接上会一直重连,设置延迟避免请求过多
+    clearTimeout(this.config.reconnect.setTimeout)
+
+    this.config.reconnect.setTimeout = setTimeout(() => {
+      this.connection()
+
+      console.log(`网络连接已断开,正在尝试重新连接...`)
+    }, this.config.reconnect.time)
+  }
+
+  /**
+   * 解析接受的消息
+   *
+   * @param {Object} evt Websocket 消息
+   */
+  onParse(evt) {
+    const { event, payload } = JSON.parse(evt.data)
+
+    return {
+      event: event,
+      payload: payload,
+      orginData: evt.data
+    }
+  }
+
+  /**
+   * 打开连接
+   *
+   * @param {Object} evt Websocket 消息
+   */
+  onOpen(evt) {
+    this.lastTime = new Date().getTime()
+
+    this.events.onOpen(evt)
+
+    this.ping()
+  }
+
+  /**
+   * 关闭连接
+   *
+   * @param {Object} evt Websocket 消息
+   */
+  onClose(evt) {
+    this.events.onClose(evt)
+
+    this.connect.close()
+
+    this.connect = null
+
+    evt.code === 1006 && this.reconnect()
+  }
+
+  /**
+   * 连接错误
+   *
+   * @param {Object} evt Websocket 消息
+   */
+  onError(evt) {
+    this.events.onError(evt)
+    this.connect.close()
+    this.connect = null
+    this.reconnect()
+  }
+
+  /**
+   * 接收消息
+   *
+   * @param {Object} evt Websocket 消息
+   */
+  onMessage(evt) {
+    this.lastTime = new Date().getTime()
+    const payload = evt.data
+    console.log(payload)
+    const result = this.onParse(evt)
+
+    // 判断消息事件是否被绑定
+    // eslint-disable-next-line no-prototype-builtins
+    if (this.onCallBacks.hasOwnProperty(result.event)) {
+      this.onCallBacks[result.event](result.payload, result.orginData)
+    } else {
+      console.warn(`WsSocket 消息事件[${result.event}]未绑定...`)
+    }
+  }
+
+  /**
+   * WebSocket 心跳检测
+   */
+  heartbeat() {
+    this.config.heartbeat.setInterval = setInterval(() => {
+      const t = new Date().getTime()
+
+      if (t - this.lastTime > this.config.heartbeat.pingTimeout) {
+        this.reconnect()
+      } else {
+        this.ping()
+      }
+    }, this.config.heartbeat.pingInterval)
+  }
+
+  ping() {
+    this.connect.send('{"event":"heartbeat","payload":"ping"}')
+  }
+
+  /**
+   * 聊天发送数据
+   *
+   * @param {Object} mesage
+   */
+  send(mesage) {
+    this.connect.send(JSON.stringify(mesage))
+  }
+
+  /**
+   * 关闭连接
+   */
+  close() {
+    this.connect.close()
+  }
+
+  /**
+   * 推送消息
+   *
+   * @param {String} event 事件名
+   * @param {Object} data 数据
+   */
+  emit(event, data) {
+    const payload = JSON.stringify({ event, data })
+
+    if (this.connect && this.connect.readyState === 1) {
+      this.connect.send(payload)
+    } else {
+      alert('WebSocket 连接已关闭...')
+      console.error('WebSocket 连接已关闭...', this.connect)
+    }
+  }
+}
+
+export default WsSocket