فهرست منبع

增加语音功能

zjs_project 3 هفته پیش
والد
کامیت
b147a53016

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 41 - 0
src/assets/speechrecognizer.js


+ 16 - 2
src/components/newQCCom/viewlayout/viewlayout.html

@@ -1,6 +1,6 @@
 <!-- 户型弹出层主操作视图 -->
-<!-- <div class="layout-view" @touchend="streamRecordEnd"> -->
-<div class="layout-view">
+<div class="layout-view" @touchend="streamRecordEnd">
+<!-- <div class="layout-view"> -->
 	<!-- 种子区域 -->
 	<div>
 		<div class="btn-list rows rows-between" v-if="styleType==1">
@@ -32,6 +32,11 @@
 			<div class="btn houseType rows justify-center up3" @click="openLayout(3)" v-else>
 				<div class="iconfont icon-huxingjianshang style1"></div>更改功能
 			</div>
+            <!-- 语音调整 -->
+            <div class="btn voice rows justify-center" @touchstart="speechRecognizer" >
+                <img class="icon" src="https://dm.static.elab-plus.com/miniProgram/iconfont/source.png" mode="widthFix"/>
+                <div class="overlay" @contextmenu.prevent></div>
+            </div>
 			<div class="btn AiBtn rows justify-center " @click="goRoam"  :style="{'background':hexToRgba(highColor1,0.8),'color':backgroundColor}">
 				<div class="iconfont icon-a-lujing35039 style1"></div>AI精软装
 			</div>
@@ -46,4 +51,13 @@
 			</div>
 		</div> -->
 	</div>
+    <!-- 语音视图 -->
+    <div class="voice-view" v-show="recording">
+        <div class="columns justify-center">
+            <div class="voice-title">客厅变大或者变小</div>
+            <div class="voice-tips">松开手指,停止录音</div>
+            <img class="voice-gif" src="https://dm.static.elab-plus.com/miniProgram/iconfont/play.gif" mode="widthFix"/>
+            <div class="voice-tips" style="margin-top:12rpx;">我在听…</div>
+        </div>
+    </div>
 </div>

+ 58 - 2
src/components/newQCCom/viewlayout/viewlayout.scss

@@ -77,7 +77,7 @@
 }
 .houseType{
 	// width: 320px;
-	width: 242px;
+	width: 200px;
 	// box-shadow: 0 6px 20px #f2980233;
 }
 .style1{
@@ -85,7 +85,7 @@
 }
 .AiBtn{
     // flex:1;
-	width: 410px;
+	width: 340px;
 	// box-shadow: 0 6px 20px #f2980233;
 }
 .pinggu{
@@ -93,4 +93,60 @@
     font-weight: 700;
     font-size: 30px;
     color: #fff;
+}
+.voice{
+    position: relative;
+    width: 100px;
+    background: linear-gradient(130.79deg, rgba(245, 201, 82, 1) 0%, rgba(253, 148, 41, 1) 100%);
+    border-radius: 50%;
+    user-select: none;
+    // background-image: url('https://dm.static.elab-plus.com/miniProgram/iconfont/play.gif');
+    // background-repeat: no-repeat;
+    // background-size: cover;
+    color: #fff;
+    .icon{
+        width: 31.5px;
+        height: 44px;
+        user-select: none;
+        -webkit-touch-callout:none;
+        // margin-right: 10px;
+    }
+    .overlay {  
+        position: absolute;  
+        top: 0;  
+        left: 0;  
+        width: 100%;  
+        height: 100%;  
+        background: transparent; /* 透明覆盖 */  
+    } 
+}
+.voice-view{
+	position: fixed;
+	left: 0px;
+	bottom: 0px;
+	width: 100%;
+    height: 550px;
+	font-family: "Verdana";
+	font-weight: 400;
+	z-index: 150;
+	pointer-events: none;
+    // backdrop-filter:blur(40px);
+    background-color: #fff;
+    border-radius: 40px 40px 0 0;
+    user-select: none;
+    .voice-title{
+    	font-size: 36px;
+    	color: #242424;
+    }
+    .voice-tips{
+    	font-size: 28px;
+    	color: rgba(36, 36, 36, 0.51);
+    	margin-top:10px;
+    	margin-bottom:28px;
+    }
+    .voice-gif{
+    	width: 100%;
+    	margin-top:-20px;
+        user-select: none;
+    }
 }

+ 236 - 11
src/components/newQCCom/viewlayout/viewlayout.vue

@@ -2,11 +2,13 @@
 
 </template>
 <script>
-	// const util = require('@/static/utils/util.js');
+	const util = require('@/utils/util.js').default;
 	const config = require('@/services/urlConfig.js');
