diff --git a/src/apis/paths/account.ts b/src/apis/paths/account.ts index c465a147b48174a8956eac27c53651ce42350657..7947e341d59ce7b72b158c35139c81dfbeb091f6 100644 --- a/src/apis/paths/account.ts +++ b/src/apis/paths/account.ts @@ -20,7 +20,7 @@ export const authorizeUser = (): Promise< ( | FcResponse<{ user_sub: string; - username: string; + user_name: string; organization: string; revision_number: string | null; is_admin: boolean; @@ -143,9 +143,32 @@ export const getUserPreferences = (): Promise< any, ( | FcResponse<{ - reasoningModelPreference?: any; - embeddingModelPreference?: any; - rerankerPreference?: any; + reasoningModelPreference?: { + llmId: string; + icon?: string; + openaiBaseUrl: string; + openaiApiKey: string; + modelName: string; + maxTokens: number; + isEditable?: boolean; + }; + embeddingModelPreference?: { + llmId: string; + modelName: string; + icon?: string; + type: string; + endpoint: string; + apiKey: string; + }; + rerankerPreference?: { + llmId: string; + modelName: string; + icon?: string; + type: string; + endpoint?: string; + apiKey?: string; + name?: string; + }; chainOfThoughtPreference?: boolean; }> | undefined diff --git a/src/apis/tools.ts b/src/apis/tools.ts index 2a2c9c5fb895b38d06083ca1aa4d655b26497c24..6f78ef7f98b572b48ad8a0c18482bf1926013528 100644 --- a/src/apis/tools.ts +++ b/src/apis/tools.ts @@ -64,6 +64,7 @@ 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); diff --git a/src/store/account.ts b/src/store/account.ts index 581ab94369ddcb26112e1f2fc8440aad048718b8..0c3dac1cf9f79fe1add030df7d43bcdede94f794 100644 --- a/src/store/account.ts +++ b/src/store/account.ts @@ -97,8 +97,8 @@ export const useAccountStore = defineStore('account', () => { const getUserInfo = async (): Promise => { const [_, res] = await api.authorizeUser(); if (!_ && res) { - const { organization, username, revision_number, user_sub } = res.result; - userinfo.username = username; + const { organization, user_name, revision_number, user_sub } = res.result; + userinfo.username = user_name; userinfo.user_sub = user_sub; userinfo.organization = organization; userinfo.revsionNumber = revision_number; diff --git a/src/store/index.ts b/src/store/index.ts index bb8159da724b49b1c7914af7b85701e3d8aea245..454d9894fb83b8e14c7f8c96c4a305eb5e1d9d19 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -12,3 +12,4 @@ export * from './conversation'; export * from './historySession'; export * from './lang'; export * from './theme'; +export * from './userPreferences'; diff --git a/src/store/userPreferences.ts b/src/store/userPreferences.ts new file mode 100644 index 0000000000000000000000000000000000000000..f771060f95bd71734a10d14e4392e00654465123 --- /dev/null +++ b/src/store/userPreferences.ts @@ -0,0 +1,113 @@ +// Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +// licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. +import { defineStore } from 'pinia'; +import { reactive, ref } from 'vue'; +import { api } from 'src/apis'; + +export interface ReasoningModelPreference { + llmId: string; + icon?: string; + openaiBaseUrl: string; + openaiApiKey: string; + modelName: string; + maxTokens: number; + isEditable?: boolean; +} + +export interface EmbeddingModelPreference { + llmId: string; + modelName: string; + icon?: string; + type: string; + endpoint: string; + apiKey: string; +} + +export interface RerankerModelPreference { + llmId: string; + modelName: string; + icon?: string; + type: string; + endpoint?: string; + apiKey?: string; + name?: string; +} + +export interface UserPreferences { + reasoningModelPreference?: ReasoningModelPreference; + embeddingModelPreference?: EmbeddingModelPreference; + rerankerPreference?: RerankerModelPreference; + chainOfThoughtPreference?: boolean; +} + +export const useUserPreferencesStore = defineStore('userPreferences', () => { + // 用户偏好设置 + const preferences = reactive({ + reasoningModelPreference: undefined, + embeddingModelPreference: undefined, + rerankerPreference: undefined, + chainOfThoughtPreference: undefined, + }); + + // 加载状态 + const loading = ref(false); + + /** + * 获取用户偏好设置 + */ + const getUserPreferences = async (): Promise => { + loading.value = true; + try { + const [_, res] = await api.getUserPreferences(); + if (!_ && res) { + Object.assign(preferences, res.result); + return true; + } + return false; + } finally { + loading.value = false; + } + }; + + /** + * 更新用户偏好设置 + */ + const updateUserPreferences = async (newPreferences: Partial): Promise => { + loading.value = true; + try { + const [_, res] = await api.updateUserPreferences(newPreferences); + if (!_ && res) { + Object.assign(preferences, newPreferences); + return true; + } + return false; + } finally { + loading.value = false; + } + }; + + /** + * 重置偏好设置 + */ + const resetPreferences = () => { + preferences.reasoningModelPreference = undefined; + preferences.embeddingModelPreference = undefined; + preferences.rerankerPreference = undefined; + preferences.chainOfThoughtPreference = undefined; + }; + + return { + preferences, + loading, + getUserPreferences, + updateUserPreferences, + resetPreferences, + }; +}); diff --git a/src/views/dialogue/Copilot.vue b/src/views/dialogue/Copilot.vue index 1164d4cf786e21ca98a8a4e955ac644c4d387e77..e5d1f914eb4e65cec904cc9454b0ca7b7ed03d93 100644 --- a/src/views/dialogue/Copilot.vue +++ b/src/views/dialogue/Copilot.vue @@ -113,6 +113,37 @@ onMounted(async () => { top: 0, left: 0, }); + + // 检查是否是登录回调 + const urlParams = new URLSearchParams(window.location.search); + const code = urlParams.get('code'); + + // 如果存在授权码且当前窗口是弹窗(有opener),则处理登录 + if (code && window.opener) { + try { + // 直接调用登录API + const [_, res] = await api.login(code); + if (!_ && res) { + // 设置CSRF token到sessionStorage + sessionStorage.setItem('csrftk', res.result.csrf_token); + + // 设置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 + }, '*'); + + // 关闭当前登录窗口 + window.close(); + } + } catch (error) { + console.error('登录失败:', error); + // 可以在这里添加错误处理,比如显示错误消息 + } + } });