Commit f0ecb243 authored by xuchaozou's avatar xuchaozou

feat: 初步完成打开语音模块

parent 7ccb01fc
Pipeline #85693 failed with stages
......@@ -118,6 +118,7 @@
"@wisdom-utils/components": "0.1.349",
"@wisdom-utils/runtime": "0.0.48",
"@wisdom-utils/utils": "0.1.388",
"@congcongcai/jieba.js" : "0.0.3",
"animate.css": "^4.1.1",
"antd": "4.21.2",
"long": "^5.2.3",
......
......@@ -9,13 +9,13 @@ import { Directive } from '../../core'
const Dialog = props => {
const {history , pandaRecordWebSocketRef} = props
const { pandaRecordWebSocketRef} = props
const ulRef = useRef(null)
const directiveRef = useRef(null)
const [data , setData] = useState([])
const finish = useCallback(async ({resultText}) => {
pandaRecordWebSocketRef.setStatus("pause")
pandaRecordWebSocketRef.current.setStatus("pause")
const directive = directiveRef.current.parse({
text : resultText
})
......@@ -25,16 +25,19 @@ const Dialog = props => {
content : "系统正在思考中,请稍后..."
})
const msg = await directive.excute()
setTimeout(() => {
updateLastData({
content : msg
})
}, 1000)
pandaRecordWebSocketRef.current.setStatus("playing")
return
}
sendContent({
role : "system",
content : "亲,我暂时还未理解你的意思,请换一种方式表达或者描述更加具体"
})
pandaRecordWebSocketRef.setStatus("playing")
pandaRecordWebSocketRef.current.setStatus("playing")
}, [])
const frame = useCallback((data) => {
......@@ -68,7 +71,6 @@ const Dialog = props => {
useEffect(() => {
directiveRef.current = new Directive({
params : {
history
}
})
}, [])
......@@ -92,14 +94,14 @@ const Dialog = props => {
}
const updateLastData = ({content , ...params }) => {
setData(data => data.map((data , index) => {
if(index < length -1) {
setData(data => data.map((item , index) => {
if(index < data.length -1) {
return {
...data
...item
}
} else {
return {
...data,
...item,
content,
...params,
}
......
......@@ -20,12 +20,11 @@ const PandaTip = props => {
} else if(directive instanceof ByeDirective && status == "open") {
setStatus("close")
}
}, [])
}, [status])
useEffect(() => {
directiveRef.current = new Directive({
// directiveTypes : [AwakenDirective , ByeDirective],
directiveTypes : []
directiveTypes : [AwakenDirective , ByeDirective],
})
}, [])
......
......@@ -3,6 +3,8 @@ class BaseDirective {
this.options = options
this.text = this.options.text
this.directives = options.directives
this.params = options.params || {}
this.data = null
}
match () {
......
......@@ -3,7 +3,7 @@ import BaseDirective from "./BaseDirective";
class ByeDirective extends BaseDirective {
match () {
const {text} = this
if(/再见再见|拜拜/.test(text)) {
if(/再见|拜拜|关闭/.test(text)) {
return true
}
return false
......
import BaseDirective from "./BaseDirective";
class CloseMenuDirective extends BaseDirective {
match () {
const { text } = this
let result = null
result = text.match(/关闭(.*)(?=(?:菜单|功能|路径))/)
if (!result) {
result = text.match(/关闭(.*)(?=(?:,|,|。|))/)
}
if (result && result.length >= 2) {
this.matchResult = result[1]
}
return !!(result && result.length >= 2)
}
async excute () {
let widgets = null
if(this.data) {
} else {
widgets = this.getCompleteMenus()
}
}
getCompleteMenus () {
const result = Utils.findMenus({
name: this.matchResult
})
const { widgets } = result
// return widgets.length > 0 ? widgets : null
}
}
export default CloseMenuDirective
\ No newline at end of file
import Utils from '../utils/Utils'
import BaseDirective from './BaseDirective'
class HomePageDirective extends BaseDirective {
match () {
const {text} = this
if(/首页/.test(text)) {
return true
}
return false
}
async excute () {
if(!window.globalConfig.homepage) {
return "没有配置首页"
}
Utils.openMenu({url : window.globalConfig.homepage})
return "返回首页成功"
}
}
export default HomePageDirective
\ No newline at end of file
import BaseDirective from "./BaseDirective";
import { cut, extract } from '@congcongcai/jieba.js'
import Utils from "../utils/Utils";
import { uniq } from "lodash";
class OpenMenuDirective extends BaseDirective {
match () {
match() {
const { text } = this
let result = null
result = text.match(/打开(.*)(?=(?:菜单|功能|路径))/)
if (!result) {
result = text.match(/打开(.*)(?=(?:,|,|。|))/)
}
if (result && result.length >= 2) {
this.matchResult = result[1]
}
return !!(result && result.length >= 2)
}
async excute() {
let widgets = null
if (this.data) {
} else {
widgets = this.getCompleteMenus()
if (!widgets) {
widgets = this.getPatternMenus()
}
if (!widgets) {
return "没有查找到此菜单,请检查语音是否正确"
}
if (widgets.length == 1) {
return this.handleOneSingleMenu(widgets[0])
} else {
this.data = {}
this.data.type = "widgets"
this.data.widgets = widgets
return `${this.widgetsToMsg(widgets)}`
}
}
//先判断一下是否能完全匹配一个菜单
}
async excute () {
handleOneSingleMenu(widget) {
if (widget.url) {
this.openSingleMenu(widget)
return `打开${widget.label}成功`
} else {
this.data = {}
this.data.type = "widgets"
this.data.widgets = widgets
return `你打开的${widget.label}是一个菜单组,${this.widgetsToMsg(widget.widgets)}`
}
}
widgetsToMsg (widgets) {
return `有以下${widgets.length - 1}个菜单\n${widgets.map((widget, index) => `${index + 1}.${widget.label}`).join("\n")},\n请语音确认一下打开第几个菜单`
}
getCompleteMenus() {
const result = Utils.findMenus({
name: this.matchResult
})
const { widgets } = result
return widgets.length > 0 ? widgets : null
}
getPatternMenus() {
const weights = extract(this.matchResult, 4)
let data = []
if (weights.length == 0) return null
weights.map(({ word }) => {
const name = new RegExp(word)
const result = Utils.findMenus({
name
})
if(result.widgets.length > 0) {
data = data.concat(result.widgets)
}
})
data = uniq(data)
return data.length > 0 ? data : null
}
openSingleMenu(widget) {
Utils.openMenu({widget})
}
}
......
import AwakenDirective from "./AwakenDirective"
import OpenMenuDirective from "./OpenMenuDirective"
import HomePageDirective from "./HomePageDirective"
const DirectiveTypes = [
AwakenDirective,
HomePageDirective,
OpenMenuDirective
]
class Directive {
......
......@@ -56,6 +56,32 @@ const Utils = {
}
return realLength;
},
findMenus ({ name }) {
const result = {
widgets : [],
}
window.globalConfig.widgets.map(widget => this._findMenus({widget, name , result}))
return result
},
_findMenus({widget, name , result}) {
if(widget.hideInMenu) return
if( name instanceof RegExp) {
const isPattern = name.test(widget.label)
if(isPattern) {
result.widgets.push(widget)
}
} else if(name == widget.label){
result.widgets.push(widget)
}
if(widget.widgets && Array.isArray(widget.widgets)) {
return widget.widgets.map(widget => this._findMenus({widget , name , result}))
}
},
openMenu ({widget = {}, url}) {
if(!((widget.url && widget.product) || url)) return
const _url = url || `${widget.product}/${widget.url}`
window.history.pushState(null, '', `/civbase/${_url}`);
}
};
export default Utils;
......@@ -3,22 +3,24 @@ import { useCallback, useEffect, useRef, useState } from 'react'
import { PandaRecordWebSocket } from './core'
import { message } from 'antd'
import PandaTip from './Ui/PandaTip'
import { init, cut, extract, ready } from "@congcongcai/jieba.js";
const SoundAi = props => {
const pandaRecordWebSocketRef = useRef(null)
const keyRef = useRef(null)
const [isStartRecorder , setIsStartRecorder] = useState(false)
const [isStartRecorder, setIsStartRecorder] = useState(false)
useEffect(async () => {
try {
await getIsOpenConfig()
await getKey()
await initJieBa()
event.emit("record:changeVisible", {
visible : true
visible: true
})
event.on("record:changedStaus", changeSwitch)
} catch (error){
} catch (error) {
console.warn(error)
}
return () => {
......@@ -30,34 +32,34 @@ const SoundAi = props => {
const changeSwitch = useCallback(async ({ recordData, e: checked }) => {
if (checked) {
emitSwitch({
loading : true
loading: true
})
createPandaRecordWebSocket()
const data = await pandaRecordWebSocketRef.current.start()
emitSwitch({
loading : false
loading: false
})
if(!data.isSuccess) {
if (!data.isSuccess) {
return message.info(data.msg)
}
emitSwitch({
checked : true
checked: true
})
setIsStartRecorder(true)
} else {
emitSwitch({
loading : true
loading: true
})
await destroyPandaRecorderWebSocket()
emitSwitch({
loading : false,
checked : false
loading: false,
checked: false
})
setIsStartRecorder(false)
}
}, [])
const createPandaRecordWebSocket = () => {
const createPandaRecordWebSocket = async () => {
destroyPandaRecorderWebSocket()
pandaRecordWebSocketRef.current = new PandaRecordWebSocket({
config : keyRef.current.shortSound,
......@@ -70,10 +72,28 @@ const SoundAi = props => {
}
}
})
// await testText("我需要打开铁山全景图菜单")
// await testText("我需要返回首页")
}
const testText = text => new Promise((resolve , reject) => {
setTimeout(() => {
event.emit("aiSound:frame", {
resultTextTemp: text
})
setTimeout(() => {
event.emit("aiSound:finish", {
resultText: text
})
setTimeout(() => {
resolve()
}, 500)
}, 500)
}, 500)
})
const destroyPandaRecorderWebSocket = async () => {
if(pandaRecordWebSocketRef.current) {
if (pandaRecordWebSocketRef.current) {
await pandaRecordWebSocketRef.current.destroy()
pandaRecordWebSocketRef.current = null
}
......@@ -110,9 +130,9 @@ const SoundAi = props => {
})
})
const getKey = () => new Promise((resolve , reject) => {
fetch("https://civgis.panda-water.cn/system/pandaAiSoundWorker/key.json",{
mode : "cors"
const getKey = () => new Promise((resolve, reject) => {
fetch("https://civgis.panda-water.cn/system/pandaAiSoundWorker/key.json", {
mode: "cors"
}).then(res => res.json())
.then(res => {
keyRef.current = res
......@@ -121,9 +141,18 @@ const SoundAi = props => {
reject(error)
})
})
const initJieBa = () => new Promise((resolve, reject) => {
ready().then(() => {
init()
resolve()
}).catch(() => {
reject()
})
})
return (<>
{
isStartRecorder ? <PandaTip pandaRecordWebSocketRef = {pandaRecordWebSocketRef} /> : null
isStartRecorder ? <PandaTip pandaRecordWebSocketRef={pandaRecordWebSocketRef} /> : null
}
</>)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment