From c1c456128bec733c46ad03a09a5bae4c79e02367 Mon Sep 17 00:00:00 2001
From: hongjli <3117313295@qq.com>
Date: 星期四, 10 四月 2025 10:18:54 +0800
Subject: [PATCH] 新建聊天页面

---
 src/components/SceneIntroDialog.tsx           |   12 ++
 src/app/ai-scene/chat/page.tsx                |  176 ++++++++++++++++++++++++++++++++++++++++++++
 src/app/ai-scene/chat/layout.tsx              |   14 +++
 src/app/ai-scene/page.tsx                     |   16 ----
 src/components/layout/ClientLayoutContent.tsx |   13 ++-
 5 files changed, 207 insertions(+), 24 deletions(-)

diff --git a/src/app/ai-scene/chat/layout.tsx b/src/app/ai-scene/chat/layout.tsx
new file mode 100644
index 0000000..b11194e
--- /dev/null
+++ b/src/app/ai-scene/chat/layout.tsx
@@ -0,0 +1,14 @@
+import type { Metadata } from 'next';
+
+export const metadata: Metadata = {
+  title: 'AI鍦烘櫙妯℃嫙鑱婂ぉ',
+  description: '鏅鸿兘鍖栦緵搴旈摼绠$悊锛孉I妯℃嫙APS鍦烘櫙鐨勯鑸��',
+};
+
+export default function Layout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  return children;
+} 
\ No newline at end of file
diff --git a/src/app/ai-scene/chat/page.tsx b/src/app/ai-scene/chat/page.tsx
new file mode 100644
index 0000000..52f1cb3
--- /dev/null
+++ b/src/app/ai-scene/chat/page.tsx
@@ -0,0 +1,176 @@
+"use client";
+
+import { useState, useEffect } from 'react';
+import { motion, AnimatePresence } from 'framer-motion';
+
+// 瀵煎叆鍦烘櫙鏁版嵁
+const services = [
+  {
+    title: '琛ユ枡',
+    description: '鏅鸿兘鍔ㄦ�佸垎鏋愪骇绾匡紝宸ヤ綅鐨勭己鏂欐儏鍐碉紝闄嶄綆鍋滅嚎椋庨櫓',
+    imageUrl: '/images/kanban.jpg',
+    chatbotId: 'JELkWpPLHQfRNhEH',
+  },
+  {
+    title: '鎻掑崟',
+    description: '鏅鸿兘璇勪及闇�姹傛彃鍗曞浜ц兘锛屽師鏉愭枡鍜屼氦浠樻湇鍔$殑褰卞搷锛屾彁鍗囧鎴锋弧鎰忓害',
+    imageUrl: '/images/xuqiu.jpg',
+    chatbotId: 'DfH4cIzujVGvn5iR',
+  },
+  {
+    title: '绉戞矁鏂攢鍞帹鑽愬皬鍔╂墜',
+    description: '鏅鸿兘鍖栦骇鍝佹帹鑽愭彁鍗囧璐晥鐜�',
+    imageUrl: '/images/robot.jpg',
+    chatbotId: 'sUAviPXvcEIw3oQC',
+  },
+  {
+    title: '搴撳瓨绠$悊鐭ヨ瘑搴撻棶绛�',
+    description: '搴撳瓨鐭ヨ瘑锛屾彁渚涗笓涓氱殑渚涘簲閾惧簱瀛樼煡璇嗛棶绛�',
+    imageUrl: '/images/know.jpg',
+    chatbotId: 'pDDfkU9HyBl2gzXx',
+  },
+];
+
+export default function AISceneChatPage() {
+  const [selectedScene, setSelectedScene] = useState(services[0]);
+  const [iframeKey, setIframeKey] = useState(0); // 鐢ㄤ簬寮哄埗鍒锋柊iframe
+
+  // 鍒囨崲鍦烘櫙鏃堕噸鏂板姞杞絠frame
+  const handleSceneChange = (scene: typeof services[0]) => {
+    setSelectedScene(scene);
+    setIframeKey(prev => prev + 1);
+  };
+
+  return (
+    <div className="h-screen flex bg-[#0A1033]">
+      {/* 宸︿晶鍦烘櫙閫夐」鍗� */}
+      <div className="w-64 bg-[#131C41] border-r border-[#6ADBFF]/20 flex flex-col">
+        <div className="p-4 flex-1 overflow-y-auto">
+          <h2 className="text-xl font-bold text-white mb-6 flex items-center">
+            <span className="text-transparent bg-clip-text bg-gradient-to-r from-[#6ADBFF] to-[#5E72EB]">
+              AI鍦烘櫙
+            </span>
+            <motion.span 
+              className="ml-2 inline-block w-2 h-2 rounded-full bg-[#6ADBFF]"
+              animate={{ 
+                scale: [1, 1.5, 1],
+                opacity: [0.7, 1, 0.7] 
+              }}
+              transition={{ 
+                duration: 2,
+                repeat: Infinity,
+                ease: "easeInOut"
+              }}
+            />
+          </h2>
+          <div className="space-y-3">
+            {services.map((scene) => (
+              <motion.button
+                key={scene.chatbotId}
+                onClick={() => handleSceneChange(scene)}
+                className={`w-full p-4 rounded-lg text-left transition-all duration-500 relative overflow-hidden
+                  ${selectedScene.chatbotId === scene.chatbotId 
+                    ? 'text-[#6ADBFF]' 
+                    : 'text-gray-300 hover:text-[#6ADBFF]'
+                  }`}
+                whileHover={{ scale: 1.02 }}
+                whileTap={{ scale: 0.98 }}
+              >
+                {selectedScene.chatbotId === scene.chatbotId && (
+                  <motion.div
+                    className="absolute inset-0 bg-gradient-to-r from-[#1A2547] to-[#1E2B63] -z-10"
+                    layoutId="activeBackground"
+                    initial={false}
+                    transition={{
+                      type: "spring",
+                      stiffness: 200,
+                      damping: 20
+                    }}
+                  />
+                )}
+                <div className="flex items-center relative z-10">
+                  <div className="w-10 h-10 rounded-lg overflow-hidden mr-3 relative">
+                    <img 
+                      src={scene.imageUrl} 
+                      alt={scene.title}
+                      className="w-full h-full object-cover transform transition-transform duration-700 group-hover:scale-110"
+                    />
+                    <div className="absolute inset-0 bg-gradient-to-br from-black/20 to-transparent"></div>
+                  </div>
+                  <div>
+                    <span className="font-medium block">{scene.title}</span>
+                    <span className="text-xs text-gray-400 line-clamp-1">{scene.description}</span>
+                  </div>
+                </div>
+                {selectedScene.chatbotId === scene.chatbotId && (
+                  <motion.div
+                    className="absolute right-3 top-1/2 -translate-y-1/2 w-1.5 h-6 bg-[#6ADBFF] rounded-full"
+                    layoutId="activeIndicator"
+                    initial={{ opacity: 0 }}
+                    animate={{ opacity: 1 }}
+                    exit={{ opacity: 0 }}
+                  />
+                )}
+              </motion.button>
+            ))}
+          </div>
+        </div>
+      </div>
+
+      {/* 涓棿鑱婂ぉ鍖哄煙 */}
+      <div className="flex-1 flex flex-col bg-gradient-to-br from-[#0A1033] to-[#131C41]">
+        {/* 椤堕儴鏍囬鏍� */}
+        <div className="h-16 border-b border-[#6ADBFF]/20 flex items-center px-6 bg-[#131C41]/50 backdrop-blur-sm">
+          <AnimatePresence mode="wait">
+            <motion.div
+              key={selectedScene.chatbotId}
+              initial={{ opacity: 0, y: -20 }}
+              animate={{ opacity: 1, y: 0 }}
+              exit={{ opacity: 0, y: 20 }}
+              transition={{ duration: 0.3 }}
+              className="flex items-center"
+            >
+              <div className="w-8 h-8 rounded-lg overflow-hidden mr-3 relative">
+                <img 
+                  src={selectedScene.imageUrl} 
+                  alt={selectedScene.title}
+                  className="w-full h-full object-cover"
+                />
+                <div className="absolute inset-0 bg-gradient-to-br from-black/20 to-transparent"></div>
+              </div>
+              <div>
+                <h1 className="text-xl font-bold text-white">
+                  {selectedScene.title}
+                </h1>
+                <p className="text-sm text-gray-400">
+                  {selectedScene.description}
+                </p>
+              </div>
+            </motion.div>
+          </AnimatePresence>
+        </div>
+
+        {/* 鑱婂ぉ绐楀彛 */}
+        <div className="flex-1 relative">
+          <AnimatePresence mode="wait">
+            <motion.div
+              key={iframeKey}
+              className="absolute inset-0"
+              initial={{ opacity: 0, scale: 0.98 }}
+              animate={{ opacity: 1, scale: 1 }}
+              exit={{ opacity: 0, scale: 1.02 }}
+              transition={{ duration: 0.3 }}
+            >
+              <iframe
+                src={`http://121.43.139.99/chatbot/${selectedScene.chatbotId}`}
+                className="w-full h-full"
+                style={{ border: 'none' }}
+                allow="microphone"
+              />
+            </motion.div>
+          </AnimatePresence>
+        </div>
+      </div>
+    </div>
+  );
+} 
\ No newline at end of file
diff --git a/src/app/ai-scene/page.tsx b/src/app/ai-scene/page.tsx
index c39a22c..7828665 100644
--- a/src/app/ai-scene/page.tsx
+++ b/src/app/ai-scene/page.tsx
@@ -2,7 +2,6 @@
 
 import { useState } from 'react';
 import Card from '@/components/Card';