-	import {
-		Toast
-	} from 'mint-ui';
+    let webAudioSpeechRecognizer;
+    import {
+        Toast,Indicator
+    } from 'mint-ui';
+    import spaceTypes from '@/static/spaceTypesIE.js';
 	// import Bus from '@/common/bus';
 	// import commonMethod from '@/common/commonMethod.js';
 	// import requestConfig from '@/static/lib/requestConfig';
@@ -46,6 +48,10 @@
                 highColor1:window.highColor1,
                 highColor2:window.highColor2,
                 backgroundColor:window.backgroundColor,
+                
+                speechText: '', //语音识别的结果-文字
+                recording: false, //语音识别是否开始
+                touching:false,
 			}
 		},
 		props: {
@@ -88,6 +94,7 @@
 						// }
 						const spaceDetail = newVal;
 						this.spaceList = JSON.parse(spaceDetail.houseJson);
+                        this.initSpanceData();
 					}
 				},
 			},
@@ -171,22 +178,29 @@
 					if(item.hasOwnProperty('spaceWidthMax') && item.hasOwnProperty('spaceHeightMax')){
 						maxArea = parseFloat((item.spaceWidthMax * item.spaceHeightMax) / 10000).toFixed(1);
 					}
-					let text = item.spaceName;
-					if(text && !item.isSizeLock){
-						// let res = await requestConfig("chineseToPinyin", {chinese:text},true);
-						// let pinyin = res.single;
+                    //修改为显示空间类型名称
+                    let text = spaceTypes[item.spaceType - 1] || item.spaceName;
+                    if(item.spaceType==15 && item.layoutSpaceType){
+                    	text = spaceTypes[item.layoutSpaceType - 1]; 
+                    }
+					// let text = item.spaceName;
+					if(text && !item.isSizeLock && (Number(maxArea) >= Number(curSpaceArea)) && !(maxArea==minArea && curSpaceArea==maxArea)){
+						let res = await requestConfig("chineseToPinyin", {chinese:text},true);
+						let pinyin = res.single;
 						let data = {
 							spaceId:item.spaceId,
 							index:this.carefulList.length,
-							name:text,
-							namePY:'',
+							name: text,
+							namePY: pinyin,
 							area:curSpaceArea,
 							percent:null,
 							minArea:minArea,	//最小面积
 							maxArea:maxArea,	//最大面积
 						}
 						this.carefulList.push(data)
-					}
+					}else{
+                        // console.warn("***viewlayout-ini1t***", item.spaceId, text, maxArea, minArea, curSpaceArea,!item.isSizeLock, maxArea >= curSpaceArea,!(maxArea==minArea && curSpaceArea==maxArea))
+                    }
 				})
 				console.warn("***viewlayout-init***", this.carefulList)
 			},
@@ -259,6 +273,217 @@
 			goRoam(){
 				this.$parent.$refs.viewCareful.goRoam();
 			},
