feat: add McpServerInputDialog component for variable input and handling
parent
7a0daeda24
commit
f5fbbfc06c
|
|
@ -0,0 +1,62 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
width="600"
|
||||||
|
title="设置变量"
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:append-to-body="true"
|
||||||
|
>
|
||||||
|
<el-form label-position="top" ref="formRef" :model="form" require-asterisk-position="right">
|
||||||
|
<el-form-item v-for="item in input_field_list" :label="item" :key="item" :prop="item"
|
||||||
|
:rules="{ required: true, message: $t('dynamicsForm.tip.requiredMessage'), trigger: 'blur' }">
|
||||||
|
<el-input v-model="form[item]"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||||
|
<el-button type="primary" @click="submit(formRef)" :loading="loading">
|
||||||
|
{{ $t('common.save') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'refresh', value: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
const form = ref<any>({})
|
||||||
|
|
||||||
|
const input_field_list = ref<string[]>([])
|
||||||
|
|
||||||
|
function open(vars: string[]) {
|
||||||
|
dialogVisible.value = true
|
||||||
|
input_field_list.value = vars
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
emit('refresh', form.value)
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defineExpose({open})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -246,6 +246,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</NodeContainer>
|
</NodeContainer>
|
||||||
|
<McpServerInputDialog ref="mcpServerInputDialogRef" @refresh="handleMcpVariables" />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cloneDeep, set } from 'lodash'
|
import { cloneDeep, set } from 'lodash'
|
||||||
|
|
@ -256,6 +257,7 @@ import { t } from '@/locales'
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message'
|
import { MsgError, MsgSuccess } from '@/utils/message'
|
||||||
import TooltipLabel from '@/components/dynamics-form/items/label/TooltipLabel.vue'
|
import TooltipLabel from '@/components/dynamics-form/items/label/TooltipLabel.vue'
|
||||||
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
||||||
|
import McpServerInputDialog from "./component/McpServerInputDialog.vue";
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||||
import { resetUrl } from '@/utils/common'
|
import { resetUrl } from '@/utils/common'
|
||||||
|
|
@ -339,12 +341,22 @@ function getTools() {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
JSON.parse(form_data.value.mcp_servers)
|
JSON.parse(form_data.value.mcp_servers)
|
||||||
|
const vars = extractPlaceholders(form_data.value.mcp_servers)
|
||||||
|
if (vars.length > 0) {
|
||||||
|
mcpServerInputDialogRef.value.open(vars)
|
||||||
|
return
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
MsgError(t('views.applicationWorkflow.nodes.mcpNode.mcpServerTip'))
|
MsgError(t('views.applicationWorkflow.nodes.mcpNode.mcpServerTip'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
loadSharedApi({ type: 'application', systemType: apiType.value })
|
// 一切正常,获取tool
|
||||||
.getMcpTools(id, form_data.value.mcp_servers, loading)
|
_getTools(form_data.value.mcp_servers)
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getTools(mcp_servers: any) {
|
||||||
|
loadSharedApi({ type: 'application', systemType: apiType.value })
|
||||||
|
.getMcpTools(id, mcp_servers, loading)
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
form_data.value.mcp_tools = res.data
|
form_data.value.mcp_tools = res.data
|
||||||
MsgSuccess(t('views.applicationWorkflow.nodes.mcpNode.getToolsSuccess'))
|
MsgSuccess(t('views.applicationWorkflow.nodes.mcpNode.getToolsSuccess'))
|
||||||
|
|
@ -355,6 +367,47 @@ function getTools() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcpServerInputDialogRef = ref()
|
||||||
|
// 提取 JSON 中所有占位符({{...}})的变量路径
|
||||||
|
function extractPlaceholders(input: unknown): string[] {
|
||||||
|
const re = /\{\{\s*([a-zA-Z_][\w.]*)\s*\}\}/g; // 捕获 {{ path.like.this }}
|
||||||
|
const found = new Set<string>();
|
||||||
|
|
||||||
|
const visit = (v: unknown) => {
|
||||||
|
if (typeof v === 'string') {
|
||||||
|
let m: RegExpExecArray | null;
|
||||||
|
while ((m = re.exec(v)) !== null) found.add(m[1]);
|
||||||
|
} else if (Array.isArray(v)) {
|
||||||
|
v.forEach(visit);
|
||||||
|
} else if (v && typeof v === 'object') {
|
||||||
|
Object.values(v as Record<string, unknown>).forEach(visit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果传入的是 JSON 字符串,尝试解析,否则按字符串/对象处理
|
||||||
|
if (typeof input === 'string') {
|
||||||
|
try {
|
||||||
|
visit(JSON.parse(input));
|
||||||
|
} catch {
|
||||||
|
visit(input);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
visit(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...found];
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMcpVariables(vars: any) {
|
||||||
|
let mcp_servers = form_data.value.mcp_servers
|
||||||
|
for (const item in vars) {
|
||||||
|
mcp_servers = mcp_servers.replace(`{{${item}}}`, vars[item])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一切正常,获取tool
|
||||||
|
_getTools(mcp_servers)
|
||||||
|
}
|
||||||
|
|
||||||
function changeTool() {
|
function changeTool() {
|
||||||
form_data.value.mcp_server = form_data.value.mcp_tools.find(
|
form_data.value.mcp_server = form_data.value.mcp_tools.find(
|
||||||
(item: any) => item.name === form_data.value.mcp_tool,
|
(item: any) => item.name === form_data.value.mcp_tool,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue