diff --git a/src/views/AgentChat/neuratalk/components/Image/MCPImage.tsx b/src/views/AgentChat/neuratalk/components/Image/MCPImage.tsx new file mode 100644 index 00000000..e6f1c800 --- /dev/null +++ b/src/views/AgentChat/neuratalk/components/Image/MCPImage.tsx @@ -0,0 +1,24 @@ +import { useState } from "react"; +import { default as NextImage, ImageProps } from "next/image"; + +const MCPImage = ({ className, src, ...props }: ImageProps) => { + const [loaded, setLoaded] = useState(false); + + // 处理图片路径 - 如果是相对路径,添加 basePath + const processedSrc = typeof src === 'string' && src.startsWith('/') && !src.startsWith('/ai-chat') + ? `/ai-chat${src}` + : src; + + return ( + setLoaded(true)} + src={processedSrc} + {...props} + /> + ); +}; + +export default MCPImage; \ No newline at end of file diff --git a/src/views/AgentChat/neuratalk/components/Layout/MCPLayout.tsx b/src/views/AgentChat/neuratalk/components/Layout/MCPLayout.tsx new file mode 100644 index 00000000..25e33ec0 --- /dev/null +++ b/src/views/AgentChat/neuratalk/components/Layout/MCPLayout.tsx @@ -0,0 +1,174 @@ +import { useState, useEffect } from "react"; +import Sidebar from "@/components/Sidebar"; +import Tools from "@/components/Tools"; +import Header from "@/components/Header"; +import PythonRunner from "@/components/PythonRunner"; +import Calculator from "@/components/Calculator"; +import Browser from "@/components/Browser"; +import WebDesign from "@/components/WebDesign"; +import FileConverter from "@/components/FileConverter"; +import LanguageTranslator from "@/components/LanguageTranslator"; +import ApiIntegrator from "@/components/ApiIntegrator"; +import { useAuth } from '@/hooks/useAuth'; +import MCPImage from "@/components/Image/MCPImage"; + +type Props = { + children: React.ReactNode; +}; + +const MCPLayout = ({ children }: Props) => { + const [activeId, setActiveId] = useState(null); + const [visibleTools, setVisibleTools] = useState(true); + const [visibleSidebar, setVisibleSidebar] = useState(false); + const { user, isAuthenticated, canAccessChat, loading: authLoading } = useAuth(); + + // 权限检查 + if (authLoading) { + return ( +
+
+
+

加载中...

+
+
+ ); + } + + if (!isAuthenticated) { + const mainAppUrl = process.env.NEXT_PUBLIC_MAIN_APP_URL || 'https://valuefrontier.cn'; + return ( +
+
+

请先登录

+

您需要登录才能使用 AI 助手

+ + 前往登录 + +
+
+ ); + } + + if (!canAccessChat) { + const mainAppUrl = process.env.NEXT_PUBLIC_MAIN_APP_URL || 'https://valuefrontier.cn'; + return ( +
+
+

需要订阅才能使用 AI 助手

+

升级到高级版解锁所有功能

+

+ 当前订阅等级:{user?.subscription_type || '未订阅'} +

+
+ + 查看订阅方案 + + +
+
+
+ ); + } + + return ( +
+ setVisibleSidebar(false)} + onClickNewChat={() => setActiveId(null)} + /> + + {/* 用户信息显示 */} + {user && ( +
+ {user.avatar_url ? ( + {user.username + ) : ( +
+ {(user.username || user.nickname || 'U')[0].toUpperCase()} +
+ )} +
+

+ {user.username || user.nickname} +

+

+ {user.subscription_type === 'max' ? '🌟 MAX会员' : + user.subscription_type === 'premium' ? '💎 高级会员' : + user.subscription_type === 'pro' ? '🚀 专业版' : '免费版'} +

+ {user.subscription_days_left && user.subscription_days_left > 0 && ( +

+ 剩余 {user.subscription_days_left} 天 +

+ )} +
+
+ )} + +
+
setVisibleSidebar(true)} + onToggleTools={() => setVisibleTools(!visibleTools)} + /> + {activeId === "python" ? ( + + ) : activeId === "calculator" ? ( + + ) : activeId === "browser" ? ( + + ) : activeId === "web-design" ? ( + + ) : activeId === "exchange" ? ( + + ) : activeId === "language" ? ( + + ) : activeId === "api" ? ( + + ) : ( + children + )} +
+ setVisibleTools(!visibleTools)} + /> + +
+ ); +}; + +export default MCPLayout; \ No newline at end of file diff --git a/src/views/AgentChat/neuratalk/components/PanelMessage/MCPPanelMessage.tsx b/src/views/AgentChat/neuratalk/components/PanelMessage/MCPPanelMessage.tsx index 0a1d68bb..a810b568 100644 --- a/src/views/AgentChat/neuratalk/components/PanelMessage/MCPPanelMessage.tsx +++ b/src/views/AgentChat/neuratalk/components/PanelMessage/MCPPanelMessage.tsx @@ -2,7 +2,7 @@ import { useState, useEffect, KeyboardEvent } from "react"; import Link from "next/link"; import TextareaAutosize from "react-textarea-autosize"; import Icon from "@/components/Icon"; -import Image from "@/components/Image"; +import MCPImage from "@/components/Image/MCPImage"; import Note from "./Note"; import Speed from "./Speed"; import Search from "./Search"; @@ -109,7 +109,7 @@ const MCPPanelMessage = ({ {isLoading ? (
) : ( - { } }; - // 权限检查 - if (authLoading) { - return ( - -
-
加载中...
-
-
- ); - } - - if (!isAuthenticated) { - const mainAppUrl = process.env.NEXT_PUBLIC_MAIN_APP_URL || 'https://valuefrontier.cn'; - return ( - -
-

请先登录

- - 前往登录 - -
-
- ); - } - - if (!canAccessChat) { - const mainAppUrl = process.env.NEXT_PUBLIC_MAIN_APP_URL || 'https://valuefrontier.cn'; - return ( - -
-

需要订阅才能使用 AI 助手

-

升级到高级版解锁所有功能

- - 查看订阅方案 - -
-
- ); + // MCPLayout 已经处理了认证检查,这里只需要简单检查 + if (!isAuthenticated || !canAccessChat) { + // MCPLayout 会自动显示登录或订阅提示 + return
; } return ( - + { )} - + ); }; diff --git a/valuefrontier.conf b/valuefrontier.conf index 276b6b6c..dfc41180 100644 --- a/valuefrontier.conf +++ b/valuefrontier.conf @@ -224,6 +224,21 @@ server { proxy_read_timeout 86400s; } # AI Chat 应用 (Next.js) - MCP 集成 + # AI Chat 静态资源(图片、CSS、JS) + location ~ ^/ai-chat/(images|_next/static|_next/image|favicon.ico) { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # 缓存设置 + expires 30d; + add_header Cache-Control "public, immutable"; + } + + # AI Chat 主应用 location /ai-chat { proxy_pass http://127.0.0.1:3000/ai-chat; proxy_http_version 1.1;