mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: add McpServerInputDialog component for variable input and handling
This commit is contained in:
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>
|
||||
</template>
|
||||
</NodeContainer>
|
||||
<McpServerInputDialog ref="mcpServerInputDialogRef" @refresh="handleMcpVariables" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { cloneDeep, set } from 'lodash'
|
||||
|
|
@ -256,6 +257,7 @@ import { t } from '@/locales'
|
|||
import { MsgError, MsgSuccess } from '@/utils/message'
|
||||
import TooltipLabel from '@/components/dynamics-form/items/label/TooltipLabel.vue'
|
||||
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
||||
import McpServerInputDialog from "./component/McpServerInputDialog.vue";
|
||||
import { useRoute } from 'vue-router'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
import { resetUrl } from '@/utils/common'
|
||||
|
|
@ -339,12 +341,22 @@ function getTools() {
|
|||
}
|
||||
try {
|
||||
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) {
|
||||
MsgError(t('views.applicationWorkflow.nodes.mcpNode.mcpServerTip'))
|
||||
return
|
||||
}
|
||||
loadSharedApi({ type: 'application', systemType: apiType.value })
|
||||
.getMcpTools(id, form_data.value.mcp_servers, loading)
|
||||
// 一切正常,获取tool
|
||||
_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) => {
|
||||
form_data.value.mcp_tools = res.data
|
||||
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() {
|
||||
form_data.value.mcp_server = form_data.value.mcp_tools.find(
|
||||
(item: any) => item.name === form_data.value.mcp_tool,
|
||||
|
|
|
|||
Loading…
Reference in New Issue