增加拖拽添加连接的功能

This commit is contained in:
锦恢 2025-05-22 16:04:00 +08:00
parent fed2e6d27c
commit 043ca8ce1d
4 changed files with 133 additions and 30 deletions

View File

@ -3,10 +3,12 @@
## [main] 0.1.0 ## [main] 0.1.0
- 新特性:支持同时连入多个 mcp server - 新特性:支持同时连入多个 mcp server
- 新特性:更新协议内容,支持 streamable http 协议,未来将逐步取代 SSE 的连接方式 - 新特性:更新协议内容,支持 streamable http 协议,未来将逐步取代 SSE 的连接方式
- 对于 uv 创建的 py 项目进行特殊支持:自动初始化项目,并将 mcp 定向到 .venv/bin/mcp 中,不再需要用户全局安装 mcp - impl issue#16:对于 uv 创建的 py 项目进行特殊支持,自动初始化项目,并将 mcp 定向到 .venv/bin/mcp 中,不再需要用户全局安装 mcp
- 对于 npm 创建的 js/ts 项目进行特殊支持:自动初始化项目 - 对于 npm 创建的 js/ts 项目进行特殊支持:自动初始化项目
- 去除了 websearch 的设置,增加了 parallel_tool_calls 的设置parallel_tool_calls 默认为 true代表 允许模型在单轮回复中调用多个工具 - 去除了 websearch 的设置,增加了 parallel_tool_calls 的设置parallel_tool_calls 默认为 true代表 允许模型在单轮回复中调用多个工具
- 重构了 openmcp 连接模块的基础设施,基于新的技术设施实现了更加详细的连接模块的日志系统 - 重构了 openmcp 连接模块的基础设施,基于新的技术设施实现了更加详细的连接模块的日志系统.
- impl issue#15:无法复制
- impl issue#14:增加日志清除按钮
## [main] 0.0.9 ## [main] 0.0.9
- 修复 0.0.8 引入的bugsystem prompt 返回的是索引而非真实内容 - 修复 0.0.8 引入的bugsystem prompt 返回的是索引而非真实内容

View File

@ -1,28 +1,28 @@
<template> <template>
<el-scrollbar> <el-scrollbar>
<div class="connection-container"> <div class="connection-container" @dragover.prevent="handleDragOver" @drop.prevent="handleDrop">
<div class="connect-panel-container left" <div v-if="isDraging" class="drag-mask">
:ref="el => client.connectionSettingRef = el" <span class="iconfont icon-connect"></span>
> <span>拖拽以填充连接参数</span>
<ConnectionMethod :index="props.index" /> </div>
<ConnectionArgs :index="props.index" /> <div class="connect-panel-container left" :ref="el => client.connectionSettingRef = el">
<ConnectionEnvironment :index="props.index" /> <ConnectionMethod :index="props.index" />
<ConnectionArgs :index="props.index" />
<ConnectionEnvironment :index="props.index" />
<div class="connect-action"> <div class="connect-action">
<el-button type="primary" size="large" :loading="isLoading" :disabled="!client.connectionResult" <el-button type="primary" size="large" :loading="isLoading" :disabled="!client.connectionResult"
@click="connect()"> @click="connect()">
<span class="iconfont icon-connect" v-if="!isLoading"></span> <span class="iconfont icon-connect" v-if="!isLoading"></span>
{{ t('connect.appearance.connect') }} {{ t('connect.appearance.connect') }}
</el-button> </el-button>
</div>
</div>
<div class="connect-panel-container right" :ref="el => client.connectionLogRef = el">
<ConnectionLog :index="props.index" />
</div> </div>
</div> </div>
<div class="connect-panel-container right"
:ref="el => client.connectionLogRef = el"
>
<ConnectionLog :index="props.index" />
</div>
</div>
</el-scrollbar> </el-scrollbar>
</template> </template>
@ -67,6 +67,60 @@ async function connect() {
isLoading.value = false; isLoading.value = false;
} }
const isDraging = ref(false);
let dragHandler: number;
function handleDragOver(event: DragEvent) {
event.preventDefault();
clearTimeout(dragHandler);
isDraging.value = true;
dragHandler = setTimeout(() => {
isDraging.value = false;
}, 100);
}
function getLaunchCommand(fileName: string) {
const ext = fileName.split('.').pop()?.toLowerCase();
switch (ext) {
case 'py':
return `mcp run ${fileName}`;
case 'js':
return `node ${fileName}`;
default:
return fileName;
}
}
function handleDrop(event: DragEvent) {
event.preventDefault();
const dragedFilePath = event.dataTransfer?.getData('text/plain') || '';
if (dragedFilePath) {
const path = dragedFilePath.replace(/\\/g, '/');
const coms = path.split('/');
const fileName = coms[coms.length - 1];
const cwd = coms.slice(0, coms.length - 1).join('/');
const command = getLaunchCommand(fileName);
client.value.connectionArgs.connectionType = 'STDIO';
client.value.connectionArgs.commandString = command;
client.value.connectionArgs.cwd = cwd;
}
isDraging.value = false;
// const files = event.dataTransfer?.files;
// if (files && files.length > 0) {
// for (let i = 0; i < files.length; i++) {
// console.log(':', files[i]);
// }
// }
}
</script> </script>
<style> <style>
@ -147,4 +201,25 @@ async function connect() {
.connect-action { .connect-action {
padding: 10px; padding: 10px;
} }
.drag-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
font-size: 18px;
z-index: 9999;
}
.drag-mask .iconfont {
font-size: 80px;
margin-bottom: 20px;
}
</style> </style>

