src/app/chat/page.tsx | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/app/globals.css | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/app/page.tsx | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/SceneIntroDialog.tsx | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
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> ); } 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; } 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ä¼å¿å ¨æ¯ - ç¬ç«åºå */} 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 (