vue+海康威视视频web插件开发

这篇具有很好参考价值的文章主要介绍了vue+海康威视视频web插件开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、环境准备

下载地址:海康威视官网

下载页面

vue+海康威视视频web插件开发

文件解压后的目录

vue+海康威视视频web插件开发

运行bin文件下的VideoWebPlugin.exe

二、插件demo测试

demo/demo_window_integration.html 包含了插件所有功能的,可参照此demo来开发、验证功能、排查问题

demo/demo_window_simple_playback.html.html  视频回放,可在此基础上二次开发

demo/demo_window_simple_preview.html 实时预览,可在基础上二次开发

在浏览器中打开 demo/demo_window_integration.html 文件如下

vue+海康威视视频web插件开发

 在进入官网运行管理平台获取到 Appkey、AppSecret、Ip、Port,就能连接到自己的摄像头进行调试开发了

三、api相关介绍

1、JS_StartService(szType,options) 启动插件服务接口 (返回值Promise)

        szType:服务类型 固定填充 “window”(必填)

        options:可选参数对象 固定填充{dllPath: "./VideoPluginConnect.dll"}(对象选填)

2、JS_Disconnect() 断开服务接口 (返回值Promise)

3、JS_CreateWnd(szId, iWidth, iHeight) 创建插件窗口接口 (返回值Promise)

        szId:父窗口的id (必填)

        iWidth:元素 ID 标识窗口的宽度 (必填)

        iHeight:元素 ID 标识窗口的高度 (必填)

4、JS_SetWindowControlCallback(callback) 设置消息回调接口

       callback(对象 必填) 示例

       {

                cbIntegrationCallBack(必要属性): function(oData){ // oData 是封装的视频 web 插件回调消息的消息体
                console.log(JSON.stringify(oData)); // 打印消息体至控制台

         }

5、JS_Resize(iWidth,iHeight) 调整插件窗口大小、位置接口

        iWidth:DIV 窗口宽度 (必填)

        iHeight:DIV 窗口高度(必填)

6、JS_CuttingPartWindow(iLeft, iTop, iWidth, iHeight) 扣除部分插件窗口接口

        场景:插件窗口创建后,会始终置顶,因此当和其它组件一同使用时,会遮挡其它组件内容,该接口 的作用是,当部分插件窗口不需要置顶时,我们会隐藏部分插件窗口。也就是向上滚动的时候会隐藏

        iLeft:距离插件窗口左边距(必填)

        iTop:距离插件窗口上边距(必填)

        iWidth:需要扣除的宽度(必填)

        iHeight:需要扣除的高度(必填)

7、JS_RepairPartWindow(iLeft, iTop, iWidth, iHeight) 还原扣除部分窗口后的插件窗口

        场景:一般联合 JS_CuttingPartWindow 一起使用,在还原部分窗口后 在扣除

        iLeft:扣除窗口的顶点距离插件窗 口左边距 (必填)

        iTop:扣除窗口的顶点距离插件窗 口上边距 (必填)

        iWidth:扣除窗口的宽度(必填)

        iHeight:扣除窗口的高度(必填)

8、JS_HideWnd() 插件窗口隐藏接口

9、JS_ShowWnd() 插件窗口显示接口

10、JS_DestroyWnd() 插件窗口销毁接口

11、JS_WakeUp(szProtocal) 唤醒 WebControl.exe 接口

        场景 当 WebControl.exe 未启动时唤醒 WebControl.exe。若 WebControl.exe 已启动则忽略

        szProtocal:唤醒协议 内容固定为("VideoWebPlugin://")

12、JS_RequestInterface({funcName,argument})通过请求响应接口 (返回值Promise)

        funcName:功能标识(必填)

        argument:功能参数 (object 格式的字符串)

  • 例 申请 RSA 公钥
 { funcName: "getRSAPubKey", argument: "{ keyLength: 1024 }" }
  • 初始化    
{
 funcName: "init",
 argument: "{
 appkey: "afsgnhmj34567dgh", // API 网关提供的 appkey
 secret: "vgkk3g0jaoj0igoigj", // API 网关提供的 secret
 ip: "10.33.31.4", // API 网关 IP 地址
 port: 9016, // API 网关端口
 playMode: 0, //播放模式(决定显示预览还是回放界面),0-预览 1-录像播放
 encryptedFields: "appkey,secret", //secret 和 appkey 已加密,对多个字段加密存在初始化耗时问题
 snapDir: "D:\SnapDir", // 抓图存储路径
 layout: "2x2" // 初始化 2x2 布局
 showToolbar: 1, // 显示工具栏
 showIntelligent: 1, // 显示智能信息
 buttonIDs: "0,16,256,257,258"
 }"
}
  • 根据监控点编号视频预览
{
 funcName: "startPreview",
 argument: "{
 cameraIndexCode: "afsgnhmj34567dgh", // 监控点编号
 streamMode: 0, // 主子码流标识,0-主码流 1-子码流
 transMode: 1, // 传输协议,0-UDP 1-TCP
 gpuMode: 0 // 是否开启 GPU 硬解,不建议开启,0-不开启 1-开启
 }"
}
  • 停止所有视频预览
{
 funcName: "stopAllPreview"
}
  • 根据监控点编号录像回放
{
  funcName: "startPlayback",
  argument: "{
    cameraIndexCode: "afsgnhmj34567dgh", // 监控点编号
    startTimeStamp: "10237898985", // 录像查询开始时间戳,单位:秒
    endTimeStamp: "10237899985", // 录像查询结束时间戳,单位:秒
    recordLocation: 0, // 录像存储类型 0-中心存储 1-设备存储
    transMode: 1, // 传输协议 ,0-UDP 1-TCP
    gpuMode: 0 // 是否开启 GPU 硬解,0-不开启 1-开启
   }"
}
  • 停止所有录像回放
{
 funcName: "stopAllPlayback"
}
  • 销毁播放实例
{
 funcName: "destroyWnd"
}
  •  获取当前布局
{
 funcName: "getLayout"
}
  • 设置当前布局 
{
 funcName: " setLayout",
 argument: "{
 layout: "2x2" // 窗口布局 
 }"
}

