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