eventsource 实现手机上传,电脑接收

eventsource 支持服务器主动推送信息给客户端;不支持双向推送。
//过程就是 pc端点击扫描按钮 请求到一个唯一id,用id及其他需要的参数通过一个接口让后端生成一个二维码返回给前台,前台拿到二维码数据展示给用户并同时开启eventsource服务(后端会根据这个id每隔一段时间去查询某个表中是否有这个id对应的记录 如果有就推送给前台,没有就过一段时间继续查), 手机扫描跳转到一个上传文件页面,手机上传完毕后提交需要的数据给后端,后端将数据以及这个唯一id生成一条记录用于source接口查询;

<template>
  <div style="margin-left:10px;width:50%;">
      <p style="line-height:40px"><el-button type="primary" class="smallbtn" style="font-size: 12px;" @click="getcode">扫描上传</el-button></p>
      <el-dialog title="扫描上传" :close-on-click-modal="false"  :modal="false" id="code_dialog" center @close='setCodedata' :visible.sync="code_dialog" width="800px">
        <p style="text-align:center"><img :src="codeImg" alt="" style="margin:0 auto"></p>
        <span slot="footer" class="dialog-footer" style="padding:0 24px;">
          <el-button style="width:120px;" ref="closebtn" @click="closecode">关闭</el-button>
        </span>
      </el-dialog>
      <ul>
        <li v-for="(item,index) in sendFileArr" :key="index">
          <span class="l_span" :title="item.fileName">{
   
   { item.fileName }}</span>  <span class="delbt" @click="del(index)" style="font-size:12px;margin-left:20px;cursor:pointer">删除</span>
        </li>
      </ul>
  </div>
</template>

<script>
import {mapState, mapGetters} from 'vuex'
export default {
  props:['filetypeArr','uploadurl','clearfn','htref'], //
  data () {
    return {
        code_dialog:false,
        codeImg:'',
        openbool:false,
        sendFileArr:[]
    }
  },

  components: {},
  watch:{  
  //这里通过弹窗开启关闭时更改值,来置空组件数据
    clearfn:function(val){
       this.sendFileArr=[]
       this.$emit('sendsuccess',[])
    }
  },
  computed: {
    userId:function(){
      return localStorage.getItem('session_id')||''
    }
  },

  methods: {
    // 获取唯一id
    getcodeid(){
      return new Promise((resolve,reject)=>{
        this.axios.post('xxxxxx').then(res=>{
           if(res.data.code===200){
              resolve(res.data.data.codeid)
           }else{
              this.$message.error('获取二维码失败')   //生成不了id就不去生成二维码了
           }
        }).catch(err=>{
           this.$message.error('获取二维码失败')
        })
      })
    },
    setCodedata(){
      this.codeImg=''
    },
    // 获取二维码图片
    async getcode(){
        if(typeof EventSource==='undefined'){
          this.$message.error('当前浏览器不支持手机传送数据到电脑功能,请更换浏览器或者使用电脑上传')
          return
        } 
        let codeid=await this.getcodeid()
       //如果参数是汉字类对象数组,这么写:encodeURIComponent(encodeURIComponent(JSON.stringify(sendtypeArr)))
        this.axios.get(`xxxxx?a=xxxx}`, {
              responseType: 'arraybuffer' // 指定返回数据的格式为blob   
            }
          ).then(res => {
           //拼成src
            this.codeImg = 'data:image/png;base64,' + btoa(new Uint8Array(res.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
            this.code_dialog=true
            this.opensource(codeid)
          }).catch(err => {
            this.$message.error('获取二维码失败')
          })
    },
    // 开启eventsource  // 
    opensource(codeid){
        this.openbool=true
        let that=this
        //因为需要在点击页面某个按钮来关闭接收服务,直接在这里申明变量的话在其他方法中访问不到,所有把source实例挂到了当前方法的内部属性,这里的this.opensource就是我们当前定义的methods方法名
        this.opensource.source = new EventSource(`${this.api.basePath}/Api/contract/uploadmessage/getDate?codeid=${codeid}&bookNumber=${this.bookNumber}&token=${this.userId}`)
        this.opensource.source.onopen = function (event) { // 与服务器连接成功回调
          console.log('成功与服务器连接')
        }
        this.opensource.source.onmessage = function (event) { // 监听未命名事件
          console.log('接收到数据')
          if(event.data){
            that.openbool=false
            that.$emit('sendsuccess',JSON.parse(event.data))
            that.sendFileArr=JSON.parse(event.data)
            that.closecode()
            that.opensource.source.close()
            console.log('服务器连接关闭')
          } 
        }
        this.opensource.source.onerror = function (error) { // 监听错误
          console.log('错误')
        }
        // console.log(this.opensource.source.readyState) //服务状态,可查看eventsource api
    },
    // 关闭弹窗 关闭eventsource
    closecode:function(){
        // console.log(this.opensource.source.readyState)
        // 如果已接收到数据,直接关闭弹窗
        if(!this.openbool){
          this.code_dialog=false
          return
        }
        // 服务正在开启 则openbool改成false  关闭服务 关闭弹窗
        this.$confirm('确定要关闭吗',{
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'}).then(()=>{
            // console.log(this.opensource.source.close)
            this.opensource.source.close()
            this.opensource.source=null
            this.openbool=false
            this.code_dialog=false
        }).catch(()=>{
          this.$message.success('已取消')
        })
    },
    del(index){   //可删除
      this.sendFileArr.splice(index,1)
      this.$emit('sendsuccess',this.sendFileArr)
    }
  },

  mounted(){

  }

}
</script>
<style lang='scss' scoped>
ul{
  width:100%;
  margin-left:10px;
  // margin-top:10px;
  li{
    display:flex;
    justify-content: space-between;
    align-items: center;
    line-height:26px;
    margin-top:5px;
    .l_span{
      width:80%;
      overflow: hidden;
      text-overflow:ellipsis;
      white-space: nowrap;
    }
    
  }
  li:nth-of-type(1){
    margin-top:10px
  }
  li:hover{
      background-color: #F5F7FA;
    .delbt{
      color:#409EFF
    }  
  }

}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_43392545/article/details/105933550
今日推荐