View File

@ -38,8 +38,12 @@
<span class="iconfont icon-add"></span> <span class="iconfont icon-add"></span>
</div> </div>
</div> </div>
<div class="panel-container"> <div class="panel-container" v-if="mcpClientAdapter.clients.length > 0">
<ConnectionPanel v-if="mcpClientAdapter.clients.length > 0" :index="mcpClientAdapter.currentClientIndex" /> <ConnectionPanel :index="mcpClientAdapter.currentClientIndex" />
</div>
<div class="empty-state" v-else>
<span class="iconfont icon-openmcp"></span>
<span class="empty-text">暂无连接选项点击上方的加号创建</span>
</div> </div>
</div> </div>
</template> </template>
@ -59,8 +63,11 @@ function selectServer(index: number) {
function addServer() { function addServer() {
mcpClientAdapter.clients.push(new McpClient()); const client = new McpClient();
mcpClientAdapter.clients.push(client);
mcpClientAdapter.currentClientIndex = mcpClientAdapter.clients.length - 1; mcpClientAdapter.currentClientIndex = mcpClientAdapter.clients.length - 1;
client.handleEnvSwitch(true);
} }
@ -172,4 +179,23 @@ function deleteServer(index: number) {
.delete-btn:hover { .delete-btn:hover {
opacity: 0.8; opacity: 0.8;
} }
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: var(--text-secondary);
}
.empty-state .iconfont {
font-size: 128px;
margin-bottom: 16px;
}
.empty-text {
font-size: 18px;
color: var(--text-secondary);
}
</style> </style>

View File

@ -283,9 +283,9 @@ export function getWorkspaceConnectionConfigItemByPath(absPath: string) {
const normaliseAbsPath = absPath.replace(/\\/g, '/'); const normaliseAbsPath = absPath.replace(/\\/g, '/');
for (let item of workspaceConnectionConfig.items) { for (let item of workspaceConnectionConfig.items) {
item = Array.isArray(item)? item[0] : item; const nItem = Array.isArray(item)? item[0] : item;
const filePath = normaliseConnectionFilePath(item, workspacePath); const filePath = normaliseConnectionFilePath(nItem, workspacePath);
if (filePath === normaliseAbsPath) { if (filePath === normaliseAbsPath) {
return item; return item;
} }
@ -303,9 +303,9 @@ export function getInstalledConnectionConfigItemByPath(absPath: string) {
const normaliseAbsPath = absPath.replace(/\\/g, '/'); const normaliseAbsPath = absPath.replace(/\\/g, '/');
for (let item of installedConnectionConfig.items) { for (let item of installedConnectionConfig.items) {
item = Array.isArray(item)? item[0] : item; const nItem = Array.isArray(item)? item[0] : item;
const filePath = (item.filePath || '').replace(/\\/g, '/'); const filePath = (nItem.filePath || '').replace(/\\/g, '/');
if (filePath === normaliseAbsPath) { if (filePath === normaliseAbsPath) {
return item; return item;
} }