Browse Source

refactor(side-panel): 重构侧边栏组件布局和功能

- 调整 ChatHistoryList组件,增加返回聊天按钮
- 重构 SidePanel 组件布局,优化历史记录和聊天界面的切换
- 移除 TemplateList组件的引用
- 调整聊天输入框的位置,使其固定在页面底部
- 优化页面样式,增加欢迎信息和调整部分UI布局
wzg 3 months ago
parent
commit
b86ce911e5

+ 56 - 83
pages/side-panel/src/SidePanel.tsx

@@ -8,9 +8,7 @@ import { type Message, Actors, chatHistoryStore } from '@extension/storage';
 import MessageList from './components/MessageList';
 import ChatInput from './components/ChatInput';
 import ChatHistoryList from './components/ChatHistoryList';
-import TemplateList from './components/TemplateList';
 import { EventType, type AgentEvent, ExecutionState } from './types/event';
-import { defaultTemplates } from './templates';
 import './SidePanel.css';
 
 const SidePanel = () => {
@@ -540,60 +538,13 @@ const SidePanel = () => {
     <div>
       <div
         className={`flex h-screen flex-col ${isDarkMode ? 'bg-slate-900' : ''} overflow-hidden border ${isDarkMode ? 'border-sky-800' : 'border-[rgb(186,230,253)]'} rounded-2xl`}>
-        <header className="header relative">
-          <div className="header-logo">
-            {showHistory ? (
-              <button
-                type="button"
-                onClick={handleBackToChat}
-                className={`${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
-                aria-label="返回聊天">
-                ← 返回
-              </button>
-            ) : (
-              <img src="/icon.png" alt="Extension Logo" className="size-6" />
-            )}
-          </div>
-          <div className="header-icons">
-            {!showHistory && (
-              <>
-                <button
-                  type="button"
-                  onClick={handleNewChat}
-                  onKeyDown={e => e.key === 'Enter' && handleNewChat()}
-                  className={`header-icon ${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
-                  aria-label="New Chat"
-                  tabIndex={0}>
-                  <PiPlusBold size={20} />
-                </button>
-                <button
-                  type="button"
-                  onClick={handleLoadHistory}
-                  onKeyDown={e => e.key === 'Enter' && handleLoadHistory()}
-                  className={`header-icon ${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
-                  aria-label="Load History"
-                  tabIndex={0}>
-                  <GrHistory size={20} />
-                </button>
-              </>
-            )}
-            <button
-              type="button"
-              onClick={() => chrome.runtime.openOptionsPage()}
-              onKeyDown={e => e.key === 'Enter' && chrome.runtime.openOptionsPage()}
-              className={`header-icon ${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
-              aria-label="Settings"
-              tabIndex={0}>
-              <FiSettings size={20} />
-            </button>
-          </div>
-        </header>
         {showHistory ? (
           <div className="flex-1 overflow-hidden">
             <ChatHistoryList
               sessions={chatSessions}
               onSessionSelect={handleSessionSelect}
               onSessionDelete={handleSessionDelete}
+              handleBackToChat={handleBackToChat}
               visible={true}
               isDarkMode={isDarkMode}
             />
@@ -602,26 +553,14 @@ const SidePanel = () => {
           <>
             {messages.length === 0 && (
               <>
-                <div
-                  className={`border-t ${isDarkMode ? 'border-sky-900' : 'border-sky-100'} mb-2 p-2 shadow-sm backdrop-blur-sm`}>
-                  <ChatInput
-                    onSendMessage={handleSendMessage}
-                    onStopTask={handleStopTask}
-                    disabled={!inputEnabled || isHistoricalSession}
-                    showStopButton={showStopButton}
-                    setContent={setter => {
-                      setInputTextRef.current = setter;
-                    }}
-                    isDarkMode={isDarkMode}
-                  />
+                <div className="w-full h-full pt-20">
+                  <div className="max-w-[720px] text-left m-auto p-5">
+                    <p className="font-black text-4xl mb-4 text-black">你好,</p>
+                    <p className="font-black text-3xl mb-4 text-black">我是PVS智能助手,</p>
+                    <p className="font-black text-2xl mb-4 text-black">我今天能帮你什么?</p>
+                    {/*<span className="text-black">作为你的智能伙伴,我既能写文案、想点子,又能陪你聊天、答疑解惑。</span>*/}
+                  </div>
                 </div>
-                {/*<div>*/}
-                {/*  <TemplateList*/}
-                {/*    templates={defaultTemplates}*/}
-                {/*    onTemplateSelect={handleTemplateSelect}*/}
-                {/*    isDarkMode={isDarkMode}*/}
-                {/*  />*/}
-                {/*</div>*/}
               </>
             )}
             <div
@@ -629,21 +568,55 @@ const SidePanel = () => {
               <MessageList messages={messages} isDarkMode={isDarkMode} />
               <div ref={messagesEndRef} />
             </div>
-            {messages.length > 0 && (
-              <div
-                className={`border-t ${isDarkMode ? 'border-sky-900' : 'border-sky-100'} p-2 shadow-sm backdrop-blur-sm`}>
-                <ChatInput
-                  onSendMessage={handleSendMessage}
-                  onStopTask={handleStopTask}
-                  disabled={!inputEnabled || isHistoricalSession}
-                  showStopButton={showStopButton}
-                  setContent={setter => {
-                    setInputTextRef.current = setter;
-                  }}
-                  isDarkMode={isDarkMode}
-                />
+            <header className="header relative">
+              <div className="header-logo"></div>
+              <div className="header-icons">
+                {!showHistory && (
+                  <>
+                    <button
+                      type="button"
+                      onClick={handleNewChat}
+                      onKeyDown={e => e.key === 'Enter' && handleNewChat()}
+                      className={`header-icon ${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
+                      aria-label="New Chat"
+                      tabIndex={0}>
+                      <PiPlusBold size={20} />
+                    </button>
+                    <button
+                      type="button"
+                      onClick={handleLoadHistory}
+                      onKeyDown={e => e.key === 'Enter' && handleLoadHistory()}
+                      className={`header-icon ${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
+                      aria-label="Load History"
+                      tabIndex={0}>
+                      <GrHistory size={20} />
+                    </button>
+                  </>
+                )}
+                <button
+                  type="button"
+                  onClick={() => chrome.runtime.openOptionsPage()}
+                  onKeyDown={e => e.key === 'Enter' && chrome.runtime.openOptionsPage()}
+                  className={`header-icon ${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer`}
+                  aria-label="Settings"
+                  tabIndex={0}>
+                  <FiSettings size={20} />
+                </button>
               </div>
-            )}
+            </header>
+            <div
+              className={`border-t ${isDarkMode ? 'border-sky-900' : 'border-sky-100'} p-2 shadow-sm backdrop-blur-sm`}>
+              <ChatInput
+                onSendMessage={handleSendMessage}
+                onStopTask={handleStopTask}
+                disabled={!inputEnabled || isHistoricalSession}
+                showStopButton={showStopButton}
+                setContent={setter => {
+                  setInputTextRef.current = setter;
+                }}
+                isDarkMode={isDarkMode}
+              />
+            </div>
           </>
         )}
       </div>

+ 15 - 3
pages/side-panel/src/components/ChatHistoryList.tsx

@@ -1,4 +1,3 @@
-/* eslint-disable react/prop-types */
 import { FaTrash } from 'react-icons/fa';
 
 interface ChatSession {
@@ -11,19 +10,22 @@ interface ChatHistoryListProps {
   sessions: ChatSession[];
   onSessionSelect: (sessionId: string) => void;
   onSessionDelete: (sessionId: string) => void;
+  handleBackToChat: () => void;
   visible: boolean;
   isDarkMode?: boolean;
 }
 
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-expect-error
 const ChatHistoryList: React.FC<ChatHistoryListProps> = ({
   sessions,
   onSessionSelect,
   onSessionDelete,
+  handleBackToChat,
   visible,
   isDarkMode = false,
 }) => {
   if (!visible) return null;
-
   const formatDate = (timestamp: number) => {
     const date = new Date(timestamp);
     return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
@@ -31,7 +33,17 @@ const ChatHistoryList: React.FC<ChatHistoryListProps> = ({
 
   return (
     <div className="h-full overflow-y-auto p-4">
-      <h2 className={`mb-4 text-lg font-semibold ${isDarkMode ? 'text-gray-200' : 'text-gray-800'}`}>历史对话</h2>
+      <h2
+        className={`mb-4 flex  justify-between text-lg font-semibold ${isDarkMode ? 'text-gray-200' : 'text-gray-800'}`}>
+        <span>历史对话</span>
+        <button
+          type="button"
+          onClick={handleBackToChat}
+          className={`${isDarkMode ? 'text-sky-400 hover:text-sky-300' : 'text-sky-400 hover:text-sky-500'} cursor-pointer text-xs font-normal`}
+          aria-label="返回聊天">
+          返回
+        </button>
+      </h2>
       {sessions.length === 0 ? (
         <div
           className={`rounded-lg ${isDarkMode ? 'bg-slate-800 text-gray-400' : 'bg-white/30 text-gray-500'} p-4 text-center backdrop-blur-sm`}>