最近接了个项目需求,给设备配置语音加弹框告警。用户登录项目后不管在哪个页面,有告警就全局在右下角消息弹框加语音播报,下面浅介绍下我在开发中的流程以及遇到的坑!!!

1、首先项目中安装speak-tts语音播报插件。

npm install speak-tts

2、创建一个全局的 speech.js文件,文件中引入插件并初始化后导出。
因为可能会一直读多条消息,防止初始化多个Speech对象,在全局api中初始化一个对象,方便播报的时候调用。

import Speech from 'speak-tts'
const speech=new Speech()
export default speech 

3、在项目点击登录按钮后调用全局的语音播报方法。
由于浏览器之间有安全限制,用户不主动触发语音播报方法, 语音播报不会主动发出声音,故在项目的登录处触发方法。

3.1、首先引入封装好的js文件

import Speech from '@/utils/speech'

3.2、在登录点击方法中调用speech方法的语言、语速等各种参数。

    initSpeech(){
      Speech.setLanguage('zh-CN')
      Speech.init({
        volume: 0.6, // 音量0-1
        lang: "zh-CN", // 语言
        rate: 2, // 语速1正常语速,2倍语速就写2
        pitch: 1, // 音调
        voice: "Microsoft Yaoyao - Chinese (Simplified, PRC)",
      })    
    }

4、在登录后的vue页面资源的首加载项,即页面入口文件处编写弹框样式及告警信息的接收等功能(我开发的项目入口文件是AppMain.vue 文件)

4.1、首先新建一个项目右下角可放多个全局弹框的div,我此处使用的是card样式

    <div class="alarmmodel" v-if=popupList.length>
      <el-card class="box-card" shadow="always" v-for="(item, index) in popupList" :key="index">
        <div slot="header" class="clearfix">
          <span v-if="item.alertLevel == 1" style="color: rgb(221, 39, 48)">红色告警</span>
          <span v-else-if="item.alertLevel == 2" style="color:rgb(255, 140, 0)">橙色告警</span>
          <span v-else-if="item.alertLevel == 3" style="color: rgb(255, 215, 0)">黄色告警</span>
          <el-button style="float: right; padding: 3px 0" type="text" @click='popupSubmit(item, index)'>确定</el-button>
        </div>
        <div class="text item">
          {{ item.msg }}
        </div>
      </el-card>
    </div>

4.2、项目中引入封装好的js文件

import Speech from '@/utils/speech'

4.3、data中定义四个对象,分别是websocket的初始化对象,websoket地址及播报的弹框数据和心跳监测对象

  data() {
    return {
      heartbeatTimer: null, // 监测心跳
      popupList: [],  // 存储弹框数据
      pathpopup: 'wss://www.aihs.dev.huanhuigroup.cn/dev/alert-service/websocket/voice',   // websocket链接地址
      socketpopup: null,  // 初始化websocket对象
    }
  },

4.4、mounted中调用初始化的方法 this.initPopupsoket()

 mounted() {
    this.popupList = [];
    this.initPopupsoket()
  },

4.5、编写链接websocket的方法initPopupsoket,接收弹框及语音数据,并进行前后端心跳检测。

 initPopupsoket() {
      if (typeof (WebSocket) === "undefined") {
        alert("您的浏览器不支持socket")
      } else {
        this.socketpopup = new WebSocket(this.pathpopup)
        this.socketpopup.onopen = this.openPopup
        this.socketpopup.onerror = this.errorPopup
        this.socketpopup.onmessage = this.getMessagepopup
      }
    },
   openPopup() {
      console.log("socketpopup连接成功")
      this.startHeartbeat()   // 添加心跳监测,用来防止websocket断开
    },
    startHeartbeat() {// 发送心跳消息
      var _this = this;
      if (_this.heartbeatTimer == null) {
        _this.heartbeatTimer = setInterval(function () {
          console.log('监测心跳')
          _this.socketpopup.send("ping");
        }, 10000);
      }
    },
    stopHeartbeat() { // 停止心跳
      if (this.heartbeatTimer !== null) {
        clearInterval(this.heartbeatTimer);
        this.heartbeatTimer = null;
      }
    },
    errorPopup() {
      console.log("1连接错误")
    },
    getMessagepopup(msg) {
      // console.log('1接受消息数据', msg.data)
      this.popupList.push(JSON.parse(msg.data)) // 将推送的单条数据存起来显示多个弹框,在用户点击确定后消除此条弹框
      this.startSpeech(JSON.parse(msg.data).msg) // 将数据中的告警传给播报的对象
    },
    closePopup() {
      console.log("socketpopup已经关闭")
      //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。  
      window.onbeforeunload = function () {
        this.socketpopup.close();
      }
    },

4.6、语音播报弹框中的数据,每推一条播报一条(注:此处是后端单条数据推送,推送一条播报一条,只读最新的,但是弹框需要显示登录网站后的全部数据,需要用户手动点击确定后弹框消失,故在消息推送后调用语音播报,并将数据存到数组显示弹框。若考虑到数据较多,告警还没读完数据就推送过来,可考虑遍历告警数据进行播报,就不在接收到消息推送后调用此方法)

    startSpeech(text) {
      Speech.speak({
        text: text,
        listeners: {
          //开始播放
          onstart: () => {
            console.log("Start utterance")
          },
          //判断播放是否完毕
          onend: () => {
            console.log("End utterance");
          },
          //恢复播放
          onresume: () => {
            console.log("Resume utterance")
          },
        },
      }).then(() => {
        console.log("读取成功")
      })
    },

4.7、点击确认后消除弹框告警

popupSubmit(item, index) {
      console.log('点击告警弹框', item, index)
      updateCurrentAlertsStatus(item.id, 'READ').then(() => {
        this.$message.success('操作成功!');
        this.popupList.splice(index, 1);
      })
        .catch(() => {
          this.$message.error('操作失败!')
        })
    }

5、页面关闭后清空掉各种方法及数据

 beforeDestroy() {
    this.speech.cancel();  // 取消播放      
    this.speech = null;
    console.log('离开页面', this.speech)
    this.socketpopup.onclose = this.closePopup
  },

遇到的坑:
1、由于浏览器安全限制,用户不主动触发语音告警不会主动出声音,故解决方法是初始化一个全局的
speech-tts方法,在点击登录的时候调用,详情见上
2、websocket链接的时候,如果域名是https的话websocket请求地址需是wss,要不会报错

以上就是我的开发流程,具体有不明白的留言给我!!

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