// 布局可选值有“1x1”、
    “2x2”、“3x3”、“4x4”、“5x5”、“1x2”、
    “1+2”、“1+5”、“1+7”、 “1+8”、“1+9”、
    “1+12”、“1+16”、“4+9”、“1+1+12”、
    “3+4”、“1x4”、“4x6”
  • 画面字符叠加
{
 "funcName": "drawOSD",
 "argument": "{
     text: "温度:50\n 湿度:38", // 窗口布局
     x: 5, // 相对播放窗口左上角的横坐标起点
     y: 5, // 相对播放窗口左上角的纵坐标起点
     color: red // 字体颜色
 }"
}

根据监控点编号批量视频预览

{
"funcName": "startMultiPreviewByCameraIndexCode",
 "argument": {
  "list": [
   {
    "cameraIndexCode": "c633ef048fe141e1ac6dbeb36aaf21d3", // 监控点编号 
    "ezvizDirect": 0, // 是否直连萤石预览 未指定或为 0-非直连 其它值-直连
    "gpuMode": 0, // 是否启用 GPU 硬解  0-不启用 1-启用
    "streamMode": 0, // 主子码流标识  0-主码流 1-子码流
    "transMode": 1, // 传输协议 0-UDP 1-TCP
    "wndId": 1 // 播放窗口序号
   },
   {
    "cameraIndexCode": "c633ef048fe141e1ac6dbeb36aaf21d3",
    "ezvizDirect": 0,
    "gpuMode": 0,
    "streamMode": 0,
    "transMode": 1,
    "wndId": 2 
  }
 ]
 }
}
  •  根据监控点编号批量录像回放
{
 "funcName": "startMultiPlaybackByCameraIndexCode",
 "argument": 
{
 "list":[{
   "cameraIndexCode": "58e90452772a4d9da7c7ba4cef26dbf0", // 监控点编号
   "startTimeStamp": "10237898985", // 录像查询开始时间戳,单位:秒
   "endTimeStamp": "10237899985", // 录像查询结束时间戳,单位:秒
   "recordLocation": 0, // 录像存储类型 0-中心存储 1-设备存储
   "transMode": 1, // 传输协议 ,0-UDP 1-TCP
   "wndId": 1, // 窗口序号
   "gpuMode": 0 // 是否开启 GPU 硬解,0-不开启 1-开启
  }]
 }
}
  • 批量停止播放
{
 "funcName": "stopMultiPlay",
 "argument": 
{
 "list":[{
   "wndId": 1 // 窗口序号
  },
 {
   "wndId": 2 // 窗口序号
  }]
 }
}

 四、开发流程示意图

