原生微信小程序实现语音转文字搜索---同声传译

效果展示

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/23257ce3b6c149a1bb54fd8bc2a05c68.png#pic_center

注意:引入同声传译组件请看这篇文章

1.search.wxml

javascript 复制代码
<view class="search-page">
    <navigation-bar title="搜索"  color="#000" background="#fff"  bind:back="onNavigationBack"></navigation-bar>
  <view class="search-bar">
    <input class="search-input" value="{{keyword}}"  placeholder="请输入搜索名称"  focus="{{true}}" 
    bindinput="onInput" 
   />
    <image wx:if="{{!isPressed}}" src="点击前的图标状态" class="search-icon" style="width: 50rpx;height: 50rpx;" bindtap="onMicTap"/>
    <image wx:else  src="点击后的图标状态" style="width: 40rpx;height: 40rpx;" bindtap="closeOnMicTap"  class="search-icon" />
  </view>
  <!-- 搜索结果区域 -->
  <!-- <view class="search-result-placeholder" wx:if="{{productList.length==0}}">
  暂无数据
  </view> -->
    <!-- 列表 -->
    <view class="product-list" style="padding-bottom:230rpx;">
            <view class="product-card" wx:for="{{productList}}" wx:key="title" bind:tap="onsubCategoriesItemTap"  data-type="{{item.type}}" data-id="{{item.id}}">
                <image class="product-img" src="{{item.image}}" mode="aspectFit"></image>
                <view class="product-info">
                    <view class="product-title">{{item.productName}}</view>
                    <image class="product-tag" src="{{item.label}}" mode="widthFix"></image>
                    <view class="product-desc">{{item.productInfo}}</view>
                </view>
            </view>
        </view>