+            //求最长公共子集
+            findSubStr(str1, str2) {
+                if (str1.length > str2.length) {
+                    var temp = str1;
+                    str1 = str2;
+                    str2 = temp;
+                }
+                let len1 = str1.length;
+                let len2 = str2.length;
+                for (var j = len1; j > 0; j--) {
+                    for (var i = 0; i < len1 - j; i++) {
+                        var current = str1.substr(i, j);
+                        if (str2.indexOf(current) >= 0) {
+                            return current;
+                        }
+                    }
+                }
+                return "";
+            },
+            async textChange(text) {
+                if (!text) {
+                    Toast({
+                        message: '未识别到语音',
+                    });
+                    return false;
+                }
+                if(!this.carefulList || this.carefulList.length==0){
+                    console.warn("****textChange***", this.carefulList)
+                    return false;
+                }
+                let param = {
+                    type: 'CLK', //埋点类型
+                    clkId: 'clk_2cmina_24082901', //点击ID
+                    clkName: 'user_talk_clk', //点击前往的页面名称
+                    clkParams: {
+                        locusValue: text,
+                    }
+                };
+                util.trackRequest(param);
+                let res = await requestConfig("chineseToPinyin", {
+                    chinese: text
+                });
+                let pinyin = res.single;
+                console.warn("****pinyin***", pinyin)
+                text = pinyin;
+                //全匹配轮一遍
+                let curSpace = this.carefulList.find(space => {
+                    return text.includes(space.namePY)
+                })
+                if (!curSpace) {
+                    let list = this.carefulList.map((space, index) => {
+                        let comStr = this.findSubStr(text, space.namePY + ' ');
+                        return {
+                            spaceId: space.spaceId,
+                            namePY: space.namePY,
+                            name: space.name,
+                            comStr,
+                            index,
+                        }
+                    })
+                    //寻找5个字符串以上的
+                    let tmpList = list.filter(it => {
+                        return it.comStr.length > 5;
+                    })
+                    if (tmpList && tmpList.length > 0) {
+                        tmpList.sort((a, b) => a.comStr.length - b.comStr.length);
+                        let index = tmpList[tmpList.length - 1].index; //最大值在carefulList的序号
+                        curSpace = this.carefulList[index]; //
+                    } else {
+                        curSpace = this.lastSpace;
+                    }
+                }
+
+                //没有找到语音操作对象
+                if (!curSpace) {
+                    curSpace = this.carefulList.find(it=>it.spaceId == this.curSpaceId);
+                    // Toast({
+                    //     message: '请再说一次',
+                    // });
+                    // return false;
+                }
+                this.lastSpace = curSpace;
+
+                console.log("textChange:", curSpace, this.carefulList, text, this.bigWordPY, this.smaillWordPY);
+
+                let biglist = this.bigWordPY.split(',').map(word => {
+                    return text.lastIndexOf(word)
+                })
+                let smalllist = this.smaillWordPY.split(',').map(word => {
+                    return text.lastIndexOf(word)
+                })
+                let a = Math.max(...biglist);
+                let b = Math.max(...smalllist);
+                let big = false;
+                if (a == -1 && b == -1) { //都没命中
+                    Toast({
+                        message: '请再说一次',
+                    });
+                    return false;
+                } else if (a > -1 && b > -1) { //两个都命中了
+                    if (a > b) { //放大靠后-命中靠后
+                        big = true;
+                    } else {
+                        big = false;
+                    }
+                } else if (a > -1) {
+                    big = true;
+                }
+                let _area = parseFloat(curSpace.area) * this.changeRate;
+                let data = {
+                    spaceId: curSpace.spaceId,
+                    area: _area,
+                    isZoomIn: big, //true 放大 false 缩放
+                }
+                console.log("viewlayout-发送消息-空间变化: ", data, curSpace.area, big);
+                Toast({
+                    message: '正在变化,请稍后',
+                });
+                // this.sendMessageAction(JSON.stringify(parmas));
+                this.$parent.$parent.callBackFun = this.callBack;//向父页面注册通知回调函数
+                this.$emit("curSpaceChange", data); //通知父组件-当前已经选中了户型大类
+            },
+            //语音识别
+            speechRecognizer() {
+                this.touching = true;//用户开始触摸语音按钮
+                console.warn('speechRecognizer', this.recording)
+                // if (!webAudioSpeechRecognizer) {
+                    const params = {
+                        // signCallback: signCallback, // 鉴权函数,若直接使用默认鉴权函数。可不传此参数
+                        // 用户参数
+                        secretid: $config.secretId,
+                        secretkey: $config.secretKey,
+                        appid: $config.txappId,
+                        // 临时密钥参数,非必填
+                        // token: config.token,
+                        // 实时识别接口参数
+                        engine_model_type: '16k_zh', // 因为内置WebRecorder采样16k的数据,所以参数 engineModelType 需要选择16k的引擎,为 '16k_zh'
+                        // 以下为非必填参数,可跟据业务自行修改
+                        // voice_format : 1,
+                        // hotword_id : '08003a00000000000000000000000000',
+                        // needvad: 1,
+                        // filter_dirty: 1,
+                        // filter_modal: 2,
+                        // filter_punc: 0,
+                        // convert_num_mode : 1,
+                        // word_info: 2
+                    }
+                    webAudioSpeechRecognizer = new WebAudioSpeechRecognizer(params);
+                    Indicator.open({
+                        text: '正在链接...',
+                        spinnerType: 'fading-circle'
+                    });
+                    // 开始识别
+                    webAudioSpeechRecognizer.OnRecognitionStart = (res) => {
+                        console.log('开始识别',this.recording, res);
+                    };
+                    // 一句话开始 socket链接成功了
+                    webAudioSpeechRecognizer.OnSentenceBegin = (res) => {
+                        console.log('一句话开始',this.touching,res);
+                        if(this.touching==false){//用户没有触摸
+                            return false;
+                        }else{//正常开始识别语句了
+                            this.speechText = "";
+                            Indicator.close();
+                            this.recording = true;//显示正在录音视图
+                        }
+                        
+                    };
+                    // 识别变化时
+                    webAudioSpeechRecognizer.OnRecognitionResultChange = (res) => {
+                        console.log('识别变化时', res);
+                        // const currentText = `${resultText}${res.result.voice_text_str}`;
+                    };
+                    // 一句话结束
+                    webAudioSpeechRecognizer.OnSentenceEnd = (res) => {
+                        console.log('一句话结束',this.recording, res);
+                        // resultText = res.result.voice_text_str;
+                        let text = res.result.voice_text_str.replaceAll(/,|。/ig, "");
+                        this.textChange(text);
+                        // this.speechText += resultText;
+                    };
+                    // 识别结束
+                    webAudioSpeechRecognizer.OnRecognitionComplete = (res) => {
+                        console.log('识别结束', res);
+                        this.recording = false; //录音结束
+                    };
+                    // 识别错误
+                    webAudioSpeechRecognizer.OnError = (res) => {
+                        console.log('识别失败', res)
+                        this.recording = false; //录音结束
+                        Indicator.close();
+                    };
+                    // webAudioSpeechRecognizer = webAudioSpeechRecognizer;
+                // }
+                webAudioSpeechRecognizer.start();
+            },
+            //结束识别
+            streamRecordEnd() {
+                this.touching = false;//用户没有触摸了
+                console.log('主动结束识别', this.recording)
+                if(webAudioSpeechRecognizer){
+                    webAudioSpeechRecognizer.stop();//关闭
+                }
+                // webAudioSpeechRecognizer = null;
+                Indicator.close();
+            },
+            callBack(type){
+                console.warn("***viewlayout-callBack***",type)
+                // this.initSpanceData();
+                this.$parent.$refs.viewCareful.initData();//注销父页面的通知回调函数
+            },
 			//评估按钮处理
 			assessmentHandle(){
                 Toast({

+ 3 - 1
src/main.js

@@ -15,6 +15,7 @@ import 'mint-ui/lib/style.css';
 
 import '@/assets/common.css'; //公共样式
 import "@/assets/font/iconfont.css"; //引用公共icon库
+import * as WebAudioSpeechRecognizer from "@/assets/speechrecognizer.js"; //引用腾讯语音识别SDK
 // import popUpComponent from "@/components/popUpComponent/popUpComponent.js"; // 公共弹框样式
 // import previewComponent from "@/components/previewComponent/previewComponent.js"; // 公共图片视频预览
 // import "@/utils/command.js"; // 自定义指令
@@ -32,6 +33,7 @@ Vue.component('mynavbar', mynavbar)
 window.$bus = new Vue(); //定义一个事件总线对象-方便组件通讯
 window.axios = axios;
 window.$ = $;
+window.WebAudioSpeechRecognizer = WebAudioSpeechRecognizer;
 Vue.prototype.$http = axios;
 Vue.prototype.axios = axios;
 // Vue.prototype.checkPermission = checkPermission; // 权限校验
@@ -44,7 +46,7 @@ window.echarts = echarts;
 
 console.log('***process.env***production', process.env);
 window.env = process.env.NODE_ENV;
-env = env == 'development' ? 'production' : env;
+env = env == 'development' ? 'test2' : env;
 window.$config = api(env);
 console.log("window.$config", window.$config);
 

+ 24 - 0
src/services/urlConfig.js

@@ -26,6 +26,9 @@ var config = function(env) {
 			clientId:'1112011009',
 			appId:'1758586978178079',
             baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'test2') {
         WEB_CONF = {
@@ -55,6 +58,9 @@ var config = function(env) {
 			clientId:'1112011009',
 			appId:'1758586978178079',
             baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'test3') {
         WEB_CONF = {
@@ -82,6 +88,9 @@ var config = function(env) {
 			clientId:'1112011009',
 			appId:'1758586978178079',
             baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'test4') {
         WEB_CONF = {
@@ -107,6 +116,9 @@ var config = function(env) {
             clientId:'1112011009',
             appId:'1758586978178079',
             baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'dev') {
         WEB_CONF = {
@@ -132,6 +144,9 @@ var config = function(env) {
 			clientId:'1112011009',
 			appId:'1758586978178079',
             baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'uat') {
         WEB_CONF = {
@@ -156,6 +171,9 @@ var config = function(env) {
             clientId:'1112013355',
 			appId:'1758979466364941',
             baiduAppid:'9a7c9c156493ffbb48bd562112e1161a',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'uat3') {
         WEB_CONF = {
@@ -180,6 +198,9 @@ var config = function(env) {
             clientId:'1112013355',
             appId:'1758979466364941',
             baiduAppid:'9a7c9c156493ffbb48bd562112e1161a',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     } else if (env === 'production') {
         WEB_CONF = {
@@ -206,6 +227,9 @@ var config = function(env) {
             clientId:'1112009742',
 			appId:'1758704971288606',
             baiduAppid:'30c97c277abecefe282aaa2ea7fa4115',
+            secretId: "AKIDypcHxZ0JVUK8nIcGh6UlwxoVz4CSexFd",
+            secretKey: "Mo4QgWAJVoJgs7GHG4iAQWPPSOTQAjGi",
+            txappId: 1256217102,
         }
     }
     return WEB_CONF