vue+海康威视视频web插件开发

       图中灰色部分为可选步骤。其中申请 RSA 公钥可选。申请 RSA 公钥是为了加密初始化中 的一些敏感参数,对安全性要求高的用户可以考虑对敏感参数加密。但需要注意的是,使用 RSA 公 钥加密机制必然会导致初始化耗时。一般情况下不需要调 JS_DestroyWnd 来销毁插件窗口 (JS_Disconnect 中会自行销毁),但一些特殊的场景如浏览器页面上需随时启用和禁用视频播放时, 需调 JS_DestroyWnd 来禁用视频播放,需要调 JS_CreateWnd 来启用视频播放。JS_DestroyWnd 和 JS_Disconnect 中会反初始化插件,这里无需调 JS_RequestInterface/uninit 反初始化。

 五、在vue中使用(实时预览完整示例)

 1、在public目录下的index.html中引入文件(资源文件在demo目录下

  <script src="./jquery-1.9.1.min.js"></script>
  <script src="./jsencrypt.min.js"></script>  // 用于 RSA 公钥加密
  <script src="./jsWebControl-1.0.0.min.js"></script> // 用于前端与插件交互

 2、线预览模块完整实例,其他的模块功能以此内推(如有疑惑,可参考doc目录下的文档,里面记载很清楚)

html 示例

 <div class="right" ref="playWndBox">
      <!-- 视频数据站位 -->
        <div
          id="playWnd"
          class="playWnd"
          :style="{
            height: playWndHeight + 'px',
            width: playWndWidth + 'px'
          }"
        ></div>
    </div>

 js 示例