-import ChatDialog from '@/components/ChatDialog';
 import SceneIntroDialog from '@/components/SceneIntroDialog';
 import { motion } from 'framer-motion';
 
@@ -83,20 +82,12 @@
 ];
 
 export default function AIScenePage() {
-  const [isChatOpen, setIsChatOpen] = useState(false);
   const [isIntroOpen, setIsIntroOpen] = useState(false);
-  const [currentChatbot, setCurrentChatbot] = useState('');
   const [selectedScene, setSelectedScene] = useState(services[0]);
 
   const handleCardClick = (service: typeof services[0]) => {
     setSelectedScene(service);
     setIsIntroOpen(true);
-  };
-
-  const handleStartChat = () => {
-    setIsIntroOpen(false);
-    setCurrentChatbot(selectedScene.chatbotId);
-    setIsChatOpen(true);
   };
 
   return (
@@ -150,14 +141,7 @@
         <SceneIntroDialog
           isOpen={isIntroOpen}
           onClose={() => setIsIntroOpen(false)}
-          onStartChat={handleStartChat}
           scene={selectedScene}
-        />
-        
-        <ChatDialog 
-          isOpen={isChatOpen} 
-          onClose={() => setIsChatOpen(false)}
-          chatbotId={currentChatbot}
         />
       </div>
     </>
diff --git a/src/components/SceneIntroDialog.tsx b/src/components/SceneIntroDialog.tsx
index 89a999a..c5d8a36 100644
--- a/src/components/SceneIntroDialog.tsx
+++ b/src/components/SceneIntroDialog.tsx
@@ -4,11 +4,11 @@
 import { Fragment, useEffect, useState } from 'react';
 import { motion, AnimatePresence } from 'framer-motion';
 import DataPreviewDialog from './DataPreviewDialog';
+import { useRouter } from 'next/navigation';
 
 interface SceneIntroDialogProps {
   isOpen: boolean;
   onClose: () => void;
-  onStartChat: () => void;
   scene: {
     title: string;
     description: string;
@@ -17,16 +17,17 @@
     instructions?: string;
     dataDescription?: string;
     exampleData?: string;
+    chatbotId: string;
   };
 }
 
 export default function SceneIntroDialog({
   isOpen,
   onClose,
-  onStartChat,
   scene
 }: SceneIntroDialogProps) {
   const [showDataPreview, setShowDataPreview] = useState(false);
+  const router = useRouter();
 
   // 纭繚鍔ㄧ敾鐘舵�佸湪姣忔鎵撳紑鏃堕兘琚噸缃�
   useEffect(() => {
@@ -42,6 +43,11 @@
       });
     }
   }, [isOpen]);
