From 6118a1019e6b53a8f3d84bf61ccbb5a2d4043049 Mon Sep 17 00:00:00 2001 From: Ethan-Zhang Date: Mon, 20 Oct 2025 09:46:23 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Fix:=20=E7=BB=9F=E4=B8=80=E6=94=B9=E7=94=A8?= =?UTF-8?q?Authorization=E5=A4=B4=E5=AD=98=E5=82=A8=E4=BB=A4=E7=89=8C&?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=99=BB=E9=99=86=E7=8A=B6=E6=80=81debug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/paths/account.ts | 6 +++--- src/apis/tools.ts | 18 ++++++++---------- src/store/account.ts | 14 ++++++++------ src/store/conversation.ts | 3 +-- src/views/chat/index.vue | 3 +-- src/views/dialogue/Copilot.vue | 12 +++++------- src/views/dialogue/components/TitleBar.vue | 3 +-- src/views/dialogue/dialogueView.vue | 6 ------ 8 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/apis/paths/account.ts b/src/apis/paths/account.ts index 7947e341..74bbdb6e 100644 --- a/src/apis/paths/account.ts +++ b/src/apis/paths/account.ts @@ -54,7 +54,7 @@ export const login = ( any, ( | FcResponse<{ - csrf_token: string; + session_id: string; }> | undefined ), @@ -75,7 +75,7 @@ export const userLogin = ( any, ( | FcResponse<{ - csrf_token: string; + session_id: string; }> | undefined ), @@ -93,7 +93,7 @@ export const refreshToken = (): Promise< any, ( | FcResponse<{ - csrf_token: string; + session_id: string; }> | undefined ), diff --git a/src/apis/tools.ts b/src/apis/tools.ts index 6f78ef7f..89fa15d7 100644 --- a/src/apis/tools.ts +++ b/src/apis/tools.ts @@ -28,22 +28,20 @@ export function getCookie(name: string) { return matches ? decodeURIComponent(matches[1]) : undefined; } -// 修改请求头 +// 修改请求头 - 统一使用session ID认证 export const handleChangeRequestHeader = ( config: InternalAxiosRequestConfig, ): InternalAxiosRequestConfig => { if (config.headers['Content-Type'] !== 'multipart/form-data') { config.headers['Content-Type'] = 'application/json; charset=UTF-8'; } - const cookieValue = getCookie('_csrf_tk'); - if (cookieValue) { - config.headers['X-CSRF-Token'] = cookieValue; - } - // TODO 请求携带token 字段待定 - const token = localStorage.getItem('ECSESSION'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; + + // 统一使用session ID作为Bearer token进行认证 + const sessionId = localStorage.getItem('ECSESSION'); + if (sessionId) { + config.headers.Authorization = `Bearer ${sessionId}`; } + return config; }; @@ -64,10 +62,10 @@ async function toAuthorization() { const postMessageListener = async (event: MessageEvent) => { // 期望 event.data = { type: 'auth_success', sessionId: 'xxxx' } - console.log(event); const { sessionId, type } = event.data || {}; if (type === 'auth_success' && sessionId) { window.removeEventListener('message', postMessageListener); + // 统一使用session ID作为认证凭据 localStorage.setItem('ECSESSION', sessionId); authWindow?.close(); window.location.reload(); diff --git a/src/store/account.ts b/src/store/account.ts index 0c3dac1c..eaa465bf 100644 --- a/src/store/account.ts +++ b/src/store/account.ts @@ -42,7 +42,8 @@ export const useAccountStore = defineStore('account', () => { const login = async (code: string): Promise => { const [_, res] = await api.login(code); if (!_ && res) { - sessionStorage.setItem('csrftk', res.result.csrf_token); + // 统一使用session_id作为认证凭据 + localStorage.setItem('ECSESSION', res.result.session_id); router.push('/'); return true; } @@ -60,7 +61,7 @@ export const useAccountStore = defineStore('account', () => { /** * 登录 * @param user password - * @returns csrftk + * @returns session_id */ const userLogin = async ( passwd: string, @@ -68,7 +69,8 @@ export const useAccountStore = defineStore('account', () => { ): Promise => { const [_, res] = await api.userLogin(passwd, account); if (!_ && res) { - sessionStorage.setItem('csrftk', res.result.csrf_token); + // 统一使用session_id作为认证凭据 + localStorage.setItem('ECSESSION', res.result.session_id); router.push('/'); return true; } @@ -85,8 +87,7 @@ export const useAccountStore = defineStore('account', () => { userinfo.organization = ''; userinfo.revsionNumber = null; userinfo.user_sub = ''; - sessionStorage.removeItem('csrftk'); - // 清理localStorage中的ECSESSION,防止自动重新登录 + // 统一清理session认证凭据 localStorage.removeItem('ECSESSION'); successMsg(i18n.global.t('Login.logout')); } @@ -114,7 +115,8 @@ export const useAccountStore = defineStore('account', () => { const refreshAccessToken = async (): Promise => { const [_, res] = await api.refreshToken(); if (!_ && res) { - sessionStorage.setItem('csrftk', res.result.csrf_token); + // 统一使用session_id作为认证凭据 + localStorage.setItem('ECSESSION', res.result.session_id); return true; } return false; diff --git a/src/store/conversation.ts b/src/store/conversation.ts index 343ad3b1..5eb34263 100644 --- a/src/store/conversation.ts +++ b/src/store/conversation.ts @@ -556,8 +556,7 @@ export const useSessionStore = defineStore('conversation', () => { headers: { user: JSON.stringify({ userName: 'openEuler' }), 'Content-Type': 'application/json; charset=UTF-8', - 'X-CSRF-Token': getCookie('_csrf_tk') || '', - // 从 localStorage 获取 ECSESSION 并设置 Authorization + // 统一使用session ID作为Bearer token进行认证 ...(localEc ? { Authorization: `Bearer ${localEc}` } : {}), }, body: {}, diff --git a/src/views/chat/index.vue b/src/views/chat/index.vue index f1396d00..791a51e9 100644 --- a/src/views/chat/index.vue +++ b/src/views/chat/index.vue @@ -86,8 +86,7 @@ function useStream() { const headers = { user: JSON.stringify({ userName: 'openEuler' }), 'Content-Type': 'application/json; charset=UTF-8', - 'X-CSRF-Token': getCookie('_csrf_tk') || '', - // 从 localStorage 获取 ECSESSION 并设置 Authorization + // 统一使用session ID作为Bearer token进行认证 ...(localEc ? { Authorization: `Bearer ${localEc}` } : {}), }; const body = { diff --git a/src/views/dialogue/Copilot.vue b/src/views/dialogue/Copilot.vue index e5d1f914..41ff1bcd 100644 --- a/src/views/dialogue/Copilot.vue +++ b/src/views/dialogue/Copilot.vue @@ -124,16 +124,14 @@ onMounted(async () => { // 直接调用登录API const [_, res] = await api.login(code); if (!_ && res) { - // 设置CSRF token到sessionStorage - sessionStorage.setItem('csrftk', res.result.csrf_token); + // 统一使用session ID作为认证凭据 + const sessionId = res.result.session_id; + localStorage.setItem('ECSESSION', sessionId); - // 设置CSRF token到cookie,这是API请求需要的 - document.cookie = `_csrf_tk=${res.result.csrf_token}; path=/; SameSite=Strict`; - - // 通知父窗口登录成功,使用现有的消息格式 + // 通知父窗口登录成功 window.opener.postMessage({ type: 'auth_success', - sessionId: res.result.csrf_token + sessionId: sessionId }, '*'); // 关闭当前登录窗口 diff --git a/src/views/dialogue/components/TitleBar.vue b/src/views/dialogue/components/TitleBar.vue index dfc78b5a..b0667fd2 100644 --- a/src/views/dialogue/components/TitleBar.vue +++ b/src/views/dialogue/components/TitleBar.vue @@ -101,10 +101,10 @@ const handleLogin = async () => { const postMessageListener = async (event: MessageEvent) => { // 期望 event.data = { type: 'auth_success', sessionId: 'xxxx' } - console.log(event); const { sessionId, type } = event.data || {}; if (type === 'auth_success' && sessionId) { window.removeEventListener('message', postMessageListener); + // 统一使用session ID作为认证凭据 localStorage.setItem('ECSESSION', sessionId); authWindow?.close(); window.location.reload(); @@ -174,7 +174,6 @@ const headerStyles = computed(() => { const styles: CSSProperties = {}; if (!electronProcess) return styles; const platform = electronProcess.platform; - console.log(electronProcess.versions.electron); if (electronProcess.versions.electron) { if (platform === 'darwin') { diff --git a/src/views/dialogue/dialogueView.vue b/src/views/dialogue/dialogueView.vue index 6882ebe8..f719f548 100644 --- a/src/views/dialogue/dialogueView.vue +++ b/src/views/dialogue/dialogueView.vue @@ -197,7 +197,6 @@ watch( ); const initCopilot = async (): Promise => { - console.log('initCopilot 开始执行'); const currRoute = router.currentRoute; if (currRoute.value.query.appId) { app.value = { @@ -206,15 +205,10 @@ const initCopilot = async (): Promise => { }; } userinfo.value.organization = type; - console.log('准备调用 getUserInfo'); const isLogin = await getUserInfo(); - console.log('getUserInfo 结果:', isLogin); if (isLogin) { - console.log('用户已登录,获取历史会话'); await api.stopGeneration(); await getHistorySession(); - } else { - console.log('用户未登录或获取用户信息失败'); } return; }; -- Gitee From facf2754cf04c572be78c91311db547f7ae3d147 Mon Sep 17 00:00:00 2001 From: Ethan-Zhang Date: Mon, 20 Oct 2025 10:59:32 +0800 Subject: [PATCH 2/2] =?UTF-8?q?Fix:=20=E4=BF=AE=E5=A4=8D=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=8B=96=E6=8B=89=E6=8B=BD=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=92=8C=E8=8A=82=E7=82=B9=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/paths/mcp.ts | 2 +- .../components/codeMirror/nodeMirrorText.vue | 4 +- .../workFlowConfig/NodeSelector.vue | 3 + .../workFlowConfig/PluginListPanel.vue | 55 ++++++++++++++++++- .../components/workFlowConfig/useDnD.js | 18 +++++- 5 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/apis/paths/mcp.ts b/src/apis/paths/mcp.ts index b4bd9851..fcae0e11 100644 --- a/src/apis/paths/mcp.ts +++ b/src/apis/paths/mcp.ts @@ -15,7 +15,7 @@ const getMcpList = (params: { }) => { return get<{ currentPage: number; - totalCount: 0; + totalCount: number; services: [ { mcpserviceId: string; diff --git a/src/views/createapp/components/codeMirror/nodeMirrorText.vue b/src/views/createapp/components/codeMirror/nodeMirrorText.vue index 838a994f..17976e47 100644 --- a/src/views/createapp/components/codeMirror/nodeMirrorText.vue +++ b/src/views/createapp/components/codeMirror/nodeMirrorText.vue @@ -157,9 +157,7 @@ const setEditorRef = (el: any, key: string) => { // 编辑器准备就绪回调 const handleReady = (payload: any, editorKey: string, code?: any) => { - if (payload && payload.editor) { - console.log(`📝 Monaco editor ready for ${editorKey}`); - + if (payload && payload.editor) { // 设置初始内容 if (code !== undefined) { const formattedCode = formatCodeData(code); diff --git a/src/views/createapp/components/workFlowConfig/NodeSelector.vue b/src/views/createapp/components/workFlowConfig/NodeSelector.vue index 613e08ee..a1922da9 100644 --- a/src/views/createapp/components/workFlowConfig/NodeSelector.vue +++ b/src/views/createapp/components/workFlowConfig/NodeSelector.vue @@ -36,7 +36,10 @@
diff --git a/src/views/createapp/components/workFlowConfig/PluginListPanel.vue b/src/views/createapp/components/workFlowConfig/PluginListPanel.vue index f9fb02f9..0244e763 100644 --- a/src/views/createapp/components/workFlowConfig/PluginListPanel.vue +++ b/src/views/createapp/components/workFlowConfig/PluginListPanel.vue @@ -49,7 +49,9 @@ :key="plugin.serviceId" class="plugin-item" :class="{ 'plugin-disabled': activeTab === 'mcp' && plugin.isActive === false }" + :draggable="enableDrag" @click="handlePluginClick(plugin)" + @dragstart="handleDragStart($event, plugin)" >
@@ -165,11 +167,20 @@ import DefaultIcon from '@/assets/svgs/defaultIcon.webp'; // Props interface Props { searchPlaceholder?: string; + enableDrag?: boolean; + onDragStart?: (event: DragEvent, plugin: any) => void; } +const props = withDefaults(defineProps(), { + searchPlaceholder: '搜索插件...', + enableDrag: false, + onDragStart: undefined +}); + // Emits interface Emits { (e: 'pluginClick', plugin: any): void; + (e: 'dragStart', event: DragEvent, plugin: any): void; } const emit = defineEmits(); @@ -189,6 +200,7 @@ const pluginLists = ref<{ favorited?: boolean; icon: string; author: string; + authorName?: string; name: string; published?: boolean; isActive?: boolean; @@ -290,6 +302,45 @@ const handlePluginClick = (plugin: any) => { emit('pluginClick', nodeData); }; +const handleDragStart = (event: DragEvent, plugin: any) => { + // 检查MCP插件是否已激活,未激活则阻止拖拽 + if (activeTab.value === 'mcp' && plugin.isActive === false) { + event.preventDefault(); + return; + } + + if (props.enableDrag) { + // 创建与点击时相同的PluginNode节点数据结构 + const nodeData = { + // 基础节点信息 + nodeId: `plugin-${plugin.serviceId}`, + callId: plugin.serviceId, + type: 'plugin-node', // 标识为PluginNode类型 + + // PluginNode专用数据 + data: { + serviceId: plugin.serviceId, + name: plugin.name, + description: plugin.description, + icon: plugin.icon, + author: plugin.author, + authorName: plugin.authorName, + pluginType: plugin.type, // 'semantic_interface' 或 'mcp' + type: 'plugin', + isActive: plugin.isActive, + status: plugin.status, + published: plugin.published, + parameters: {} // 插件节点的默认参数 + } + }; + + if (props.onDragStart) { + props.onDragStart(event, nodeData); + } + emit('dragStart', event, nodeData); + } +}; + const handleFavorite = async (e: Event, item: any) => { e.stopPropagation(); // 未发布的不可收藏 @@ -444,6 +495,7 @@ defineExpose({ border-radius: 8px; margin: 16px 20px 12px; flex-shrink: 0; + min-width: 280px; .search-input { flex: 1; @@ -509,7 +561,7 @@ defineExpose({ flex: 1; overflow-y: auto; min-height: 0; - padding: 0 20px; + padding: 0 40px; .plugin-cards { display: flex; @@ -717,6 +769,7 @@ defineExpose({ margin-bottom: 12px; display: -webkit-box; -webkit-line-clamp: 2; + line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } diff --git a/src/views/createapp/components/workFlowConfig/useDnD.js b/src/views/createapp/components/workFlowConfig/useDnD.js index c4d80be8..41b455f9 100644 --- a/src/views/createapp/components/workFlowConfig/useDnD.js +++ b/src/views/createapp/components/workFlowConfig/useDnD.js @@ -233,6 +233,10 @@ function sanitizeNodeData(nodeData, nodeId) { } } }; + } else if (cleanNodeData.type === 'plugin-node') { + // 插件节点不需要清洗,直接返回原始数据 + // 插件节点的数据结构已经在PluginListPanel中正确构建 + return cleanNodeData; } else { // 对于所有其他节点类型(LLM、RAG、API、SQL等),使用API返回的原始parameters cleanNodeData.parameters = cleanNodeData.parameters || { @@ -332,7 +336,19 @@ export default function useDragAndDrop() { event.dataTransfer.effectAllowed = 'move'; } - draggedType.value = info?.callId === 'Choice' ? 'Choice' : info?.callId === 'Loop' ? 'Loop' : 'custom'; + // 根据节点类型设置draggedType + if (info?.type === 'plugin-node') { + draggedType.value = 'plugin-node'; + } else if (info?.callId === 'Choice') { + draggedType.value = 'Choice'; + } else if (info?.callId === 'Loop') { + draggedType.value = 'Loop'; + } else if (info?.callId === 'VariableAssign') { + draggedType.value = 'VariableAssign'; + } else { + draggedType.value = 'custom'; + } + isDragging.value = true; nodeData.value = { ...info }; -- Gitee