<script>
// 声明公用变量 摄像头实例对现象,为了方便引用 定义在全局
let oWebControl = null
var initCount = 0
var pubKey = ''
export default {
  name: 'videoRuntime',
  data() {
    return {
      playWndHeight: '', // 视频盒子的高度
      playWndWidth: '' // 视频盒子的宽度
    }
  },
  mounted() {
    this.playWndHeight = this.$refs.playWndBox.clientHeight // 首次加载时的到父容器的高度
    this.playWndWidth = this.$refs.playWndBox.clientWidth // 首次加载时的到父容器的宽度
    this.$nextTick(() => {
      // 初始化摄像头
      this.initPlugin()
    })

    // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化
    window.addEventListener('resize', () => {
      if (oWebControl != null) {
        if (this.$refs.playWndBox)
          oWebControl.JS_Resize(this.$refs.playWndBox.clientWidth,         this.$refs.playWndBox.clientHeight)
      }
    })
  },
  methods: {
    // 创建播放实例
    initPlugin() {
      let that = this
      oWebControl = new window.WebControl({
        szPluginContainer: 'playWnd', // 指定容器id
        iServicePortStart: 15900, // 指定起止端口号,建议使用该值
        iServicePortEnd: 15909,
        szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
        cbConnectSuccess: () => {
          // 创建WebControl实例成功
          oWebControl
            .JS_StartService('window', {
              // WebControl实例创建成功后需要启动服务
              dllPath: './VideoPluginConnect.dll' // 值"./VideoPluginConnect.dll"写死
            })
            .then(
              function() {
                // 启动插件服务成功
                oWebControl.JS_SetWindowControlCallback({
                  // 设置消息回调
                  cbIntegrationCallBack: that.cbIntegrationCallBack
                })

                oWebControl.JS_CreateWnd('playWnd', 0,0).then(function() {
                  //JS_CreateWnd创建视频播放窗口,宽高可设定  默认设置为0 消除初始化闪白问题
                  that.init() // 创建播放实例成功后初始化
                })
              },
              function() {
                // 启动插件服务失败
              }
            )
        },
        cbConnectError: function() {
          // 创建WebControl实例失败
          oWebControl = null
          that.$message.warning('插件未启动,正在尝试启动,请稍候...')
          window.WebControl.JS_WakeUp('VideoWebPlugin://') // 程序未启动时执行error函数,采用wakeup来启动程序
          initCount++
          if (initCount < 3) {
            setTimeout(function() {
              that.initPlugin()
            }, 3000)
          } else {
            that.$message.warning('插件启动失败,请检查插件是否安装!')
          }
        },
        cbConnectClose: () => {
          // 异常断开:bNormalClose = false
          // JS_Disconnect正常断开:bNormalClose = true
          console.log('cbConnectClose')
          oWebControl = null
        }
      })
    },
    // 初始化
    init() {
      let that = this
      this.getPubKey(() => {
        var appkey = '28730366' //综合安防管理平台提供的appkey,必填
        var secret = this.setEncrypt('HSZkCJpSJ7gSUYrO6wVi') //综合安防管理平台提供的secret,必填
        var ip = '10.19.132.75' //综合安防管理平台IP地址,必填
        var playMode = 0 //初始播放模式:0-预览,1-回放
        var port = 443 //综合安防管理平台端口,若启用HTTPS协议,默认443
        var snapDir = 'D:\\SnapDir' //抓图存储路径
        var videoDir = 'D:\\VideoDir' //紧急录像或录像剪辑存储路径
        var layout = '1x1' //playMode指定模式的布局
        var enableHTTPS = 1 //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
        var encryptedFields = 'secret' //加密字段,默认加密领域为secret
        var showToolbar = 1 //是否显示工具栏,0-不显示,非0-显示
        var showSmart = 1 //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
        var buttonIDs = '0,16,256,257,258,259,260,512,513,514,515,516,517,768,769' //自定义工具条按钮
        // var toolBarButtonIDs = "2049,2304" // 工具栏上自定义按钮

        oWebControl
          .JS_RequestInterface({
            funcName: 'init',
            argument: JSON.stringify({
              appkey: appkey, //API网关提供的appkey
              secret: secret, //API网关提供的secret
              ip: ip, //API网关IP地址
              playMode: playMode, //播放模式(决定显示预览还是回放界面)
              port: port, //端口
              snapDir: snapDir, //抓图存储路径
              videoDir: videoDir, //紧急录像或录像剪辑存储路径
              layout: layout, //布局
              enableHTTPS: enableHTTPS, //是否启用HTTPS协议
              encryptedFields: encryptedFields, //加密字段
              showToolbar: showToolbar, //是否显示工具栏
              showSmart: showSmart, //是否显示智能信息
              buttonIDs //自定义工具条按钮
            })
          })
          .then(function(oData) {
            console.log(oData)
            oWebControl.JS_Resize(that.playWndWidth, that.playWndHeight) // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
            // 一进来就隐藏
            oWebControl.JS_HideWnd() // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
          })
      })
    },
    // 获取公钥
    getPubKey(callback) {
      oWebControl
        .JS_RequestInterface({
          funcName: 'getRSAPubKey',
          argument: JSON.stringify({
            keyLength: 1024
          })
        })
        .then(function(oData) {
          console.log(oData)
          if (oData.responseMsg.data) {
            pubKey = oData.responseMsg.data
            callback()
          }
        })
    },
    // RSA 加密
    setEncrypt(value) {
      var encrypt = new window.JSEncrypt()
      encrypt.setPublicKey(pubKey)
      return encrypt.encrypt(value)
    },
    // 回调的消息
    cbIntegrationCallBack(oData) {
      let { responseMsg: type, responseMsg: msg } = oData

      if (type === 'error') {
        console.log(type, msg, this.dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'))
      } else {
        console.log(type, msg, this.dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'))
      }
    },
    // 预览
    startPreview(cameraCode) {
      // 点击查询后显示
      oWebControl.JS_ShowWnd()
      var cameraIndexCode = cameraCode //获取输入的监控点编号值,必填
      console.log(cameraCode)
      var streamMode = 0 //主子码流标识:0-主码流,1-子码流
      var transMode = 1 //传输协议:0-UDP,1-TCP
      var gpuMode = 0 //是否启用GPU硬解,0-不启用,1-启用
      var wndId = -1 //播放窗口序号(在2x2以上布局下可指定播放窗口)

      cameraIndexCode = cameraIndexCode.replace(/(^\s*)/g, '')
      cameraIndexCode = cameraIndexCode.replace(/(\s*$)/g, '')

      oWebControl.JS_RequestInterface({
        funcName: 'startPreview',
        argument: JSON.stringify({
          cameraIndexCode: cameraIndexCode, //监控点编号
          streamMode: streamMode, //主子码流标识
          transMode: transMode, //传输协议
          gpuMode: gpuMode, //是否开启GPU硬解
          wndId: wndId //可指定播放窗口
        })
      })
    },
    // 停止全部预览
    stopAllPreview() {
      oWebControl.JS_RequestInterface({
        funcName: 'stopAllPreview'
      })
    },

    // 格式化时间
    dateFormat(oDate, fmt) {
        var o = {
            "M+": oDate.getMonth() + 1, //月份
            "d+": oDate.getDate(), //日
            "h+": oDate.getHours(), //小时
            "m+": oDate.getMinutes(), //分
            "s+": oDate.getSeconds(), //秒
            "q+": Math.floor((oDate.getMonth() + 3) / 3), //季度
            "S": oDate.getMilliseconds()//毫秒
        };
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (oDate.getFullYear() + "").substr(4 - RegExp.$1.length));
        }
        for (var k in o) {
            if (new RegExp("(" + k + ")").test(fmt)) {
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            }
        }
        return fmt;
    }
  },
  destroyed() { // 组件销毁后
    if (oWebControl != null) {
      oWebControl.JS_HideWnd() // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
      oWebControl.JS_RequestInterface({funcName: "destroyWnd"}) // 销毁当前播放的视频
      oWebControl.JS_Disconnect() // 断开与插件服务连接
    }
  }
}
</script>