+
+  const handleStartChat = () => {
+    onClose();
+    router.push('/ai-scene/chat');
+  };
 
   return (
     <AnimatePresence>
@@ -143,7 +149,7 @@
                             transition={{ duration: 0.5, delay: 0.3 }}
                           >
                             <button
-                              onClick={onStartChat}
+                              onClick={handleStartChat}
                               className="group relative w-64 cursor-pointer"
                             >
                               <div className="absolute -inset-0.5 rounded-lg bg-gradient-to-r from-[#6ADBFF] to-[#5E72EB] opacity-60 blur group-hover:opacity-100 transition-all duration-300"></div>
diff --git a/src/components/layout/ClientLayoutContent.tsx b/src/components/layout/ClientLayoutContent.tsx
index 2022e09..19286e6 100644
--- a/src/components/layout/ClientLayoutContent.tsx
+++ b/src/components/layout/ClientLayoutContent.tsx
@@ -12,14 +12,17 @@
   const [isClient, setIsClient] = useState(false);
   const [hasError, setHasError] = useState(false);
   const pathname = usePathname();
-  const isLoginPage = pathname === '/login';
-  const isRegisterPage = pathname === '/register';
-  const isHomePage = pathname === '/';
-  const isAIScenePage = pathname.startsWith('/ai-scene');
 
   useEffect(() => {
     setIsClient(true);
   }, []);
+
+  // 鍒ゆ柇褰撳墠椤甸潰
+  const isLoginPage = pathname === '/login';
+  const isRegisterPage = pathname === '/register';
+  const isHomePage = pathname === '/';
+  const isAIScenePage = pathname === '/ai-scene';
+  const isAISceneChatPage = pathname.startsWith('/ai-scene/chat');
 
   // 娣诲姞閿欒鎹曡幏
   useEffect(() => {
@@ -65,7 +68,7 @@
             <main className={`flex-1 ${isHomePage || isAIScenePage ? '' : 'bg-gradient-to-b from-[var(--ai-surface)] to-white'} pt-0 mt-0`}>
               {children}
             </main>
-            {!isLoginPage && !isRegisterPage && (
+            {!isLoginPage && !isRegisterPage && !isAISceneChatPage && (
               <footer className="relative z-20 bg-gradient-to-br from-[#0A1033] via-[#1E2B63] to-[#131C41] text-white py-10 overflow-hidden">
                 {/* 绉戞妧鎰熷姩鎬佽儗鏅厓绱� */}
                 <div className="absolute inset-0 overflow-hidden pointer-events-none">

--
Gitblit v1.9.3