feat(flowEditor): 添加麦克风节点语音输入功能

fixbug
钟良源 1 month ago
parent beca6752a6
commit 5d08b79904

@ -7,7 +7,8 @@ import {
paramsT, paramsT,
StepRunEventParams, StepRunEventParams,
ExecuteCurrentEventParams, ExecuteCurrentEventParams,
ReconnectRunParams ReconnectRunParams,
voiceTriggerParams
} from '@/api/interface/index'; } from '@/api/interface/index';
// 公共路径 // 公共路径
@ -144,3 +145,8 @@ export function executeCurrentEvent(params: ExecuteCurrentEventParams) {
export function reconnectRun(params: ReconnectRunParams) { export function reconnectRun(params: ReconnectRunParams) {
return axios.post(`${runPrefix}/apps/reconnect`, params); return axios.post(`${runPrefix}/apps/reconnect`, params);
} }
// 语音输入
export function voiceTrigger(data: voiceTriggerParams) {
return axios.post(`${runPrefix}/apps/voiceTrigger`, data);
}

@ -92,6 +92,13 @@ export interface flowType {
type?: string; type?: string;
} }
export interface voiceTriggerParams {
appId: string;
appInstanceId: string;
nodeId: string;
msg: string;
}
// aichat // aichat
export interface RecommendResponse { export interface RecommendResponse {
code: number; code: number;

@ -35,7 +35,7 @@ const MicrophoneNode = ({ data, id }: { data: any; id: string }) => {
{title} {title}
<NodeStatusIndicator status={nodeStatus} isVisible={isStatusVisible} /> <NodeStatusIndicator status={nodeStatus} isVisible={isStatusVisible} />
</div> </div>
<NodeContentMicrophone data={data} /> <NodeContentMicrophone data={{ ...data, nodeId: id }} />
</div> </div>
); );
}; };

@ -105,6 +105,15 @@
min-height: 10px; min-height: 10px;
} }
.node-content-box {
padding: 10px;
margin: -1px auto;
background-color: #fff;
border-top: 1px solid #ffffff;
border-left: 1px solid #cccccc;
border-right: 1px solid #cccccc;
}
.node-footer { .node-footer {
background-color: #ffffff; background-color: #ffffff;
color: #000000; color: #000000;

@ -1,9 +1,11 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import styles from '@/components/FlowEditor/node/style/baseOther.module.less'; import styles from '@/components/FlowEditor/node/style/baseOther.module.less';
import { Handle, Position } from '@xyflow/react'; import { Handle, Position } from '@xyflow/react';
import { formatDataType } from '@/utils/common'; import { formatDataType } from '@/utils/common';
import { Button } from '@arco-design/web-react'; import { Button } from '@arco-design/web-react';
import { audioService } from '@/components/audio-recognize/audio/main'; import { audioService } from '@/components/audio-recognize/audio/main';
import { voiceTrigger } from '@/api/apps';
interface NodeContentData { interface NodeContentData {
parameters?: { parameters?: {
@ -187,6 +189,8 @@ const NodeContentMicrophone = ({ data }: { data: NodeContentData }) => {
const [isRecording, setIsRecording] = useState(false); const [isRecording, setIsRecording] = useState(false);
const [resultText, setResultText] = useState(''); const [resultText, setResultText] = useState('');
const { connect, stop } = audioService(setResultText); const { connect, stop } = audioService(setResultText);
const { appRuntimeData, currentAppData } = useSelector((state: any) => state.ideContainer);
const apiIns = data.parameters?.apiIns || []; const apiIns = data.parameters?.apiIns || [];
const apiOuts = data.parameters?.apiOuts || []; const apiOuts = data.parameters?.apiOuts || [];
@ -217,8 +221,14 @@ const NodeContentMicrophone = ({ data }: { data: NodeContentData }) => {
const handleComplete = () => { const handleComplete = () => {
console.log('用户结束语音转文字'); console.log('用户结束语音转文字');
stop(); stop();
// TODO 调接口 等待后端出接口 const params = {
// voiceTrigger(params); nodeId: data.nodeId,
appId: currentAppData.id,
appInstanceId: appRuntimeData[currentAppData.id].runId,
msg: resultText || '你好'
};
if (!params.msg || !params.nodeId) return;
voiceTrigger(params);
}; };
useEffect(() => { useEffect(() => {
@ -287,6 +297,28 @@ const NodeContentMicrophone = ({ data }: { data: NodeContentData }) => {
</> </>
)} )}
<div className={styles['node-content-box']}>
<textarea
value={resultText}
placeholder="等待语音输入..."
readOnly
style={{
height: '80px',
padding: '8px',
backgroundColor: '#f7f8fa',
borderRadius: '4px',
fontSize: '12px',
lineHeight: '1.5',
color: '#4e5969',
border: '1px solid #e5e6eb',
resize: 'none',
outline: 'none',
fontFamily: 'inherit'
}}
/>
</div>
{/*footer栏*/} {/*footer栏*/}
<div className={styles['node-footer']}> <div className={styles['node-footer']}>
{!isRecording ? {!isRecording ?

@ -114,6 +114,30 @@ const codeParameters = {
'id': 'arg' 'id': 'arg'
}] }]
}; };
const microParameters = {
apiIns: [{
name: 'start',
desc: '',
dataType: '',
defaultValue: ''
}],
apiOuts: [{
name: 'done',
desc: '',
dataType: '',
defaultValue: ''
}],
dataIns: [],
dataOuts: [
{
'arrayType': null,
'dataType': 'STRING',
'defaultValue': 'STRING',
'desc': '输出参数',
'id': 'out'
}
]
};
// 定义节点基本信息 画布中添加的组件列表依赖这里 // 定义节点基本信息 画布中添加的组件列表依赖这里
const nodeDefinitions = [ const nodeDefinitions = [
@ -155,6 +179,9 @@ export const localNodeData = nodeDefinitions.map(({ nodeName, nodeType, nodeGrou
else if (nodeType === 'CODE') { else if (nodeType === 'CODE') {
parameters = codeParameters; parameters = codeParameters;
} }
else if (nodeType === 'MICRO') {
parameters = microParameters;
}
return { return {
nodeName, nodeName,

Loading…
Cancel
Save