鸿蒙OSUniApp 实现的语音输入与语音识别功能#三方框架 #Uniapp
UniApp 实现的语音输入与语音识别功能
最近在开发跨平台应用时,客户要求添加语音输入功能以提升用户体验。经过一番调研和实践,我成功在UniApp项目中实现了语音输入与识别功能,现将过程和方法分享出来,希望对有类似需求的开发者有所帮助。
为什么需要语音输入功能?
随着移动设备的普及,语音交互已成为一种高效的人机交流方式。与传统的文字输入相比,语音输入具有以下优势:
- 操作便捷:免去键盘敲击,尤其适合单手操作或行走等场景
- 输入高效:语音输入速度通常快于手动输入
- 提升体验:为特定人群(如老年人、视障人士)提供便利
- 解放双手:适用于驾车、做家务等无法腾出手打字的场景
在商业应用中,语音输入可以显著降低用户的操作门槛,提高转化率和用户留存。
技术方案选型
在UniApp环境中实现语音识别,主要有三种方案:
- 使用原生插件:调用各平台的原生语音识别能力
- 对接云服务:接入第三方语音识别API(如百度、讯飞等)
- Web API:在H5平台利用Web Speech API
经过对比和测试,我最终采用了混合方案:
- 在App平台使用原生插件获取最佳体验
- 在微信小程序使用微信自带的语音识别能力
- 在H5平台尝试使用Web Speech API,不支持时降级为云服务API
实现步骤
1. App端实现(基于原生插件)
首先需要安装语音识别插件。我选择了市场上比较成熟的speech-baidu插件,这是基于百度语音识别SDK封装的UniApp插件。
安装插件后,在manifest.json中配置:
"app-plus": {"plugins": {"speech": {"baidu": {"appid": "你的百度语音识别AppID","apikey": "你的API Key","secretkey": "你的Secret Key"}}},"distribute": {"android": {"permissions": ["<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>","<uses-permission android:name=\"android.permission.INTERNET\"/>"]}}
}
接下来创建语音识别组件:
<template><view class="voice-input-container"><view class="voice-btn" :class="{ 'recording': isRecording }"@touchstart="startRecord" @touchend="stopRecord"@touchcancel="cancelRecord"><image :src="isRecording ? '/static/mic-active.png' : '/static/mic.png'" mode="aspectFit"></image><text>{{ isRecording ? '松开结束' : '按住说话' }}</text></view><view v-if="isRecording" class="recording-tip"><text>正在聆听...</text><view class="wave-container"><view v-for="(item, index) in waveItems" :key="index" class="wave-item":style="{ height: item + 'rpx' }"></view></view></view></view>
</template><script>
// #ifdef APP-PLUS
const speechPlugin = uni.requireNativePlugin('speech-baidu');
// #endifexport default {name: 'VoiceInput',data() {return {isRecording: false,timer: null,waveItems: [10, 15, 20, 25, 30, 25, 20, 15, 10]}},props: {lang: {type: String,default: 'zh' // zh: 中文, en: 英文},maxDuration: {type: Number,default: 60 // 最长录音时间,单位秒}},methods: {startRecord() {if (this.isRecording) return;// 申请录音权限uni.authorize({scope: 'scope.record',success: () => {this.isRecording = true;this.startWaveAnimation();// #ifdef APP-PLUSspeechPlugin.start({vadEos: 3000, // 静音超时时间language: this.lang === 'zh' ? 'zh-cn' : 'en-us'}, (res) => {if (res.errorCode === 0) {// 识别结果this.$emit('result', res.result);} else {uni.showToast({title: `识别失败: ${res.errorCode}`,icon: 'none'});}this.isRecording = false;this.stopWaveAnimation();});// #endif// 设置最长录制时间this.timer = setTimeout(() => {if (this.isRecording) {this.stopRecord();}}, this.maxDuration * 1000);},fail: () => {uni.showToast({title: '请授权录音权限',icon: 'none'});}});},stopRecord() {if (!this.isRecording) return;// #ifdef APP-PLUSspeechPlugin.stop();// #endifclearTimeout(this.timer);this.isRecording = false;this.stopWaveAnimation();},cancelRecord() {if (!this.isRecording) return;// #ifdef APP-PLUSspeechPlugin.cancel();// #endifclearTimeout(this.timer);this.isRecording = false;this.stopWaveAnimation();},// 波形动画startWaveAnimation() {this.waveAnimTimer = setInterval(() => {this.waveItems = this.waveItems.map(() => Math.floor(Math.random() * 40) + 10);}, 200);},stopWaveAnimation() {clearInterval(this.waveAnimTimer);this.waveItems = [10, 15, 20, 25, 30, 25, 20, 15, 10];}},beforeDestroy() {this.cancelRecord();}
}
</script><style scoped>
.voice-input-container {width: 100%;
}.voice-btn {width: 200rpx;height: 200rpx;border-radius: 100rpx;background-color: #f5f5f5;display: flex;flex-direction: column;align-items: center;justify-content: center;margin: 0 auto;
}.voice-btn.recording {background-color: #e1f5fe;box-shadow: 0 0 20rpx rgba(0, 120, 255, 0.5);
}.voice-btn image {width: 80rpx;height: 80rpx;margin-bottom: 10rpx;
}.recording-tip {margin-top: 30rpx;text-align: center;
}.wave-container {display: flex;justify-content: center;align-items: flex-end;height: 80rpx;margin-top: 20rpx;
}.wave-item {width: 8rpx;background-color: #1890ff;margin: 0 5rpx;border-radius: 4rpx;transition: height 0.2s;
}
</style>
2. 微信小程序实现
微信小程序提供了原生的语音识别API,使用非常方便:
// 在小程序环境下的代码
startRecord() {// #ifdef MP-WEIXINthis.isRecording = true;this.startWaveAnimation();const recorderManager = wx.getRecorderManager();recorderManager.onStart(() => {console.log('录音开始');});recorderManager.onStop((res) => {this.isRecording = false;this.stopWaveAnimation();// 将录音文件发送到微信后台识别wx.showLoading({ title: '识别中...' });const { tempFilePath } = res;wx.uploadFile({url: 'https://api.weixin.qq.com/cgi-bin/media/voice/translatecontent',filePath: tempFilePath,name: 'media',formData: {access_token: this.accessToken,format: 'mp3',voice_id: Date.now(),lfrom: this.lang === 'zh' ? 'zh_CN' : 'en_US',lto: 'zh_CN'},success: (uploadRes) => {wx.hideLoading();const data = JSON.parse(uploadRes.data);if (data.errcode === 0) {this.$emit('result', data.result);} else {uni.showToast({title: `识别失败: ${data.errmsg}`,icon: 'none'});}},fail: () => {wx.hideLoading();uni.showToast({title: '语音识别失败',icon: 'none'});}});});recorderManager.start({duration: this.maxDuration * 1000,sampleRate: 16000,numberOfChannels: 1,encodeBitRate: 48000,format: 'mp3'});// #endif
},stopRecord() {// #ifdef MP-WEIXINwx.getRecorderManager().stop();// #endif// ...与App端相同的代码...
}
需要注意的是,微信小程序的语音识别需要获取access_token,这通常需要在后端实现并提供接口。
3. H5端实现
在H5端,我们可以利用Web Speech API来实现语音识别,当浏览器不支持时则降级为云服务API:
startRecord() {// #ifdef H5this.isRecording = true;this.startWaveAnimation();// 检查浏览器是否支持Speech Recognitionif ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;this.recognition = new SpeechRecognition();this.recognition.lang = this.lang === 'zh' ? 'zh-CN' : 'en-US';this.recognition.continuous = false;this.recognition.interimResults = false;this.recognition.onresult = (event) => {const result = event.results[0][0].transcript;this.$emit('result', result);};this.recognition.onerror = (event) => {uni.showToast({title: `识别错误: ${event.error}`,icon: 'none'});};this.recognition.onend = () => {this.isRecording = false;this.stopWaveAnimation();};this.recognition.start();} else {// 不支持Web Speech API,调用云服务APIthis.useCloudSpeechAPI();}// #endif// 设置最长录制时间this.timer = setTimeout(() => {if (this.isRecording) {this.stopRecord();}}, this.maxDuration * 1000);
},stopRecord() {// #ifdef H5if (this.recognition) {this.recognition.stop();}// #endif// ...与App端相同的代码...
},useCloudSpeechAPI() {// 这里实现降级方案,调用后端接口进行语音识别uni.chooseFile({count: 1,type: 'file',extension: ['.mp3', '.wav'],success: (res) => {const tempFilePath = res.tempFilePaths[0];// 上传音频文件到后端进行识别uni.uploadFile({url: this.apiBaseUrl + '/speech/recognize',filePath: tempFilePath,name: 'audio',formData: {lang: this.lang},success: (uploadRes) => {const data = JSON.parse(uploadRes.data);if (data.code === 0) {this.$emit('result', data.result);} else {uni.showToast({title: `识别失败: ${data.msg}`,icon: 'none'});}},complete: () => {this.isRecording = false;this.stopWaveAnimation();}});}});
}
4. 通用接口封装
为了让调用方便,我封装了一个统一的API:
// 在 utils/speech.js 中
const Speech = {// 开始语音识别startRecognize(options) {const { lang = 'zh', success, fail, complete } = options;// #ifdef APP-PLUSconst speechPlugin = uni.requireNativePlugin('speech-baidu');speechPlugin.start({vadEos: 3000,language: lang === 'zh' ? 'zh-cn' : 'en-us'}, (res) => {if (res.errorCode === 0) {success && success(res.result);} else {fail && fail(res);}complete && complete();});return {stop: () => speechPlugin.stop(),cancel: () => speechPlugin.cancel()};// #endif// #ifdef MP-WEIXIN// 微信小程序实现逻辑// ...// #endif// #ifdef H5// H5实现逻辑// ...// #endif}
};export default Speech;
实战案例:聊天应用中的语音输入
现在,我们来看一个实际应用场景 - 在聊天应用中添加语音输入功能:
<template><view class="chat-input-container"><view class="chat-tools"><image :src="isVoiceMode ? '/static/keyboard.png' : '/static/mic.png'" @tap="toggleInputMode"></image><image src="/static/emoji.png" @tap="showEmojiPicker"></image></view><view v-if="!isVoiceMode" class="text-input"><textareav-model="message"auto-heightplaceholder="请输入消息...":focus="textFocus"@focus="onFocus"@blur="onBlur"></textarea></view><view v-else class="voice-input"><voice-input @result="onVoiceResult"></voice-input></view><button class="send-btn" :disabled="!message.trim()" @tap="sendMessage">发送</button></view>
</template><script>
import VoiceInput from '@/components/voice-input/voice-input.vue';export default {components: {VoiceInput},data() {return {message: '',isVoiceMode: false,textFocus: false};},methods: {toggleInputMode() {this.isVoiceMode = !this.isVoiceMode;if (!this.isVoiceMode) {this.$nextTick(() => {this.textFocus = true;});}},onVoiceResult(result) {this.message = result;this.isVoiceMode = false;},sendMessage() {if (!this.message.trim()) return;this.$emit('send', this.message);this.message = '';},onFocus() {this.textFocus = true;},onBlur() {this.textFocus = false;},showEmojiPicker() {// 显示表情选择器}}
};
</script><style>
.chat-input-container {display: flex;align-items: center;padding: 20rpx;border-top: 1rpx solid #eee;background-color: #fff;
}.chat-tools {display: flex;margin-right: 20rpx;
}.chat-tools image {width: 60rpx;height: 60rpx;margin-right: 20rpx;
}.text-input {flex: 1;background-color: #f5f5f5;border-radius: 10rpx;padding: 10rpx 20rpx;
}.text-input textarea {width: 100%;min-height: 60rpx;max-height: 240rpx;
}.voice-input {flex: 1;display: flex;justify-content: center;
}.send-btn {width: 140rpx;height: 80rpx;line-height: 80rpx;font-size: 28rpx;margin-left: 20rpx;padding: 0;background-color: #1890ff;color: #fff;
}.send-btn[disabled] {background-color: #ccc;
}
</style>
性能优化和注意事项
在实际开发中,我遇到了一些需要特别注意的问题:
1. 权限处理
语音识别需要麦克风权限,不同平台的权限处理方式不同:
// 统一请求录音权限
requestAudioPermission() {return new Promise((resolve, reject) => {// #ifdef APP-PLUSconst permissions = ['android.permission.RECORD_AUDIO'];plus.android.requestPermissions(permissions,function(e) {if (e.granted.length === permissions.length) {resolve();} else {reject(new Error('未授予录音权限'));}},function(e) {reject(e);});// #endif// #ifdef MP-WEIXIN || MP-BAIDUuni.authorize({scope: 'scope.record',success: () => resolve(),fail: (err) => reject(err)});// #endif// #ifdef H5if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {navigator.mediaDevices.getUserMedia({ audio: true }).then(() => resolve()).catch(err => reject(err));} else {reject(new Error('浏览器不支持录音功能'));}// #endif});
}
2. 流量控制
语音识别需要上传音频数据,在移动网络下会消耗流量:
// 检查网络环境并提示用户
checkNetwork() {uni.getNetworkType({success: (res) => {if (res.networkType === '2g' || res.networkType === '3g') {uni.showModal({title: '流量提醒',content: '当前处于移动网络环境,语音识别可能消耗较多流量,是否继续?',success: (confirm) => {if (confirm.confirm) {this.startSpeechRecognition();}}});} else {this.startSpeechRecognition();}}});
}
3. 性能优化
长时间语音识别会增加内存和电量消耗,需要做好优化:
// 设置最大录音时长和自动结束
setupMaxDuration() {if (this.timer) {clearTimeout(this.timer);}this.timer = setTimeout(() => {if (this.isRecording) {uni.showToast({title: '录音时间过长,已自动结束',icon: 'none'});this.stopRecord();}}, this.maxDuration * 1000);
}// 空闲自动停止
setupVAD() {// 监测静音,如果用户停止说话3秒,自动结束录音let lastAudioLevel = 0;let silenceCounter = 0;this.vadTimer = setInterval(() => {// 获取当前音量const currentLevel = this.getAudioLevel();if (Math.abs(currentLevel - lastAudioLevel) < 0.05) {silenceCounter++;if (silenceCounter > 30) { // 3秒 (30 * 100ms)this.stopRecord();}} else {silenceCounter = 0;}lastAudioLevel = currentLevel;}, 100);
}
增强功能:语音合成(TTS)
除了语音识别外,语音合成(Text-to-Speech)也是很有用的功能,可以将文本转换为语音:
// 语音合成
textToSpeech(text, options = {}) {const { lang = 'zh', speed = 5, volume = 5 } = options;// #ifdef APP-PLUSconst speechPlugin = uni.requireNativePlugin('speech-baidu');return new Promise((resolve, reject) => {speechPlugin.textToSpeech({text,language: lang === 'zh' ? 'zh-cn' : 'en-us',speed,volume}, (res) => {if (res.errorCode === 0) {resolve(res);} else {reject(new Error(`语音合成失败: ${res.errorCode}`));}});});// #endif// #ifdef H5return new Promise((resolve, reject) => {if ('speechSynthesis' in window) {const speech = new SpeechSynthesisUtterance();speech.text = text;speech.lang = lang === 'zh' ? 'zh-CN' : 'en-US';speech.rate = speed / 10;speech.volume = volume / 10;speech.onend = () => {resolve();};speech.onerror = (err) => {reject(err);};window.speechSynthesis.speak(speech);} else {reject(new Error('当前浏览器不支持语音合成'));}});// #endif
}
踩坑记录与解决方案
开发过程中,我遇到了一些常见问题与解决方法,分享如下:
- 百度语音插件初始化失败:检查API密钥配置和网络环境,特别是HTTPS限制
- H5录音无法使用:多数浏览器要求必须在HTTPS环境下才能使用麦克风
- 识别结果不准确:尝试调整录音参数,如采样率、声道数等,或者使用更专业的噪声抑制算法
- 微信小程序调用失败:检查access_token是否有效,注意token有效期
- 不同设备体验差异大:针对低端设备优化,如减少动画效果、降低采样率等
我们的解决方案是进行兼容性检测,并根据设备性能自动调整参数:
// 检测设备性能并调整参数
detectDevicePerformance() {const platform = uni.getSystemInfoSync().platform;const brand = uni.getSystemInfoSync().brand;const model = uni.getSystemInfoSync().model;// 低端安卓设备优化if (platform === 'android') {// 特定型号的优化if (brand === 'samsung' && model.includes('SM-J')) {return {sampleRate: 8000,quality: 'low',useVAD: false // 禁用语音活动检测,降低CPU占用};}}// 默认配置return {sampleRate: 16000,quality: 'high',useVAD: true};
}
总结与展望
通过本文,我们探讨了在UniApp中实现语音输入与识别功能的多种方案,并提供了具体的代码实现。这些实现方案已在实际项目中得到验证,能够满足大多数应用场景的需求。
语音技术在移动应用中的重要性不断提升,未来可以探索更多高级功能:
- 离线语音识别:降低网络依赖,提高响应速度
- 多语言支持:增加更多语言的识别能力
- 声纹识别:通过语音实现用户身份验证
- 情感分析:从语音中识别用户情绪
希望本文对你在UniApp中实现语音功能有所帮助!如有问题欢迎在评论区交流讨论。
参考资料
- UniApp官方文档
- 百度语音识别API文档
- Web Speech API
相关文章:
鸿蒙OSUniApp 实现的语音输入与语音识别功能#三方框架 #Uniapp
UniApp 实现的语音输入与语音识别功能 最近在开发跨平台应用时,客户要求添加语音输入功能以提升用户体验。经过一番调研和实践,我成功在UniApp项目中实现了语音输入与识别功能,现将过程和方法分享出来,希望对有类似需求的开发者有…...

windows版redis的使用
redis下载 Releases microsoftarchive/redishttps://github.com/microsoftarchive/redis/releases redis的启动和停止 进入路径的cmd 启动:redis-server.exe redis.windows.conf 停止:ctrlc 连接redis 指定要连接的IP和端口号 -h IP地址 -p 端口…...

Java版OA管理系统源码 手机版OA系统源码
Java版OA管理系统源码 手机版OA系统源码 一:OA系统的主要优势 1. 提升效率 减少纸质流程和重复性工作,自动化处理常规事务,缩短响应时间。 2. 降低成本 节省纸张、打印、通讯及人力成本,优化资源分配。 3. 规范管理 固化企…...

NineData 社区版 V4.1.0 正式发布,新增 4 条迁移链路,本地化数据管理能力再升级
NineData 社区版 V4.1.0 正式更新发布。本次通过新增 4 条迁移链路扩展、国产数据库深度适配、敏感数据保护增强等升级,进一步巩固了其作为高效、安全、易用的数据管理工具的定位。无论是开发测试、数据迁移,还是多环境的数据管理,NineData…...

进阶2_1:QT5多线程与定时器共生死
1、在widget.ui中使用 LCD Number控件 注意:若 LCD 控件不是多线程,LCD控件则会瞬间自增到最大的数值,如上图,说明两者都是多线程处理 2、实现方式 1、创建 LCD 控件并修改为 LCD1 2、创建任务类 mytask. h,对任务类…...

在虚拟机Ubuntu18.04中安装NS2教程及应用
NS2简介 一、主要组成部分: 1.NS2:模拟器本身,负责执行TCL脚本进行模拟,并生成trace文件输出结果。 2.NAM:网络动画模拟器,用于将模拟结果可视化。 二、使用的语言: 1.C:NS2中最重要…...

VBA —— 第6章子程序与函数
子程序:实现特定功能的程序代码块 子程序语法: [修饰符] Sub 子程序名称([参数1,参数2,参数3]) 代码块 End Sub 子程序如何调用: 1 . 子程序名 [参数1,参数2,...] 2. Call 子程序名 [(参…...
MySQL知识点总结(持续更新)
聚合函数通常用于对数据进行统计和聚合操作。以下是一些常见数据库系统(如 MySQL、PostgreSQL、Oracle、SQL Server 等)中常用的聚合函数: 常见的数据库聚合函数: COUNT():计算指定列中非空值的数量 SELECT COUNT(*) …...

全新开发-iVX图形化编程VS完整IDE
本文针对传统软件开发的效率与可控性矛盾,系统阐释 iVX"图形化编程 全栈 IDE" 的复合架构如何突破行业瓶颈。通过 "可视化建模 - 标准代码生成 - 独立运行" 的技术闭环,iVX 实现开发效率提升 60% 与源码完全可控的双重目标。研究揭…...
【android bluetooth 协议分析 12】【A2DP详解 1】【车机侧蓝牙音乐免切源介绍】
“车机蓝牙音乐免切源” 是近年来车载系统(IVI,In-Vehicle Infotainment)中常见的一个用户体验优化功能。它主要是为了简化蓝牙音乐播放流程、减少用户操作,提升使用便捷性。 一、什么是“切源”? 在车机系统中&#…...

【Linux系列】跨平台安装与配置 Vim 文本编辑器
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
蓝桥杯题库经典题型
1、数列排序(数组 排序) 问题描述 给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<n<200 输入格式 第一行为一个整数n。 第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。 输出格式 输出…...
Spring Boot整合MyBatis全攻略:原理剖析与最佳实践
MyBatis作为Java生态中最流行的ORM框架之一,与Spring Boot的结合极大地简化了数据库访问层的开发。本文将深入剖析Spring Boot整合MyBatis的核心机制,详细介绍各种使用方式,并分享实际开发中的高级技巧和最佳实践。 一、Spring Boot与MyBati…...

十天学会嵌入式技术之51单片机—day-10
第 20 章 18B20 温度检测 20.1 18B20 概述 20.1.1 简介 18B20 是一种常用的数字温度传感器,广泛应用于环境监测、工业控制、家居自动化 和设备温度监控等领域。 20.1.2 引脚功能 18B20 引脚功能如下图所示,需要特别强调的是,18B20 采用 1-…...

【C++】17. 多态
上一章节中我们讲了C三大特性的继承,这一章节我们接着来讲另一个特性——多态 1. 多态的概念 多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态),这里我们重点讲运行时多态…...
Excel的详细使用指南
### **一、Excel基础操作** #### **1. 界面与基本概念** - **工作簿(Workbook)**:一个Excel文件(扩展名.xlsx)。 - **工作表(Worksheet)**:工作簿中的单个表格(默认名…...
没经过我同意,flink window就把数据存到state里的了?
欢迎关注我 不知道大家在初次使用Flink的时候,是否对Flink中定义本地变量和状态比较好奇,这俩有啥区别? 而且在使用Window API时明明没有显式地创建状态,也没调用getState(),却依然把每个窗口里的所有元素都自动缓存…...
Python+OpenCV打造AR/VR基础框架:从原理到实战的全链路解析
引言:重新定义数字与现实的边界 在元宇宙概念持续升温的当下,AR(增强现实)与VR(虚拟现实)技术正成为连接物理世界与数字世界的桥梁。Python凭借其丰富的计算机视觉生态(尤其是OpenCV库…...

家用或办公 Windows 电脑玩人工智能开源项目配备核显的必要性(含 NPU 及显卡类型补充)
一、GPU 与显卡的概念澄清 首先需要明确一个容易误解的概念:GPU 不等同于显卡。 显卡和GPU是两个不同的概念。 【概念区分】 在讨论图形计算领域时,需首先澄清一个常见误区:GPU(图形处理单元)与显卡(视…...

实现一个简单的 TCP 客户端/服务器
注意: TCP 三次握手建立连接建立连接后,TCP 提供全双工的通信服务,也就是在同一个连接中,通信双方 可以在同一时刻同时写数据,相对的概念叫做半双工,同一个连接的同一时刻,只能由一方来写数据T…...

对抗帕金森:在疾病阴影下,如何重掌生活主动权?
帕金森病,一种影响全球超 1000 万人的神经退行性疾病,正无声地改变着患者的生活轨迹。随着大脑中多巴胺分泌减少,患者逐渐出现肢体震颤、肌肉僵硬、步态迟缓等症状,甚至连扣纽扣、端水杯这类日常动作都变得艰难。更棘手的是&#…...

鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
使用 EventHub 进行数据通信 Stage模型概念图 根据 Stage 模型概念图 UIAbility 先于 ArkUI Page 创建 所以,事件要先 .on 订阅 再 emit 发布 假如现在有页面 Page1 和他的 UIAbility // src/main/ets/page1ability/Page1Ability.ets onCreate(want: Want, laun…...
DeepSeek 赋能汽车全生态:从产品到服务的智能化跃迁
目录 一、引言二、DeepSeek 助力汽车产品介绍与推广2.1 新车性能参数与技术亮点宣传文案2.2 汽车品牌故事与文化内涵挖掘2.3 汽车广告创意与宣传方案设计 三、DeepSeek 赋能汽车售后服务支持3.1 汽车维修保养知识科普文章创作3.2 常见故障诊断与解决方案生成3.3 汽车用户个性化…...
MQTT 在Spring Boot 中的使用
在 Spring Boot 中使用 MQTT 通常会借助 Spring Integration 项目提供的 MQTT 支持。这使得 MQTT 的集成可以很好地融入 Spring 的消息驱动和企业集成模式。 以下是如何在 Spring Boot 中集成和使用 MQTT 的详细步骤: 前提条件: MQTT Brokerÿ…...

Vue3学习(组合式API——计算属性computed详解)
目录 一、计算属性computed。 Vue官方提供的案例。(普通写法与计算属性写法) 使用计算属性computed重构——>简化描述响应式状态的复杂逻辑。 (1)计算属性computed小案例。 <1>需求说明。(筛选原数组——>得新数组) &…...
Spring 中的 @ComponentScan注解详解
在 Spring 框架中,@ComponentScan 是一个非常重要的注解,它用于自动扫描和注册 Bean。通过该注解,Spring 能够自动发现并管理标注了特定注解的类(如 @Component, @Service, @Repository 等),从而实现依赖注入和容器管理。 本文将详细介绍 @ComponentScan 的作用、常见搭…...
MySQL 数据库故障排查指南
MySQL 数据库故障排查指南 本指南旨在帮助您识别和解决常见的 MySQL 数据库故障。我们将从问题识别开始,逐步深入到具体的故障类型和排查步骤。 1. 问题识别与信息收集 在开始排查之前,首先需要清晰地了解问题的现象和范围。 故障现象: 数…...

Android Studio 模拟器配置方案
Android Studio 模拟器配置方案 1.引言2.使用Android Studio中的模拟器3.使用国产模拟器1.引言 前面介绍【React Native基础环境配置】的时候需要配置模拟器,当时直接使用了USB调试方案,但是有些时候可能不太方便连接手机调试,比如没有iPhone调不了ios。接下来说明另外两种可…...

k8s中ingress-nginx介绍
1. 介绍 Ingress是一种Kubernetes资源,用于将外部流量路由到Kubernetes集群内的服务。与NodePort相比,它提供了更高级别的路由功能和负载平衡,可以根据HTTP请求的路径、主机名、HTTP方法等来路由流量。可以说Ingress是为了弥补NodePort在流量…...
键盘输出希腊字符方法
在不同操作系统中,输出希腊字母的方法有所不同。以下是针对 Windows 和 macOS 系统的详细方法,以及一些通用技巧: 1.Windows 系统 1.1 使用字符映射表 字符映射表是一个内置工具,可以方便地找到并插入希腊字母。 • 步骤…...