diff --git a/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx b/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx index a1285f12..7c89a34e 100644 --- a/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx +++ b/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx @@ -17,7 +17,7 @@ import { Switch } from '@/components/ui/switch'; import { ControllerRenderProps } from 'react-hook-form'; import { Button } from '@/components/ui/button'; import { useEffect, useState } from 'react'; -import { httpClient, systemInfo } from '@/app/infra/http/HttpClient'; +import { httpClient, systemInfo, userInfo } from '@/app/infra/http'; import { LLMModel, Bot, @@ -99,8 +99,11 @@ export default function DynamicFormItemComponent({ .getProviderLLMModels() .then((resp) => { let models = resp.models; - // Filter out space-chat-completions models when models service is disabled - if (systemInfo.disable_models_service) { + // Filter out space-chat-completions models when not logged in with space account or when models service is disabled + if ( + systemInfo.disable_models_service || + userInfo?.account_type !== 'space' + ) { models = models.filter( (m) => m.provider?.requester !== 'space-chat-completions', ); diff --git a/web/src/app/home/components/models-dialog/components/ModelItem.tsx b/web/src/app/home/components/models-dialog/components/ModelItem.tsx index 81649195..61215ce3 100644 --- a/web/src/app/home/components/models-dialog/components/ModelItem.tsx +++ b/web/src/app/home/components/models-dialog/components/ModelItem.tsx @@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next'; import { LLMModel, EmbeddingModel } from '@/app/infra/entities/api'; import { ExtraArg, ModelType, TestResult } from '../types'; import ExtraArgsEditor from './ExtraArgsEditor'; +import { userInfo } from '@/app/infra/http'; interface ModelItemProps { model: LLMModel | EmbeddingModel; @@ -113,10 +114,15 @@ export default function ModelItem({ } }; + // Check if popover should be disabled (space models when not logged in) + const isPopoverDisabled = + isLangBotModels && userInfo?.account_type !== 'space'; + return ( { + if (isPopoverDisabled) return; if (open) { onOpenEditModel(model.uuid); } else { @@ -125,7 +131,13 @@ export default function ModelItem({ }} > -
+
{model.name} diff --git a/web/src/app/home/knowledge/components/kb-form/KBForm.tsx b/web/src/app/home/knowledge/components/kb-form/KBForm.tsx index e8e4c650..8ed045c2 100644 --- a/web/src/app/home/knowledge/components/kb-form/KBForm.tsx +++ b/web/src/app/home/knowledge/components/kb-form/KBForm.tsx @@ -14,7 +14,7 @@ import { FormMessage, FormDescription, } from '@/components/ui/form'; -import { httpClient, systemInfo } from '@/app/infra/http/HttpClient'; +import { httpClient, systemInfo, userInfo } from '@/app/infra/http'; import { Select, SelectContent, @@ -101,8 +101,11 @@ export default function KBForm({ const getEmbeddingModelNameList = async () => { const resp = await httpClient.getProviderEmbeddingModels(); let models = resp.models; - // Filter out space-chat-completions models when models service is disabled - if (systemInfo.disable_models_service) { + // Filter out space-chat-completions models when not logged in with space account or when models service is disabled + if ( + systemInfo.disable_models_service || + userInfo?.account_type !== 'space' + ) { models = models.filter( (m) => m.provider?.requester !== 'space-chat-completions', ); diff --git a/web/src/app/home/layout.tsx b/web/src/app/home/layout.tsx index 01f38657..11353b4c 100644 --- a/web/src/app/home/layout.tsx +++ b/web/src/app/home/layout.tsx @@ -3,9 +3,10 @@ import styles from './layout.module.css'; import HomeSidebar from '@/app/home/components/home-sidebar/HomeSidebar'; import HomeTitleBar from '@/app/home/components/home-titlebar/HomeTitleBar'; -import React, { useState, useCallback, useMemo } from 'react'; +import React, { useState, useCallback, useMemo, useEffect } from 'react'; import { SidebarChildVO } from '@/app/home/components/home-sidebar/HomeSidebarChild'; import { I18nObject } from '@/app/infra/entities/common'; +import { userInfo, initializeUserInfo } from '@/app/infra/http'; export default function HomeLayout({ children, @@ -19,6 +20,13 @@ export default function HomeLayout({ zh_Hans: '', }); + // Initialize user info if not already initialized + useEffect(() => { + if (!userInfo) { + initializeUserInfo(); + } + }, []); + const onSelectedChangeAction = useCallback((child: SidebarChildVO) => { setTitle(child.name); setSubtitle(child.description); diff --git a/web/src/app/infra/http/index.ts b/web/src/app/infra/http/index.ts index 4ce98b1d..b4b720d2 100644 --- a/web/src/app/infra/http/index.ts +++ b/web/src/app/infra/http/index.ts @@ -12,6 +12,13 @@ export let systemInfo: ApiRespSystemInfo = { disable_models_service: false, }; +// 用户信息 +export let userInfo: { + user: string; + account_type: 'local' | 'space'; + has_password: boolean; +} | null = null; + /** * 获取基础 URL */ @@ -24,6 +31,8 @@ const getBaseURL = (): string => { // 创建后端客户端实例 export const backendClient = new BackendClient(getBaseURL()); +// 为了兼容性,也导出为 httpClient +export const httpClient = backendClient; // 创建云服务客户端实例(初始化时使用默认 URL) export const cloudServiceClient = new CloudServiceClient( @@ -82,6 +91,27 @@ export const initializeSystemInfo = async (): Promise => { } }; +/** + * 初始化用户信息 + * 应该在用户登录后调用此方法 + */ +export const initializeUserInfo = async (): Promise => { + try { + userInfo = await backendClient.getUserInfo(); + } catch (error) { + console.error('Failed to initialize user info:', error); + userInfo = null; + } +}; + +/** + * 清除用户信息 + * 应该在用户登出时调用此方法 + */ +export const clearUserInfo = (): void => { + userInfo = null; +}; + // 导出类型,以便其他地方使用 export type { ResponseData, RequestConfig } from './BaseHttpClient'; export { BaseHttpClient } from './BaseHttpClient'; diff --git a/web/src/app/login/page.tsx b/web/src/app/login/page.tsx index 4ce2f722..39d5272a 100644 --- a/web/src/app/login/page.tsx +++ b/web/src/app/login/page.tsx @@ -21,7 +21,7 @@ import { FormMessage, } from '@/components/ui/form'; import { useEffect, useState } from 'react'; -import { httpClient } from '@/app/infra/http/HttpClient'; +import { httpClient, initializeUserInfo } from '@/app/infra/http'; import { useRouter } from 'next/navigation'; import { Mail, Lock, Loader2 } from 'lucide-react'; import langbotIcon from '@/app/assets/langbot-logo.webp'; @@ -95,9 +95,10 @@ export default function Login() { function handleLogin(username: string, password: string) { httpClient .authUser(username, password) - .then((res) => { + .then(async (res) => { localStorage.setItem('token', res.token); localStorage.setItem('userEmail', username); + await initializeUserInfo(); router.push('/home'); toast.success(t('common.loginSuccess')); })