diff --git a/src/views/AgentChat/neuratalk/app/ai-chat/generate-code-template/page.tsx b/src/views/AgentChat/neuratalk/app/ai-chat/generate-code-template/page.tsx
new file mode 100644
index 00000000..9bbc4fa8
--- /dev/null
+++ b/src/views/AgentChat/neuratalk/app/ai-chat/generate-code-template/page.tsx
@@ -0,0 +1,6 @@
+// app/ai-chat/generate-code-template/page.tsx - 原始模板页面(仅演示)
+import GenerateCodePage from "@/templates/GenerateCodePage";
+
+export default function Page() {
+ return ;
+}
\ No newline at end of file
diff --git a/src/views/AgentChat/neuratalk/app/ai-chat/generate-code/page.tsx b/src/views/AgentChat/neuratalk/app/ai-chat/generate-code/page.tsx
new file mode 100644
index 00000000..6f820f73
--- /dev/null
+++ b/src/views/AgentChat/neuratalk/app/ai-chat/generate-code/page.tsx
@@ -0,0 +1,6 @@
+// app/ai-chat/generate-code/page.tsx - MCP 集成的代码生成页面
+import MCPGenerateCodePage from "@/templates/GenerateCodePage/MCPIntegrated";
+
+export default function Page() {
+ return ;
+}
\ No newline at end of file
diff --git a/src/views/AgentChat/neuratalk/app/chat/page.tsx b/src/views/AgentChat/neuratalk/app/chat/page.tsx
new file mode 100644
index 00000000..0bbfc58c
--- /dev/null
+++ b/src/views/AgentChat/neuratalk/app/chat/page.tsx
@@ -0,0 +1,7 @@
+// app/chat/page.tsx - 使用模板的漂亮聊天界面
+import GenerateCodePage from "@/templates/GenerateCodePage";
+
+export default function ChatPage() {
+ // 使用代码生成页面模板(最接近聊天功能)
+ return ;
+}
\ No newline at end of file
diff --git a/src/views/AgentChat/neuratalk/app/demo/page.tsx b/src/views/AgentChat/neuratalk/app/demo/page.tsx
new file mode 100644
index 00000000..69bf2443
--- /dev/null
+++ b/src/views/AgentChat/neuratalk/app/demo/page.tsx
@@ -0,0 +1,75 @@
+// app/demo/page.tsx - 所有页面演示
+'use client';
+
+export default function DemoPage() {
+ const pages = [
+ { name: '🏠 主页', path: '/ai-chat', desc: '欢迎页面,功能卡片展示' },
+ { name: '🤖 AI 代码助手', path: '/ai-chat/generate-code', desc: '✨ 漂亮界面 + MCP 集成(推荐)' },
+ { name: '💬 模板代码生成', path: '/ai-chat/generate-code-template', desc: '原始模板界面(仅演示)' },
+ { name: '🎨 图像生成', path: '/ai-chat/image-generation', desc: '图像生成界面' },
+ { name: '📊 数据分析', path: '/ai-chat/data-analytics', desc: '数据分析和图表' },
+ { name: '📝 文档生成', path: '/ai-chat/document-generation', desc: '文档生成界面' },
+ { name: '📁 文档管理', path: '/ai-chat/documents', desc: '文档列表管理' },
+ { name: '🔍 研究', path: '/ai-chat/research', desc: '研究和语音功能' },
+ { name: '📋 模板', path: '/ai-chat/templates', desc: '模板库' },
+ { name: '⏰ 历史', path: '/ai-chat/history', desc: '聊天历史' },
+ { name: '🚀 简单聊天', path: '/ai-chat/chat-direct', desc: '简化版聊天(已集成 MCP)' }
+ ];
+
+ return (
+
+
+
AI Chat 页面导航
+
选择您想查看的页面模板
+
+
+
+
+
推荐查看
+
+ -
+ 最漂亮:
+ 主页
+ - 精美的欢迎界面和功能卡片
+
+ -
+ 🔥 最新集成:
+ AI 代码助手
+ - 漂亮界面 + MCP 功能
+
+ -
+ 最全功能:
+ 研究
+ - 包含语音和多种工具
+
+ -
+ 已集成 MCP:
+ 直接聊天
+ - 简化版但已连接 MCP
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/views/AgentChat/neuratalk/app/page.tsx b/src/views/AgentChat/neuratalk/app/page.tsx
index 72729129..fefe2982 100644
--- a/src/views/AgentChat/neuratalk/app/page.tsx
+++ b/src/views/AgentChat/neuratalk/app/page.tsx
@@ -1,15 +1,15 @@
-// 可以选择使用原始主页或直接进入聊天
-// import HomePage from "@/templates/HomePage";
-import MCPChat from "@/components/Chat/MCPChat";
+// 使用原始模板的漂亮界面
+import HomePage from "@/templates/HomePage";
+// import MCPChat from "@/components/Chat/MCPChat";
export default function Page() {
- // 直接显示聊天界面
- return (
-
-
-
- );
+ // 使用原始主页 - 漂亮的界面
+ return ;
- // 或者使用原始主页
- // return ;
+ // 简单聊天界面(备用)
+ // return (
+ //
+ //
+ //
+ // );
}
diff --git a/src/views/AgentChat/neuratalk/components/Chat/MCPChat.tsx b/src/views/AgentChat/neuratalk/components/Chat/MCPChat.tsx
index 5f644e1a..374deca9 100644
--- a/src/views/AgentChat/neuratalk/components/Chat/MCPChat.tsx
+++ b/src/views/AgentChat/neuratalk/components/Chat/MCPChat.tsx
@@ -1,305 +1,62 @@
-// components/Chat/MCPChat.tsx - 集成 MCP 的聊天组件
-'use client';
+import MCPPanelMessage from "@/components/PanelMessage/MCPPanelMessage";
+import Head from "./Head";
+import { useState } from "react";
-import React, { useState, useRef, useEffect } from 'react';
-import { mcpService } from '../../services/mcp-real';
-import { useAuth } from '../../hooks/useAuth';
-import styles from './MCPChat.module.css';
+type Props = {
+ titleHead?: React.ReactNode;
+ hidePanelMessage?: boolean;
+ children: React.ReactNode;
+ onInputChange?: (value: string) => void;
+ onSend?: () => void;
+ inputValue?: string;
+ isLoading?: boolean;
+};
-interface Message {
- id: string;
- role: 'user' | 'assistant' | 'system';
- content: string;
- timestamp: Date;
- isStreaming?: boolean;
-}
+const MCPChat = ({
+ titleHead,
+ hidePanelMessage,
+ children,
+ onInputChange,
+ onSend,
+ inputValue,
+ isLoading
+}: Props) => {
+ const [localInput, setLocalInput] = useState('');
-export default function MCPChat() {
- const [messages, setMessages] = useState([]);
- const [input, setInput] = useState('');
- const [isLoading, setIsLoading] = useState(false);
- const [streamingMessage, setStreamingMessage] = useState('');
- const [tools, setTools] = useState([]);
- const messagesEndRef = useRef(null);
- const { user, isAuthenticated, canAccessChat, loading: authLoading } = useAuth();
-
- // 加载可用工具
- useEffect(() => {
- if (isAuthenticated && canAccessChat) {
- loadTools();
- }
- }, [isAuthenticated, canAccessChat]);
-
- // 自动滚动到底部
- useEffect(() => {
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
- }, [messages, streamingMessage]);
-
- const loadTools = async () => {
- try {
- const availableTools = await mcpService.getTools();
- setTools(availableTools);
- console.log('Available tools:', availableTools);
- } catch (error) {
- console.error('Failed to load tools:', error);
- }
- };
-
- const handleSend = async () => {
- if (!input.trim() || isLoading) return;
-
- const userMessage: Message = {
- id: Date.now().toString(),
- role: 'user',
- content: input,
- timestamp: new Date(),
+ const handleInputChange = (value: string) => {
+ if (onInputChange) {
+ onInputChange(value);
+ } else {
+ setLocalInput(value);
+ }
};
- setMessages(prev => [...prev, userMessage]);
- setInput('');
- setIsLoading(true);
- setStreamingMessage('');
+ const handleSend = () => {
+ if (onSend) {
+ onSend();
+ }
+ };
- try {
- // 创建助手消息占位符
- const assistantMessage: Message = {
- id: (Date.now() + 1).toString(),
- role: 'assistant',
- content: '',
- timestamp: new Date(),
- isStreaming: true,
- };
-
- setMessages(prev => [...prev, assistantMessage]);
-
- // 流式接收回复
- let fullContent = '';
- for await (const chunk of mcpService.streamMessage(input)) {
- fullContent += chunk;
- setStreamingMessage(fullContent);
- }
-
- // 更新最终消息
- setMessages(prev =>
- prev.map(msg =>
- msg.id === assistantMessage.id
- ? { ...msg, content: fullContent, isStreaming: false }
- : msg
- )
- );
- setStreamingMessage('');
- } catch (error) {
- console.error('Send message error:', error);
- setMessages(prev => [
- ...prev,
- {
- id: Date.now().toString(),
- role: 'system',
- content: '抱歉,发送消息时出错了。请稍后重试。',
- timestamp: new Date(),
- },
- ]);
- } finally {
- setIsLoading(false);
- }
- };
-
- const handleToolCall = async (toolName: string) => {
- // 示例:调用工具
- try {
- setIsLoading(true);
- const result = await mcpService.callTool(toolName, {});
- console.log('Tool result:', result);
-
- // 显示工具结果
- setMessages(prev => [
- ...prev,
- {
- id: Date.now().toString(),
- role: 'system',
- content: `工具 ${toolName} 执行结果:${JSON.stringify(result.result, null, 2)}`,
- timestamp: new Date(),
- },
- ]);
- } catch (error) {
- console.error('Tool call error:', error);
- } finally {
- setIsLoading(false);
- }
- };
-
- // 权限检查
- 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 助手
-
升级到高级版解锁所有功能
-
- 当前订阅等级:{user?.subscription_type || user?.subscription_tier || '未知'}
- {user?.is_subscription_active && ' (活跃)'}
-
-
-
- 查看订阅方案
-
-
-
-
- );
- }
-
- return (
-
- {/* 侧边栏 - 工具列表 */}
-
-
可用工具
-
- {tools.map(tool => (
-
- ))}
-
-
- {/* 用户信息 */}
-
-
-
- {user?.username?.[0]?.toUpperCase()}
-
-
-
{user?.username || user?.nickname}
-
- {user?.subscription_type || user?.subscription_tier || 'Free'}
- {user?.is_subscription_active && ' ✓'}
-
-
-
-
-
-
- {/* 主聊天区域 */}
-
- {/* 消息列表 */}
-
- {messages.map(msg => (
+
+
-
- {msg.isStreaming ? (
-
- {streamingMessage || (
- 思考中...
- )}
-
- ) : (
-
{msg.content}
- )}
-
- {msg.timestamp.toLocaleTimeString()}
-
-
+ >
+ {children}
- ))}
-
+ {!hidePanelMessage && (
+
+ )}
+ );
+};
- {/* 输入区域 */}
-
-
- setInput(e.target.value)}
- onKeyPress={e => e.key === 'Enter' && handleSend()}
- disabled={isLoading}
- placeholder="输入消息..."
- className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
- />
-
-
-
- {/* 快捷操作 */}
-
-
-
-
-
-
-
-
- );
-}
-
-// CSS 模块文件需要单独创建
\ No newline at end of file
+export default MCPChat;
\ 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
new file mode 100644
index 00000000..0a1d68bb
--- /dev/null
+++ b/src/views/AgentChat/neuratalk/components/PanelMessage/MCPPanelMessage.tsx
@@ -0,0 +1,131 @@
+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 Note from "./Note";
+import Speed from "./Speed";
+import Search from "./Search";
+import Menu from "./Menu";
+
+type ButtonProps = {
+ className?: string;
+ icon: string;
+ onClick: () => void;
+};
+
+const Button = ({ className, icon, onClick }: ButtonProps) => {
+ return (
+
+ );
+};
+
+type MCPPanelMessageProps = {
+ value?: string;
+ onInputChange?: (value: string) => void;
+ onSend?: () => void;
+ isLoading?: boolean;
+ placeholder?: string;
+};
+
+const MCPPanelMessage = ({
+ value = '',
+ onInputChange,
+ onSend,
+ isLoading = false,
+ placeholder = "输入消息,与 AI 对话..."
+}: MCPPanelMessageProps) => {
+ const [localMessage, setLocalMessage] = useState("");
+
+ // 同步外部值
+ useEffect(() => {
+ if (value !== undefined) {
+ setLocalMessage(value);
+ }
+ }, [value]);
+
+ const handleChange = (newValue: string) => {
+ setLocalMessage(newValue);
+ if (onInputChange) {
+ onInputChange(newValue);
+ }
+ };
+
+ const handleSend = () => {
+ if (!localMessage.trim() || isLoading) return;
+
+ if (onSend) {
+ onSend();
+ }
+ };
+
+ const handleKeyPress = (e: KeyboardEvent) => {
+ // Shift+Enter 换行,Enter 发送
+ if (e.key === 'Enter' && !e.shiftKey) {
+ e.preventDefault();
+ handleSend();
+ }
+ };
+
+ return (
+
+
+
+
+ handleChange(e.target.value)}
+ onKeyDown={handleKeyPress}
+ placeholder={placeholder}
+ disabled={isLoading}
+ />
+
+
+
+
+
+
+ {/* 快捷提示 */}
+
+ 按 Enter 发送,Shift+Enter 换行
+
+
+
+ );
+};
+
+export default MCPPanelMessage;
\ No newline at end of file
diff --git a/src/views/AgentChat/neuratalk/templates/GenerateCodePage/MCPIntegrated.tsx b/src/views/AgentChat/neuratalk/templates/GenerateCodePage/MCPIntegrated.tsx
new file mode 100644
index 00000000..d46591f7
--- /dev/null
+++ b/src/views/AgentChat/neuratalk/templates/GenerateCodePage/MCPIntegrated.tsx
@@ -0,0 +1,274 @@
+"use client";
+
+import { useState, useRef, useEffect } from "react";
+import Layout from "@/components/Layout";
+import MCPChat from "@/components/Chat/MCPChat";
+import Question from "@/components/Question";
+import Answer from "@/components/Answer";
+import CodeEditor from "@/components/CodeEditor";
+import { mcpService } from '@/services/mcp-real';
+import { useAuth } from '@/hooks/useAuth';
+
+interface Message {
+ id: string;
+ role: 'user' | 'assistant' | 'system';
+ content: string;
+ timestamp: Date;
+ code?: {
+ language: string;
+ content: string;
+ title?: string;
+ };
+ isStreaming?: boolean;
+}
+
+const MCPGenerateCodePage = () => {
+ const [messages, setMessages] = useState([]);
+ const [input, setInput] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+ const [currentStreamingContent, setCurrentStreamingContent] = useState('');
+ const [currentStreamingId, setCurrentStreamingId] = useState(null);
+ const messagesEndRef = useRef(null);
+ const { user, isAuthenticated, canAccessChat, loading: authLoading } = useAuth();
+
+ // 自动滚动到底部
+ useEffect(() => {
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
+ }, [messages, currentStreamingContent]);
+
+ const extractCodeFromResponse = (content: string) => {
+ // 匹配 markdown 代码块
+ const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
+ const matches = [...content.matchAll(codeBlockRegex)];
+
+ if (matches.length > 0) {
+ // 返回第一个代码块
+ const [, language = 'javascript', code] = matches[0];
+ return {
+ hasCode: true,
+ language,
+ code: code.trim(),
+ textBefore: content.substring(0, matches[0].index),
+ textAfter: content.substring((matches[0].index || 0) + matches[0][0].length)
+ };
+ }
+
+ return { hasCode: false, content };
+ };
+
+ const handleSend = async () => {
+ if (!input.trim() || isLoading) return;
+
+ const userMessage: Message = {
+ id: Date.now().toString(),
+ role: 'user',
+ content: input,
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => [...prev, userMessage]);
+ setInput('');
+ setIsLoading(true);
+ setCurrentStreamingContent('');
+
+ try {
+ // 创建助手消息占位符
+ const assistantMessageId = (Date.now() + 1).toString();
+ setCurrentStreamingId(assistantMessageId);
+
+ const assistantMessage: Message = {
+ id: assistantMessageId,
+ role: 'assistant',
+ content: '',
+ timestamp: new Date(),
+ isStreaming: true,
+ };
+
+ setMessages(prev => [...prev, assistantMessage]);
+
+ // 流式接收回复
+ let fullContent = '';
+ for await (const chunk of mcpService.streamMessage(input)) {
+ fullContent += chunk;
+ setCurrentStreamingContent(fullContent);
+ }
+
+ // 检查回复中是否包含代码
+ const codeInfo = extractCodeFromResponse(fullContent);
+
+ // 更新最终消息
+ setMessages(prev =>
+ prev.map(msg =>
+ msg.id === assistantMessageId
+ ? {
+ ...msg,
+ content: codeInfo.hasCode
+ ? (codeInfo.textBefore || '这是生成的代码:')
+ : fullContent,
+ code: codeInfo.hasCode
+ ? {
+ language: codeInfo.language!,
+ content: codeInfo.code!,
+ title: '生成的代码'
+ }
+ : undefined,
+ isStreaming: false
+ }
+ : msg
+ )
+ );
+
+ setCurrentStreamingContent('');
+ setCurrentStreamingId(null);
+ } catch (error) {
+ console.error('Send message error:', error);
+ setMessages(prev => [
+ ...prev,
+ {
+ id: Date.now().toString(),
+ role: 'system',
+ content: '抱歉,发送消息时出错了。请稍后重试。',
+ timestamp: new Date(),
+ },
+ ]);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // 权限检查
+ 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 (
+
+
+
+ );
+ }
+
+ return (
+
+
+ {messages.length === 0 ? (
+
+
👋 欢迎使用 AI 代码生成助手
+
输入您的需求,我会帮您生成代码
+
+ setInput('生成一个响应式的导航栏组件')}
+ className="text-left p-3 border rounded-lg hover:bg-gray-50 transition-colors"
+ >
+ 💡 生成响应式导航栏
+
+ setInput('创建一个表单验证函数')}
+ className="text-left p-3 border rounded-lg hover:bg-gray-50 transition-colors"
+ >
+ 📝 创建表单验证
+
+ setInput('写一个排序算法')}
+ className="text-left p-3 border rounded-lg hover:bg-gray-50 transition-colors"
+ >
+ 🔢 实现排序算法
+
+ setInput('生成 REST API 接口')}
+ className="text-left p-3 border rounded-lg hover:bg-gray-50 transition-colors"
+ >
+ 🌐 创建 API 接口
+
+
+
+ ) : (
+ <>
+ {messages.map((msg, index) => (
+
+ {msg.role === 'user' ? (
+
{msg.content}
+ ) : msg.role === 'assistant' ? (
+
+
+ {msg.isStreaming ? (
+
+ {msg.id === currentStreamingId ? currentStreamingContent : msg.content}
+ {msg.id === currentStreamingId && !currentStreamingContent && (
+ 思考中...
+ )}
+
+ ) : (
+ <>
+ {msg.content && (
+
{msg.content}
+ )}
+ {msg.code && (
+
{}}
+ isGenerating={false}
+ readOnly={false}
+ />
+ )}
+ >
+ )}
+
+
+ ) : (
+
+ {msg.content}
+
+ )}
+
+ ))}
+
+ >
+ )}
+
+
+ );
+};
+
+export default MCPGenerateCodePage;
\ No newline at end of file