</view> ```
1.search.ts

```javascript
import { get, post } from '../../api/request';
//import { share } from '../../utils/util';
//引入插件:微信同声传译
const plugin = requirePlugin('WechatSI');
//获取全局唯一的语音识别管理器recordRecoManager
const manager = plugin.getRecordRecognitionManager();
// const shareData  =  wx.getStorageSync("shareData")
Page({
  data: {
    resultStr:null,
    keyword:"",//搜索词
    msgText: 1, //1默认初始化  2对话进行中   3结束对话  4对话出现问题
    // recordState: false, //麦克风默认关闭状态
    isFlag: false, //是否点击录音到获取结果之间状态
    islongPress: false, //是否长按
    isPressed: false,
    normalIcon: 'microphone.png', // 正常状态图标路径
    pressedIcon: 'prohibit.png', // 按下状态图标路径
    isplay: true,
    haveflag: false, //防止重复点击
    // keyword: '',
    currentTab: 0, // 0:产品科普 1:科普图文
    productList: [],

  },
  onLoad(){
    //识别语音
 this.initRecord();
  },
  cleanup() {
    if (manager) {
      // 停止录音并移除所有监听
      manager.stop();
      manager.onStart(null);
      manager.onStop(null);
      manager.onError(null);
      // manager = null;
      console.log('录音管理器已销毁');
      // 显示Toast(3秒后自动关闭)
      this.setData({
        isPressed:false,
        islongPress:false,
        isFlag:false,
        msgText:1,
        keyword:"",
        resultStr:null,
        isplay:true,
        haveflag:false
      })
    }
  },
   //语音  点击说话
   onMicTap() {
    // 判断是否获取录音权限
    // console.log("是否关闭语音",this.data.haveflag)
    if (this.data.haveflag) { //true 请先结束语音
      wx.showToast({
        title: '请先关闭语音!',
        icon: 'none',
        duration: 2000
      })
      return false
    }
    // 当前正在识别语音,还没结束上一次识别,请先关闭再进行录音
    if (this.data.isFlag) { //true 请先结束语音
      wx.showToast({
        title: '请先关闭语音!',
        icon: 'none',
        duration: 2000
      })
      return false
    }
    this.setData({
      islongPress: true,
      isplay: true
    })
    // var flag = Number(e.currentTarget.dataset.flag);
    this.setData({
      // recordState: true, //录音状态
      // flag: true,
      // touchstart: true, //按下
      isPressed:true,
      msgText: 2, //初始化状态
    })
    // 语音开始识别
    manager.start({
      lang: 'zh_CN', // 识别的语言
    })

  },
   //语音  --点击结束
   closeOnMicTap() {
    if (!(this.data.islongPress)) { //如果是长按执行下面内容
      return false
    }
    wx.showLoading({
      title: '正在思考...',
      icon: 'none',
    })
    if (this.data.haveflag) { //true 请先结束语音
      wx.hideLoading();
      // wx.showToast({
      //   title: '请先关闭语音111!',
      //   icon: 'none',
      //   duration: 2000
      // })
      return false
    }
    this.setData({
      // touchstart: false,
      isPressed:false,
      // recordState: false,
      islongPress: false, //长按初始状态
      isFlag: true, //判断从松手到识别录音期间状态
      haveflag: true
    })
    // 语音结束识别
    manager.stop();
  },
   //识别语音 -- 初始化
   initRecord() {
    const that = this;
    // 有新的识别内容返回,则会调用此事件
    manager.onRecognize = function (res:any) {
      console.log("有新的识别内容返回,则会调用此事件")
    }
    // 正常开始录音识别时会调用此事件
    manager.onStart = function (res:any) {
      console.log("成功开始录音识别", res)
      that.setData({
        // annimationFlag:true
      })
    }
    //识别结束事件
    manager.onStop = function (res:any) {
      that.setData({
        resultStr:res
      })
      if(!res){//证明可能已经销毁
        return false
      }
      if (!that.data.isplay) {
        wx.showToast({
          title: "请说话",
          icon: 'none',
          // image: 'no_voice.png',
          duration: 1000,
          success: function (res) {
            that.setData({
              haveflag: false,
            })
          },
          fail: function (res) {
            console.log(res);
          }
        });
        return false
      }
      // console.log("过来????")
      if (res.result == '') {
        wx.hideLoading();
        // wx.showToast({
        //   title: '听不清楚,请重新说一遍!',
        //   icon: 'none',
        //   duration: 2000
        // })
        that.showRecordEmptyTip()
        return;
      } else {
        that.setData({
          keyword: res.result,
          msgText: 2, //正在对话
          // resultobj: {
          //   result: res.result,
          //   annimationFlag: true
          // }
        })
        // console.log("调用·接口",that.data.keyword)
        //  调用接口
        that.onSearch();
      }
    }
    // 识别错误事件
    manager.onError = function (res:any) {
      console.log("error msg", res);
      if(!res){
        return false
      }
      wx.hideLoading();
      // wx.showToast({
      //   icon: "none",
      //   title: '请重新开始~'
      // })
      that.setData({
        haveflag: false,
        msgText: 1,
        isPressed:false,
        // annimationFlag: false,
        isFlag: false, //当前录制语音识别状态
      })
    }
  },
  showRecordEmptyTip: function () {
    this.setData({
      msgText: 1, //初始化
      haveflag: false,
      isFlag: false,
    })
    if(!this.data.resultStr){
      return false
    }
    // console.log("进来了,啊",this.data.resultStr)
    wx.showToast({
      title: "请说话",
      icon: 'none',
      // image: 'no_voice.png',
      duration: 1000,
      success: function (res) {},
      fail: function (res) {
        console.log(res);
      }
    });
  },
  // 根据wx.getSetting判断用户是否打开了录音权限,如果没有打开,则通过wx.authorize,向用户打开授权请求,如果用户拒绝了,就给用户打开授权设置页面。
  getSeeting(type:any) {
    // wx.showLoading({
    //   title: '获取录音权限',
    //   icon: 'none',
    //   mask: true
    // })
    const _this = this
    wx.getSetting({ //获取用户当前设置
      success: res => {
        // wx.hideLoading();
        // console.log('获取权限', res);

        if (res.authSetting['scope.record']) { //查看是否授权了录音设置
          // console.log('获取权限1111');
          const authset = wx.setStorageSync('AUTHSETTING', true);
          _this.setData({
            authsetting: true
          })
          if (type == 2) {
            wx.showToast({
              title: '获取录音权限成功,点击重新开始!',
              icon: 'none',
              duration: 2000
            })
          }
        } else {
          // 用户还没有授权,向 用户发起授权请求
          wx.authorize({ //提前向用户发起授权请求,调用后会立刻弹窗询问用户是否同意授权小程序使用某项功能或获取用户的某些数据,但不会实际调用对应接口
            scope: 'scope.record',
            success() { //用户同意授权摄像头
              // console.log("同意授权");
              // wx.showToast({
              //   title: '获取录音权限成功',
              //   icon: 'none',
              //   duration: 2000
              // })

            },
            fail() { //用户不同意授权摄像头
              _this.openSetting()
            }
          })
        }
      },
      fail() {
        // console.log('获取用户授权信息失败');
        wx.showToast({
          title: '获取权限失败',
          icon: 'none',
          duration: 2000
        })
      }
    })
  },
  openSetting() {
    wx.openSetting({
      success(res) {
        console.log(res);
        if (res.authSetting['scope.record']) {
          console.log('用户已经同意录音权限');
          // 在这里可以再次执行录音操作或者其他逻辑
        } else {
          console.log('用户依然拒绝录音权限');
          // 可以提示用户继续操作的限制或者做其他处理
        }
      },
      fail() {
        console.log('打开设置页面失败');
      },
    });
  },
  onNavigationBack(e:any) {
    console.log('返回按钮被点击',e);
    this.cleanup();
    // 执行自定义逻辑
    wx.navigateBack({
      delta: e.detail
    })
  },
  //==========================================================================
  onInput(e:any) {
  
    this.setData({ keyword: e.detail.value });
    if(e.detail.value){
      this.onSearch()
    }else{
      this.setData({productList:[]})
    }
    // console.log("拿到值",this.data.keyword)
  },
  onSearch() {
    // TODO: 搜索逻辑
    let cleanedText =this.data.keyword;
    if(cleanedText){
     cleanedText = cleanedText.replace(/[.,\/#!?;:,。、;:?!]/g, '');
    }
    get(`product/search`, {productKeyword:cleanedText}, { intercept: true }).then((res: any) => {
      wx.hideLoading();
      // 语音重置
      if(this.data.isplay){
        this.setData({
          isFlag: false,
          msgText: 1,
          haveflag:false
        })
      }
      console.log("没有分页",res);
      this.setData({
        productList: res.content,
    })
  })
  },
   // 产品列表点击
   onsubCategoriesItemTap(e: any) {
    wx.navigateTo({ url: `/pages/product-detail/product-detail?id=${e.currentTarget.dataset.id}` });

},
}); 

3.search.wxss

javascript 复制代码
.search-page { width: 100%; min-height: 100vh; }
.search-bar { display: flex; align-items: center; background: #fff; border-radius: 30rpx; padding: 16rpx 24rpx; box-shadow: 0 2rpx 8rpx #f5e9c7; }
.search-input { flex: 1; border: none; background: transparent; font-size: 28rpx; color: #222; outline: none; }
.search-icon { width: 36rpx; height: 36rpx; margin-left: 16rpx; }
.search-result-placeholder { height: 400rpx; background: #f5f5f5; border-radius: 20rpx; margin-top: 40rpx; text-align: center; line-height: 400rpx; color: #bbb; } 
/* 搜索列表展示 */
.product-list { margin: 30rpx 10px; padding-bottom: 100rpx;  }
.product-card { display: flex; align-items:center; border-top: 3px solid #fff; border-radius: 20rpx;
   /* margin-bottom: 32rpx;  */
   padding: 24rpx 32rpx;    background: #FAF6E4; }
.product-img { width: 160rpx; height: 160rpx; border-radius: 12rpx; margin-right: 32rpx; background: #fff;  padding: 20rpx 10rpx; }
.product-info { flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center; }
.product-title { font-size: 36rpx; font-weight: bold; color: #222; margin-bottom: 12rpx; }
.product-tag {     display: inline-block; width: 110rpx; margin-top: -5rpx; }
.product-desc { font-size: 20rpx; color: #222; line-height: 1.6; word-break: break-all;  margin-top: 10rpx;}```
4.search.json

```javascript
{
  "navigationBarTitleText": "搜索",
  "navigationStyle": "custom"
} ```
相关推荐
壹立科技6 小时前
Java源码构建智能名片小程序
java·开发语言·小程序
qingyingWin8 小时前
原生微信小程序研发,如何对图片进行统一管理?
前端·微信小程序
shadouqi9 小时前
问题1:uniapp在pages样式穿刺没有问题,在components组件中样式穿刺小程序不起效果
小程序·uni-app
韩召华9 小时前
uniapp实现微信小程序导航功能
微信小程序·uni-app·notepad++
前端Hardy11 小时前
10 分钟搞定婚礼小程序?我用 DeepSeek 把同学的作业卷成了范本!
前端·javascript·微信小程序
2501_9159090617 小时前
iOS电池寿命与App能耗监测实战 构建完整性能监控系统
android·ios·小程序·https·uni-app·iphone·webview
weixin_lynhgworld19 小时前
旧物回收小程序:科技赋能,让旧物回收焕发生机
科技·小程序
此心光明事上练1 天前
微信小程序组件发布为 npm 包的具体步骤
微信小程序·小程序·npm
Byte_Me1 天前
从东南亚出发:小程序容器技术如何助力 App 快速打入全球市场?
小程序