注:由于本页面没有滚动条,不会出现因滚动条滚动导致窗口需要被遮住的情况,所以就没有添加scroll,如有滚动条,请参考demo文件下 demo_window_simple_preview.html 中的setWndCover事件文章来源地址https://www.toymoban.com/news/detail-402397.html

到了这里,关于vue+海康威视视频web插件开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3实现海康威视根据海康插件进行监控实时预览和回放功能

    因为我的文章已经写过基于vue实现海康web插件进行视频播放开箱即用文章,这个文章是利用 vite+vue3+js 进行编写的,大致内容跟vue2一样,拿过去能直接用。 至于我为什么要用js而不用ts,因为海康提供的三个脚本为js语言的,ts尝试过一次,我道行太浅,没搞明白。 这些代码是

    2024年02月05日
    浏览(56)
  • vue2 对接 海康摄像头插件 (视频WEB插件 V1.5.2)

    前言 海康视频插件v.1.5.2版本运行环境需要安装插件VideoWebPlugin.exe,对浏览器也有兼容性要求,具体看官方文档 对应下载插件 去海康官网下载插件 里面有dome等其他需要用到的 地址: 安装插件 打开下载的文件里的bin文件 安装一下VideoWebPlugin vue脚手架中集成插件 把官方资源

    2024年02月03日
    浏览(37)
  • web前端在vue中通过海康插件嵌入视频,实现实时预览以及视频回放功能

      首先第一步,在海康官网下海康视频插件下载到电脑中海康开放平台    然后新建一个组件,下面我直接把我封装好的组件代码拿出来,重要的地方我在代码中添加了注释   以上是封装的组件,下面是调用的方法   

    2024年02月03日
    浏览(36)
  • 海康威视web3.0在ie浏览器上一直提示安装插件的问题解决

    打开ie浏览器,点击右上角的齿轮。 64位的会显示64-bit信息 32位的就不会显示这个信息。  答案就是,前面解压出来有两个版本一个是32位,一个是64位,我们首先要确定的就是自己电脑ie浏览器的位数,用错了就会报这个问题,所以一定得先确认自己的ie位数,不然就要像我一

    2024年02月08日
    浏览(31)
  • vue2实现海康威视根据海康插件进行监控实时预览和回放功能,全套代码,开箱即用。

     这是一套拿到手就能直接用的根据海康提供的摄像机节点实时预览和回放的全步骤代码,开箱即用。  我的是基于vue2写的,vue3可以看我下一篇文章。 很多人在开发vue项目的时候,不知道怎么去开发视频实时预览和回放功能,然后一直查文档,再去看别人写的项目,就是无

    2023年04月15日
    浏览(53)
  • vue2使用rtsp视频流接入海康威视摄像头(纯前端)

    海康威视官方的RTSP最新取流格式如下: rtsp://用户名:密码@IP:554/Streaming/Channels/101 用户名和密码 IP就是登陆摄像头时候的IP(笔者这里IP是192.168.1.210) 所以笔者的rtsp流地址就是 rtsp://用户名:密码@192.168.1.210:554/Streaming/Channels/101 1.1关闭 萤石云的接入 1.2 调整视频编码为H.264 在此下载

    2024年04月26日
    浏览(41)
  • 记录对接海康威视摄像头web端实时预览:Linux+ffmpeg+nginx转换RTSP视频流(完整版实现)

            需求:web端实现海康摄像头实时预览效果         由于市面上大部分网络摄像头都支持RTSP协议视频流,web端一般无法直接使用RTSP实现视频预览,本篇使用ffmpeg对视频流进行转换,最终实现web端实时预览。         工具介绍:ffmpeg、nginx、vue         介

    2024年01月25日
    浏览(43)
  • 海康威视摄像头二次开发_云台控制_视频画面实时预览(基于Qt实现)

    需求:需要在公司的产品里集成海康威视摄像头的SDK,用于控制海康威视的摄像头。 拍照抓图、视频录制、云台控制、视频实时预览等等功能。 开发环境: windows-X64(系统) + Qt5.12.6(Qt版本) + MSVC2017_X64(使用的编译器) 海康威视提供了 设备网络SDK ,设备网络SDK是基于设备私有网

    2024年02月13日
    浏览(36)
  • vue项目引用海康视频插件(web1.5),el-date-picker下拉选择时间面板会被遮盖问题解决。

    一、海康插件浮窗的层级,会把项目中时间控件中的时间选择面板挡住,导致时间面板显示不全,无法选择时间。如图所示: 二、解决办法:调用API中的JS_ JS_CuttingPartWindow(iLeft, iTop, iWidth, iHeight )方法, 三、效果图 四、API接口文档 大致意思就是当点击时间控件出现时间选择

    2024年02月11日
    浏览(27)
  • 解决海康威视监控安装插件后依然预览不了

    故障表现: 多次重装插件依然浏览不了监控画面,一直显示以下图片信息,提示安装插件 原因: 监控探头版本老旧,画面不能在新版浏览器上播放,两者不能兼容 解决办法: 1.IE浏览器 点开设置,找到“兼容性视图设置” 将监控画面网址添加入框中,点击确定,再点关闭

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包