diff --git a/src/api/device/flow.js b/src/api/device/flow.js index b3e3b76..e1ad731 100644 --- a/src/api/device/flow.js +++ b/src/api/device/flow.js @@ -1,55 +1,63 @@ -import request from '@/utils/request' - -// 发布流程 -export function flowDeploy(data) { - return request({ - url: '/flow/publish', - method: 'post', - data: data - }) -} - -export function flowExecute(data) { - return request({ - url: '/flow/execute', - method: 'post', - data: data - }) -} - -export function flowExecuteTrial(data) { - return request({ - url: '/flow/executeTrial', - method: 'post', - data: data - }) -} - -export function flowView(data) { - return request({ - url: '/flow/view', - method: 'post', - data: data - }) -} - -export function flowPause(instId) { - return request({ - url: `/flow/pause/${instId}`, - method: 'post' - }) -} - -export function flowResume(instId) { - return request({ - url: `/flow/resume/${instId}`, - method: 'post' - }) -} - -export function flowStop(instId) { - return request({ - url: `/flow/stop/${instId}`, - method: 'post' - }) +import request from '@/utils/request' + +// 发布流程 +export function flowDeploy(data) { + return request({ + url: '/flow/publish', + method: 'post', + data: data + }) +} + +export function flowExecute(data) { + return request({ + url: '/flow/execute', + method: 'post', + data: data + }) +} + +export function flowAction(data) { + return request({ + url: '/flow/action', + method: 'post', + data: data + }) +} + +export function flowExecuteTrial(data) { + return request({ + url: '/flow/executeTrial', + method: 'post', + data: data + }) +} + +export function flowView(data) { + return request({ + url: '/flow/view', + method: 'post', + data: data + }) +} + +export function flowPause(instId) { + return request({ + url: `/flow/pause/${instId}`, + method: 'post' + }) +} + +export function flowResume(instId) { + return request({ + url: `/flow/resume/${instId}`, + method: 'post' + }) +} + +export function flowStop(instId) { + return request({ + url: `/flow/stop/${instId}`, + method: 'post' + }) } \ No newline at end of file diff --git a/src/api/device/microphone.js b/src/api/device/microphone.js new file mode 100644 index 0000000..e5fa841 --- /dev/null +++ b/src/api/device/microphone.js @@ -0,0 +1,46 @@ +import request from '@/utils/request' + +// 开始录音 +export function startMicrophoneApi(data) { + return request({ + url: '/api/Microphone/start', + method: 'post', + params: data + }) +} + +// 暂停录音 +export function pauseMicrophoneApi(data) { + return request({ + url: '/api/Microphone/pause', + method: 'post', + params: data + }) +} + +// 恢复录音 +export function resumeMicrophoneApi(data) { + return request({ + url: '/api/Microphone/resume', + method: 'post', + params: data + }) +} + +// 停止录音 +export function stopMicrophoneApi(data) { + return request({ + url: '/api/Microphone/stop', + method: 'post', + params: data + }) +} + +// 播放音频 +export function playSpeaker(data) { + return request({ + url: '/api/Speaker/play', + method: 'post', + params: data + }) +} \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index dbabe71..5c17dd3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,6 +1,7 @@ import { createWebHistory, createRouter } from "vue-router"; /* Layout */ import Layout from "@/layout"; +import path from "path"; /** * Note: 路由配置项 @@ -92,7 +93,14 @@ export const constantRoutes = [ name: "灵巧手示教", meta: { title: "灵巧手详情" }, hidden: true, - }, + },{ + path: "microphone/:id", + component: () => + import("@/views/device/register/components/Microphone/index.vue"), + name: "麦克风示教", + meta: { title: "麦克风详情" }, + hidden: true, + } ], }, { diff --git a/src/utils/flow.js b/src/utils/flow.js index 94f7557..44a9db8 100644 --- a/src/utils/flow.js +++ b/src/utils/flow.js @@ -127,6 +127,34 @@ export const formatTableData = (arr, data = {}) => { } export const addNewEdge = (nodeId) => { + const { edges } = lf.getGraphData(); + const ttt = edges.slice(); // 浅拷贝(比 JSON 深拷贝高效 10x+) + + const edgesToDelete = ttt.filter(_edge => + _edge.sourceNodeId === nodeId || _edge.targetNodeId === nodeId + ); + + edgesToDelete.forEach(edge => lf.deleteEdge(edge.id)); + + if (window.addNewEdgeTimer) { + clearTimeout(window.addNewEdgeTimer); // 清理上一次未执行的定时器 + } + + window.addNewEdgeTimer = setTimeout(() => { + edgesToDelete.forEach(item => { + lf.addEdge({ + type: "bezier", + sourceNodeId: item.sourceNodeId, + targetNodeId: item.targetNodeId, + sourceAnchorId: item.sourceAnchorId, + targetAnchorId: item.targetAnchorId + }); + }) + delete window.addNewEdgeTimer; + }, 50) +} + +export const newEdge = (nodeId) => { const { edges } = lf.getGraphData(); const arr = JSON.parse(JSON.stringify(edges)) arr.forEach(_edge => { @@ -144,6 +172,22 @@ export const addNewEdge = (nodeId) => { }) } +export const initNodeZoom = (modelId, nodeZoom, className, init=false) => { + const nodes = document.getElementsByClassName(modelId) + if (nodes.length > 0) { + const node = nodes[0] + const parent = node.closest(className); + if (nodeZoom) { + parent.style.width = '680px' + } else { + parent.style.width = '380px' + } + if (!init) { + addNewEdge(modelId) + } + } +} + export const getInputNumber = (nodeId) => { const data = lf.getGraphData(); let flag = false diff --git a/src/views/device/profile/index.vue b/src/views/device/profile/index.vue index c76ce62..ee10b2b 100644 --- a/src/views/device/profile/index.vue +++ b/src/views/device/profile/index.vue @@ -1,510 +1,508 @@ - - - + + + diff --git a/src/views/device/register/components/Microphone/index.vue b/src/views/device/register/components/Microphone/index.vue new file mode 100644 index 0000000..fa76496 --- /dev/null +++ b/src/views/device/register/components/Microphone/index.vue @@ -0,0 +1,225 @@ + + + diff --git a/src/views/device/register/index.vue b/src/views/device/register/index.vue index 986fb2d..7520614 100644 --- a/src/views/device/register/index.vue +++ b/src/views/device/register/index.vue @@ -378,6 +378,10 @@ function handleControl(row) { const fullPath = `${row.deviceModel}/${row.id}`; // 构造路由路径 router.push({ path: fullPath, + query: { + terminalId: row.idDeDeviceTerminalConfig, + deviceId: row.deviceCode + } }); // 使用路由跳转 // intoControlPage(`/${row.deviceModel}`, `${row.id}`) } diff --git a/src/views/flow/components/NodeTitle.vue b/src/views/flow/components/NodeTitle.vue index b7f61b4..b60b2dd 100644 --- a/src/views/flow/components/NodeTitle.vue +++ b/src/views/flow/components/NodeTitle.vue @@ -1,171 +1,239 @@ - - - \ No newline at end of file + + + diff --git a/src/views/flow/config.js b/src/views/flow/config.js index f7fce53..d75dd78 100644 --- a/src/views/flow/config.js +++ b/src/views/flow/config.js @@ -16,6 +16,8 @@ import planSvg from './icon/plan.svg' import awakenSvg from './icon/awaken.svg' import dialogueSvg from './icon/dialogue.svg' import audioSvg from './icon/audio.svg' +import touchSvg from './icon/touch.svg' +import expressionSvg from './icon/expression.svg' import { v4 as randomUUID } from 'uuid' @@ -40,6 +42,11 @@ export const lfConfig = { // foldSize: 30, // 折叠后显示的图标尺寸 // }, edgeType: "bezier", + zoomConfig: { + min: 0.05, // 最小缩放比例(支持更小值,如 0.01,但不建议过小) + max: 3, // 最大缩放比例(可自定义) + step: 0.1 // 每次滚轮缩放的步长(默认 0.1) + }, style: { anchor: { show: true, // 强制全局锚点显示 @@ -73,11 +80,39 @@ export const registerCustomizeNode = (lf) => { }; const deviceOptions = () => { - return ['cam1', 'cam2', 'cam3', 'cam4'] + return [{ + value: 'cam1', + label: 'cam1' + }, { + value: 'cam2', + label: 'cam2' + }, { + value: 'cam3', + label: 'cam3' + }, { + value: 'cam4', + label: 'cam4' + }] } const audioOptions = () => { - return ['spk1'] + return [{ + value: 'spk1', + label: 'spk1' + }] +} + +const expressOptions = () => { + return [{ + value: 1, + label: '高兴' + }, { + value: 2, + label: '惊讶' + }, { + value: 3, + label: '疲惫' + }] } export const collapseList = [ @@ -90,6 +125,7 @@ export const collapseList = [ type: "serviceNode", desc: "在获取相机照片时,需要先启动相机", action: 'CAMERA_START', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -101,6 +137,7 @@ export const collapseList = [ type: "serviceNode", desc: "获取相机拍摄的照片", action: 'CAMERA_GETRGBIMAGE', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -113,6 +150,7 @@ export const collapseList = [ type: "serviceNode", desc: "获取相机照片后,关闭该相机", action: 'CAMERA_STOP', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -129,6 +167,7 @@ export const collapseList = [ type: "serviceNode", desc: "开启摄像头,并开始录像", action: 'CAMERA_RECORDING_START', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -140,6 +179,7 @@ export const collapseList = [ type: "serviceNode", desc: "停止录像,并关闭摄像头", action: 'CAMERA_RECORDING_STOP', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -224,6 +264,7 @@ export const collapseList = [ type: "serviceNode", desc: "用于启动麦克风的节点", action: 'MICROPHONE_START', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -235,6 +276,7 @@ export const collapseList = [ type: "serviceNode", desc: "用于停止麦克风的节点", action: 'MICROPHONE_START', + nodeType: 'EDGE', nodeParams: [ { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } ], @@ -262,6 +304,7 @@ export const collapseList = [ type: "serviceNode", desc: "用于获取触控坐标的节点", action: 'TOUCH_COORDINATES', + nodeType: "LLM", nodeParams: [ { name: "targetFeature", type: "input", input: "运动模式", disabled: true }, { name: "manufacturer", type: "input", input: "xiaomi", disabled: true }, @@ -275,6 +318,7 @@ export const collapseList = [ type: "serviceNode", desc: "将指令文本(text)处理合成语音,输出语音路径(audioPath)", action: 'GENERATE_ADVANCED_AUDIO', + nodeType: "LLM", outputType: 'json', nodeParams: [{ name: 'text', type: "input", input: "", disabled: true }], outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}] @@ -284,6 +328,7 @@ export const collapseList = [ type: "serviceNode", desc: "意图识别,输出类型(type) 1: 语音交互 2: 触控交互 3: 闲聊 4: 知识问答", action: 'INTENT_RECOGNITION', + nodeType: "LLM", outputType: 'json', nodeParams: [{ name: 'text', type: "input", input: "", disabled: true }], outputParams: [{ name: 'type', type: 'string', desc: '1:语音交互 2:触控交互 3: 闲聊 4:知识问答', disabled: true}] @@ -312,6 +357,7 @@ export const collapseList = [ type: "serviceNode", desc: "唤醒语料处理,输入唤醒语料(wakeCorpus),输出语音路径(audioPath)", action: 'VI_CORPUS_WAKE', + nodeType: "EDGE", outputType: 'json', nodeParams: [{ name: 'wakeCorpus', type: "input", input: "", disabled: true }], outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}] @@ -322,6 +368,7 @@ export const collapseList = [ type: "serviceNode", desc: "测试语料-单次对话语料处理,输入单次对话语料(testCorpus),输出语音路径(audioPath)", action: 'VI_CORPUS_SINGLE', + nodeType: "EDGE", outputType: 'json', nodeParams: [{ name: 'testCorpus', type: "input", input: "", disabled: true }], outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}] @@ -332,6 +379,7 @@ export const collapseList = [ type: "serviceNode", desc: "测试语料-连续对话语料处理,输入连续对话语料(testCorpus),输出语音路径(audioPath)", action: 'VI_CORPUS_CONTINUOUS', + nodeType: "EDGE", outputType: 'json', nodeParams: [{ name: 'testCorpus', type: "input", input: "", disabled: true }], outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}] @@ -342,6 +390,7 @@ export const collapseList = [ type: "serviceNode", desc: "用于播放语料的节点,需要输入语音路径(audioPath)和播放语音的设备id(deviceId)", action: 'VI_PLAY_CORPUS', + nodeType: "EDGE", outputType: 'json', nodeParams: [ { name: 'audioPath', type: "input", input: "", disabled: true }, @@ -350,4 +399,59 @@ export const collapseList = [ } ], }, + { + collapseTitle: "触控交互", + nodeList: [ + { + icon: touchSvg, + name: "触控", + type: "serviceNode", + desc: "去触控坐标的点位", + action: 'TOUCH', + nodeType: "EDGE", + nodeParams: [ + { name: "deviceId", type: "input", input: "", disabled: true }, + { name: "touchParams", type: "input", input: "", disabled: true } + ], + outputType: 'json', + }, + { + icon: expressionSvg, + name: "开始说话", + type: "serviceNode", + desc: "控制机器人说话", + action: 'BIO_HEAD_SPEAK_START', + nodeType: "EDGE", + nodeParams: [ + { name: "deviceId", type: "input", input: "", disabled: true } + ], + outputType: 'json', + }, + { + icon: expressionSvg, + name: "停止说话", + type: "serviceNode", + desc: "停止机器人说话", + action: 'BIO_HEAD_SPEAK_STOP', + nodeType: "EDGE", + nodeParams: [ + { name: "deviceId", type: "input", input: "", disabled: true } + ], + outputType: 'json', + }, + { + icon: expressionSvg, + name: "表情", + type: "serviceNode", + desc: "控制机器人的面部表情", + action: 'BIO_HEAD_SPECIAL_EXPRESSION', + nodeType: "EDGE", + nodeParams: [ + { name: "deviceId", type: "input", input: "", disabled: true }, + { name: "expressKey", type: "input",componentType: 'select', selectOptions: expressOptions(), disabled: true }, + ], + outputType: 'json', + }, + ], + }, ] diff --git a/src/views/flow/icon/dialogue.svg b/src/views/flow/icon/dialogue.svg index e3481ff..b208067 100644 --- a/src/views/flow/icon/dialogue.svg +++ b/src/views/flow/icon/dialogue.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/views/flow/icon/expression.svg b/src/views/flow/icon/expression.svg new file mode 100644 index 0000000..ae84256 --- /dev/null +++ b/src/views/flow/icon/expression.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/views/flow/icon/touch.svg b/src/views/flow/icon/touch.svg new file mode 100644 index 0000000..44a14a5 --- /dev/null +++ b/src/views/flow/icon/touch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/views/flow/index.vue b/src/views/flow/index.vue index c0541a3..612c036 100644 --- a/src/views/flow/index.vue +++ b/src/views/flow/index.vue @@ -1,7 +1,7 @@ diff --git a/src/views/flow/nodes/common/serviceNode.vue b/src/views/flow/nodes/common/serviceNode.vue index dab8b6c..3fa852d 100644 --- a/src/views/flow/nodes/common/serviceNode.vue +++ b/src/views/flow/nodes/common/serviceNode.vue @@ -1,32 +1,46 @@ - - + + + + + diff --git a/src/views/flow/nodes/function/switch.vue b/src/views/flow/nodes/function/switch.vue index 05b538b..45aebf7 100644 --- a/src/views/flow/nodes/function/switch.vue +++ b/src/views/flow/nodes/function/switch.vue @@ -1,440 +1,558 @@ - - - \ No newline at end of file + + + diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue index 6cd0a93..d6ed77f 100644 --- a/src/views/system/menu/index.vue +++ b/src/views/system/menu/index.vue @@ -1,452 +1,461 @@ - - - + + + diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue index 81b98dc..02e8048 100644 --- a/src/views/system/role/index.vue +++ b/src/views/system/role/index.vue @@ -1,584 +1,593 @@ - - - + + + diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 04d482c..9cd3e8d 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -1,538 +1,547 @@ - - - + + + diff --git a/src/views/test/configs/Run.vue b/src/views/test/configs/Run.vue index 95d1b4b..a5a0c07 100644 --- a/src/views/test/configs/Run.vue +++ b/src/views/test/configs/Run.vue @@ -48,7 +48,7 @@