From 57f311036b7e97453413b47ebe5d1248dfff50cc Mon Sep 17 00:00:00 2001 From: hongjli <3117313295@qq.com> Date: 星期三, 23 四月 2025 15:14:02 +0800 Subject: [PATCH] 新建聊天页面 --- src/components/SceneIntroDialog.tsx | 7 +- src/app/globals.css | 22 +++++++ src/app/page.tsx | 32 +++++++++- src/app/chat/page.tsx | 70 +++++++++++++++++++++++ 4 files changed, 123 insertions(+), 8 deletions(-) diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx new file mode 100644 index 0000000..415bf60 --- /dev/null +++ b/src/app/chat/page.tsx @@ -0,0 +1,70 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; + +export default function Page() { + const router = useRouter(); + const [token, setToken] = useState<string | null>(null); + + useEffect(() => { + // 鑾峰彇token + const storedToken = localStorage.getItem('token'); + setToken(storedToken); + + // 濡傛灉娌℃湁token锛岀洿鎺ヨ烦杞埌鐧诲綍椤甸潰 + if (!storedToken) { + router.push('/login'); + } + }, []); + + // 濡傛灉娌℃湁token锛屼笉娓叉煋浠讳綍鍐呭 + if (!token) { + return null; + } + + return ( + <div className="min-h-screen bg-[#0A1033] text-white"> + {/* 椤堕儴瀵艰埅 */} + <div className="bg-[#131C41] p-4 border-b border-[#6ADBFF]/20"> + <div className="max-w-4xl mx-auto flex justify-between items-center"> + <Link href="/" className="text-[#6ADBFF] hover:underline flex items-center gap-2"> + <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> + <path fillRule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clipRule="evenodd" /> + </svg> + 杩斿洖棣栭〉 + </Link> + <h1 className="text-xl font-bold">AI鍔╂墜瀵硅瘽</h1> + </div> + </div> + + {/* 鑱婂ぉ鍖哄煙 */} + <div className="max-w-4xl mx-auto p-4"> + <div className="space-y-4 mb-20"> + <div className="flex justify-start"> + <div className="max-w-[80%] rounded-lg p-4 bg-[#131C41]"> + <p>浣犲ソ锛佹杩庢潵鍒拌亰澶╁銆�</p> + </div> + </div> + </div> + </div> + + {/* 杈撳叆鍖哄煙 */} + <div className="fixed bottom-0 left-0 right-0 bg-[#131C41] border-t border-[#6ADBFF]/20 p-4"> + <div className="max-w-4xl mx-auto flex gap-4"> + <input + type="text" + placeholder="杈撳叆娑堟伅..." + className="flex-1 bg-[#1E2B63] rounded-lg px-4 py-2 text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#6ADBFF]/50" + /> + <button + className="bg-gradient-to-r from-[#6ADBFF] to-[#5E72EB] text-white px-6 py-2 rounded-lg font-medium hover:opacity-90 transition-opacity" + > + 鍙戦�� + </button> + </div> + </div> + </div> + ); +} diff --git a/src/app/globals.css b/src/app/globals.css index 9ed40ec..7a4563e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -44,6 +44,8 @@ color: rgb(var(--foreground-rgb)); font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif; min-height: 100vh; + opacity: 1; + transition: opacity 0.2s ease-out; } /* 婊氬姩鎬ц兘浼樺寲 */ @@ -819,3 +821,23 @@ .animate-error-scan { animation: error-scan 2s linear infinite; } + +/* 椤甸潰杩囨浮鏁堟灉 */ +.page-transitioning { + animation: fadeOut 0.2s ease-out forwards; + pointer-events: none; +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +/* 闃叉閾炬帴鐐瑰嚮鏃剁殑闂儊 */ +.no-flash-link { + -webkit-tap-highlight-color: transparent; +} diff --git a/src/app/page.tsx b/src/app/page.tsx index af7c629..735bd5f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -171,7 +171,17 @@ {/* 浜や簰鎸夐挳缁� - 椤堕儴 */} <div className="flex flex-col sm:flex-row items-center justify-center gap-6 mb-20"> - <a href="/ai-scene"> + <a + href="/ai-scene" + className="no-flash-link" + onClick={(e) => { + e.preventDefault(); + document.body.classList.add('page-transitioning'); + setTimeout(() => { + window.location.href = '/ai-scene'; + }, 100); + }} + > <motion.div custom={0} initial="hidden" @@ -179,7 +189,7 @@ viewport={{ once: false, margin: "-100px" }} variants={buttonVariants} whileTap={{ scale: 0.97, transition: { duration: 0.1 } }} - className="group relative will-change-transform" + className="group relative will-change-transform cursor-pointer" > <div className="absolute -inset-0.5 rounded-xl bg-gradient-to-r from-[#6ADBFF] to-[#5E72EB] opacity-30 blur group-hover:opacity-100 group-hover:blur-md transition-all duration-500 group-hover:duration-200 group-active:opacity-70"></div> <div className="relative flex items-center gap-2 px-10 py-4 rounded-lg backdrop-blur-sm bg-[#131C41]/90 border border-[#6ADBFF]/30 transition-all duration-300 shadow-[0_0_15px_rgba(106,219,255,0.15)] group-hover:shadow-[0_0_25px_rgba(106,219,255,0.25)] group-active:shadow-[0_0_10px_rgba(106,219,255,0.3)]"> @@ -214,7 +224,19 @@ </motion.div> </a> - <Link href="/chat"> + <a + href="/chat" + className="no-flash-link" + onClick={(e) => { + e.preventDefault(); + document.body.classList.add('page-transitioning'); + const token = localStorage.getItem('token'); + const targetUrl = token ? '/chat' : '/login'; + setTimeout(() => { + window.location.href = targetUrl; + }, 100); + }} + > <motion.div custom={1} initial="hidden" @@ -222,7 +244,7 @@ viewport={{ once: false, margin: "-100px" }} variants={buttonVariants} whileTap={{ scale: 0.97, transition: { duration: 0.1 } }} - className="group relative will-change-transform" + className="group relative will-change-transform cursor-pointer" > <div className="absolute -inset-0.5 rounded-xl bg-gradient-to-r from-[#FF6A88] to-[#5E72EB] opacity-30 blur group-hover:opacity-100 group-hover:blur-md transition-all duration-500 group-hover:duration-200 group-active:opacity-70"></div> <div className="relative flex items-center gap-2 px-10 py-4 rounded-lg backdrop-blur-sm bg-[#131C41]/90 border border-[#FF6A88]/30 transition-all duration-300 shadow-[0_0_15px_rgba(255,106,136,0.15)] group-hover:shadow-[0_0_25px_rgba(255,106,136,0.25)] group-active:shadow-[0_0_10px_rgba(255,106,136,0.3)]"> @@ -255,7 +277,7 @@ </div> </div> </motion.div> - </Link> + </a> </div> {/* AI璧嬭兘APS浼樺娍鍏ㄦ櫙 - 鐙珛鍖哄潡 */} diff --git a/src/components/SceneIntroDialog.tsx b/src/components/SceneIntroDialog.tsx index a79138c..fea9b41 100644 --- a/src/components/SceneIntroDialog.tsx +++ b/src/components/SceneIntroDialog.tsx @@ -4,7 +4,6 @@ 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; @@ -27,7 +26,6 @@ scene }: SceneIntroDialogProps) { const [showDataPreview, setShowDataPreview] = useState(false); - const router = useRouter(); // 纭繚鍔ㄧ敾鐘舵�佸湪姣忔鎵撳紑鏃堕兘琚噸缃� useEffect(() => { @@ -46,7 +44,10 @@ const handleStartChat = () => { onClose(); - router.push(`/ai-scene/chat?scene=${scene.chatbotId}`); + document.body.classList.add('page-transitioning'); + setTimeout(() => { + window.location.href = `/ai-scene/chat?scene=${scene.chatbotId}`; + }, 100); }; return ( -- Gitblit v1.9.3