智能交互

This commit is contained in:
zhanghao 2026-07-08 11:09:51 +08:00
parent 9d37c56b8d
commit 587ba3482e
21 changed files with 267 additions and 33 deletions

View File

@ -61,3 +61,11 @@ export function flowStop(instId) {
method: 'post' method: 'post'
}) })
} }
export function getArmStatus(params) {
return request({
url: '/api/arm/getPose',
method: 'get',
params: params
})
}

View File

@ -69,6 +69,7 @@
<el-form-item label="模型" prop="voice"> <el-form-item label="模型" prop="voice">
<el-select v-model="form.model" placeholder="模型"> <el-select v-model="form.model" placeholder="模型">
<el-option label="科大讯飞" value="科大讯飞" /> <el-option label="科大讯飞" value="科大讯飞" />
<el-option label="火山引擎" value="火山引擎" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -196,7 +197,7 @@ const handleClose = (tag) => {
const form = ref({ const form = ref({
tags: [], tags: [],
model: '科大讯飞', model: '科大讯飞',
voice: 'xiaoyan', voice: 'x4_xiaoyan',
speed: 50, speed: 50,
volume: 50, volume: 50,
pitch: 50, pitch: 50,
@ -236,7 +237,10 @@ const dialectOption = ref([
const voiceOption = ref([ const voiceOption = ref([
{ {
label: '女声', label: '女声',
value: 'xiaoyan' value: 'x4_xiaoyan'
}, {
label: '男声',
value: 'x4_lingbosong'
} }
]) ])

View File

@ -119,7 +119,7 @@ class CustomFlowHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = 'none'; style.stroke = 'none';
style.hover.stroke = 'none'; // style.hover.stroke = 'none';
return style; return style;
} }
} }

View File

@ -59,14 +59,14 @@ defineExpose({ confirmSave })
// / // /
const handleSaveSuccess = () => { const handleSaveSuccess = () => {
emitter.emit('setProperties', { id: props.data.id }) emitter.emit('setProperties', { id: props.data.id })
emitter.emit("throwAnError", { id: props.data.id, hasError: false }); emitter.emit("throwAnError", { id: props.data.id, hasError: false, type: props.data.type });
// //
emits('close') emits('close')
} }
const handleSaveError = () => { const handleSaveError = () => {
emitter.emit('setProperties', { id: props.data.id }) emitter.emit('setProperties', { id: props.data.id })
emitter.emit("throwAnError", { id: props.data.id, hasError: true }); emitter.emit("throwAnError", { id: props.data.id, hasError: true, type: props.data.type });
emits('close') emits('close')
} }

View File

@ -542,8 +542,16 @@ const initFlow = () => {
keys: ["backspace", "delete"], // keys: ["backspace", "delete"], //
callback: () => { callback: () => {
const activeElem = document.activeElement; const activeElem = document.activeElement;
if (activeElem.tagName === "INPUT" || activeElem.tagName === "TEXTAREA") { if (["INPUT", "TEXTAREA"].includes(activeElem.tagName)) {
return; // return false
}
const { nodes } = lf.getSelectElements();
//
const hasProtectedNode = nodes.some(node => ["start", "end"].includes(node.type));
if (hasProtectedNode) {
lf.selectElementById(null);
return false;
} }
const { nodes, edges } = lf.getSelectElements(); const { nodes, edges } = lf.getSelectElements();
@ -555,7 +563,7 @@ const initFlow = () => {
if (hasProtectedNode) { if (hasProtectedNode) {
lf.selectElementById(null); // lf.selectElementById(null); //
return; // return false; //
} }
// //
@ -571,7 +579,7 @@ const initFlow = () => {
// //
lf.deleteEdgeByNodeId(node.id); lf.deleteEdgeByNodeId(node.id);
}); });
return; return false;
} }
if (nodes.length === 0 && edges.length > 0) { if (nodes.length === 0 && edges.length > 0) {
edges.forEach((node) => { edges.forEach((node) => {
@ -584,12 +592,12 @@ const initFlow = () => {
{ {
keys: ["ctrl+z"], // keys: ["ctrl+z"], //
callback: () => { callback: () => {
return false; return true;
}, },
}, },
{ {
keys: ["ctrl+shift+z"], keys: ["ctrl+shift+z"],
callback: () => false, callback: () => true,
}, },
], ],
}, },
@ -789,8 +797,23 @@ onMounted(() => {
emitter.on("throwAnError", (data) => { emitter.on("throwAnError", (data) => {
// //
const { id, hasError } = data; const { id, hasError, type } = data;
const element = document.getElementsByClassName(`node__container ${id}`)[0].parentElement; let element
if (type === 'loop') {
const tt = document.getElementsByClassName(`group__container ${id}`)[0];
if (tt?.parentElement) {
element = tt.parentElement;
} else {
element = tt
}
} else {
const tt = document.getElementsByClassName(`node__container ${id}`)[0]
if (tt?.parentElement) {
element = tt.parentElement;
} else {
element = tt
}
}
if (hasError) { if (hasError) {
if (!nodeErrorList.value.includes(id)) { if (!nodeErrorList.value.includes(id)) {
nodeErrorList.value.push(id); nodeErrorList.value.push(id);
@ -889,10 +912,12 @@ onUnmounted(() => {
.node__container { .node__container {
border-color: #8dc99d; border-color: #8dc99d;
// pointer-events: none;
} }
.group__container { .group__container {
border-color: #8dc99d; border-color: #8dc99d;
// pointer-events: none;
} }
} }
} }

View File

@ -181,7 +181,7 @@ class EndNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -198,7 +198,7 @@ class ServiceNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -180,7 +180,7 @@ class StartNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = 'none'; style.stroke = 'none';
style.hover.stroke = 'none'; // style.hover.stroke = 'none';
return style; return style;
} }
} }

View File

@ -198,7 +198,7 @@ class CodeNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -204,7 +204,7 @@ class CurrentLoopNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -198,7 +198,7 @@ class HttpNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -45,7 +45,6 @@ class loopBodyModel extends GroupNodeModel {
// 计算子节点的包围盒(包含所有子节点的最小矩形区域) // 计算子节点的包围盒(包含所有子节点的最小矩形区域)
getChildrenBBox() { getChildrenBBox() {
const children = this.getAllValidChildren(this.children, this.graphModel) const children = this.getAllValidChildren(this.children, this.graphModel)
console.log('children', children)
// Array.from(this.children).forEach((id) => { // Array.from(this.children).forEach((id) => {
// const node = this.graphModel.getNodeModelById(id) // const node = this.graphModel.getNodeModelById(id)
// if (node) { // if (node) {
@ -109,14 +108,16 @@ class loopBodyModel extends GroupNodeModel {
return [ return [
{ {
x: x + width / 2 , x: x + width / 2 ,
y: y + height / 2, // y: y + height / 2,
y:y,
name: "right", name: "right",
id: "".concat(this.id, "_1"), id: "".concat(this.id, "_1"),
properties: { connectionType: "source" }, properties: { connectionType: "source" },
}, },
{ {
x: x - width / 2, x: x - width / 2,
y: y + height / 2, // y: y + height / 2,
y:y,
name: "left", name: "left",
id: "".concat(this.id, "_3"), id: "".concat(this.id, "_3"),
properties: { connectionType: "target" }, properties: { connectionType: "target" },
@ -241,6 +242,13 @@ class loopBodyView extends HtmlNode {
return svgH('g', {}, anchorShapes); return svgH('g', {}, anchorShapes);
} }
getOutlineStyle() {
const style = super.getOutlineStyle();
style.stroke = "none";
// style.hover.stroke = "none";
return style;
}
/** /**
* HTML 内容设置到指定的根元素上 * HTML 内容设置到指定的根元素上
* @param rootEl 根元素 * @param rootEl 根元素

View File

@ -87,13 +87,13 @@ onUnmounted(() => {
.group__container { .group__container {
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 420px; // min-height: 420px;
background: #fff; background: #fff;
padding: 12px; padding: 12px;
cursor: default; cursor: default;
border-radius: 12px; border-radius: 12px;
border: 2px solid white; border: 2px solid white;
box-shadow: 0 5px 15px 0#00000008; // box-shadow: 0 5px 15px 0#00000008;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;

View File

@ -198,7 +198,7 @@ class SdAgentNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -198,7 +198,7 @@ class SleepNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -176,7 +176,7 @@ class StopLoopHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -171,7 +171,7 @@ class SubEndNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -170,7 +170,7 @@ class SubStartNodeHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -303,7 +303,7 @@ class SwitchHtmlModel extends HtmlNodeModel {
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = "none"; style.stroke = "none";
style.hover.stroke = "none"; // style.hover.stroke = "none";
return style; return style;
} }
} }

View File

@ -192,12 +192,13 @@
</el-form> </el-form>
<div v-if="form.sceneType && form.sceneType != 1"> <div v-if="form.sceneType && form.sceneType != 1">
<div>语料配置({{ form.sceneType == 2 ? "单次" : "连续" }})</div> <div>语料配置({{ form.sceneType == 2 ? "单次" : "连续" }})</div>
<Setting <!-- <Setting
type="1" type="1"
v-if="form.sceneType == 2" v-if="form.sceneType == 2"
:corpusIds="selectCorpusIds" :corpusIds="selectCorpusIds"
@updateSelectRows="getSelectRows" @updateSelectRows="getSelectRows"
/> /> -->
<Single v-if="form.sceneType == 2" :corpusIds="selectCorpusIds" @updateSelectRows="getSelectRows" />
<Setting <Setting
type="0" type="0"
v-if="form.sceneType == 3" v-if="form.sceneType == 3"
@ -228,6 +229,7 @@ import Setting from "./setting.vue";
import { onMounted } from "vue"; import { onMounted } from "vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useContainerHeight } from "@/hooks/tableHeight"; import { useContainerHeight } from "@/hooks/tableHeight";
import Single from "./single.vue";
const topContainerRef = ref(); const topContainerRef = ref();
const containerHeight = useContainerHeight(topContainerRef); const containerHeight = useContainerHeight(topContainerRef);
@ -415,7 +417,7 @@ const getWakeList = () => {
}; };
const getSelectRows = (arr) => { const getSelectRows = (arr) => {
const corpusIds = arr.map((item) => item.parentId); const corpusIds = arr.map((item) => item.id);
form.value.corpusIds = corpusIds.toString(); form.value.corpusIds = corpusIds.toString();
}; };

View File

@ -0,0 +1,187 @@
<template>
<div>
<div class="btn-container">
<el-button type="primary" @click="openDialog">配置语料</el-button>
</div>
<el-table :data="selectList" height="260">
<el-table-column
label="语料类型"
align="center"
prop="categoryName"
width="150"
show-overflow-tooltip />
<el-table-column
label="语音文本"
align="center"
prop="text"
width="150"
show-overflow-tooltip
/>
<el-table-column label="音色" align="center" prop="voice" />
<el-table-column label="语种" align="center" prop="language" />
</el-table>
<el-dialog title="选择语料" v-model="open" width="700px">
<el-form
:model="queryParams"
ref="queryRef"
:inline="true"
label-width="68px"
>
<el-form-item label="语料文本">
<el-input
v-model="queryParams.text"
placeholder="请输入语料名称"
clearable
@keyup.enter="getList"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="getList"
>搜索</el-button
>
<el-button icon="Refresh" @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
<el-table
ref="tableRef"
:data="corpusList"
:tree-props="{ checkStrictly: true }"
:row-key="rowKey"
:height="400"
>
<el-table-column
type="selection"
width="55"
align="center"
v-show="false"
:selectable="selectable"
/>
<el-table-column
label="语料类型"
align="center"
prop="categoryName"
min-width="100"
show-overflow-tooltip
/>
<el-table-column
label="语音文本"
align="center"
prop="text"
min-width="200"
show-overflow-tooltip
/>
<el-table-column label="音色" align="center" prop="voice" />
<el-table-column label="语种" align="center" prop="language" />
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { onMounted } from "vue";
// import { listCorpus, getBatchCorpus } from "@/api/vi/corpus";
import { getCorpusListApi } from '@/api/corpusManger/corpus.js'
const props = defineProps({
corpusIds: {
type: String,
default: "",
},
});
const emits = defineEmits(["updateSelectRows"]);
const selectList = ref([]);
const corpusList = ref([]);
const open = ref(false);
const openDialog = () => {
open.value = true;
setTimeout(() => {
toggleRowSelection();
}, 100);
}
const toggleRowSelection = () => {
if (selectList.value.length > 0) {
corpusList.value.forEach((row) => {
selectList.value.forEach((item) => {
if ( item.id === row.id ) {
tableRef.value.toggleRowSelection(row, true);
}
})
})
}
}
const selectable = (row) => {
if (row.continuous + "" === "0") {
return false;
} else {
return true;
}
};
const queryParams = ref({
pageNum: 1,
pageSize: 100000,
text: ''
})
const getList = async () => {
const res = await getCorpusListApi(queryParams.value)
if (res.code === 0) {
corpusList.value = res.rows
}
};
const resetForm = () => {
queryParams.value.text = ''
getList()
}
const tableRef = ref();
const submitForm = () => {
const rows = tableRef.value.getSelectionRows();
selectList.value = rows;
open.value = false;
emits("updateSelectRows", rows);
resetForm()
};
const cancel = () => {
open.value = false;
resetForm()
};
const getSelectList = async (corpusIds) => {
const res = await getCorpusListApi({
...queryParams.value,
text: '',
ids: corpusIds
})
if (res.code === 0) {
selectList.value = res.rows
}
};
onMounted(() => {
getList();
if (props.corpusIds) {
getSelectList(props.corpusIds.split(","));
}
});
</script>
<style lang="scss" scoped>
.btn-container {
text-align: right;
margin-bottom: 12px;
}
</style>