feat(frontend):优化前端页面设计
This commit is contained in:
+63
-123
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { TopBar } from './components/Layout/TopBar';
|
||||
import { CollapsibleSidebar } from './components/Layout/CollapsibleSidebar';
|
||||
import { SettingsLayout } from './components/Settings/SettingsLayout';
|
||||
@@ -10,162 +10,75 @@ import { RightPanel } from './components/Chat/RightPanel';
|
||||
import { WorkflowListView } from './components/Chat/WorkflowListView';
|
||||
import { NewWorkflowDialog } from './components/Chat/NewWorkflowDialog';
|
||||
import { AuthPage } from './components/Auth/AuthPage';
|
||||
import apiClient from './api/client';
|
||||
import type { ChatSessionDB } from './types';
|
||||
|
||||
export interface Message {
|
||||
id: string;
|
||||
role: 'user' | 'assistant' | 'system';
|
||||
content: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface ChatSession {
|
||||
id: string;
|
||||
title: string;
|
||||
messages: Message[];
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
function mapSessionFromDB(s: ChatSessionDB): ChatSession {
|
||||
return {
|
||||
id: s.chat_id,
|
||||
title: s.title,
|
||||
messages: [],
|
||||
updatedAt: new Date(s.updated_at).getTime(),
|
||||
};
|
||||
}
|
||||
import { useAppStore } from './store/useAppStore';
|
||||
import { useChatStore } from './store/useChatStore';
|
||||
|
||||
function App() {
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const {
|
||||
isAuthenticated,
|
||||
setIsAuthenticated,
|
||||
mode,
|
||||
showSettings,
|
||||
workTab,
|
||||
agentTab,
|
||||
applyTheme,
|
||||
} = useAppStore();
|
||||
|
||||
const [mode, setMode] = useState<'work' | 'agent'>('work');
|
||||
const [showSettings, setShowSettings] = useState(false);
|
||||
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
||||
const { loadSessions } = useChatStore();
|
||||
|
||||
const [workTab, setWorkTab] = useState<'chat' | 'workflow'>('chat');
|
||||
const [selectedWorkflow, setSelectedWorkflow] = useState<string | null>(null);
|
||||
|
||||
const [agentTab, setAgentTab] = useState<'plugin' | 'agents'>('plugin');
|
||||
const [settingsTab, setSettingsTab] = useState('users');
|
||||
const [innerAgentTab, setInnerAgentTab] = useState('worker');
|
||||
const [resourceTab, setResourceTab] = useState('skill');
|
||||
|
||||
const [chatSessions, setChatSessions] = useState<ChatSession[]>([]);
|
||||
const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
|
||||
|
||||
const loadChatSessions = useCallback(async () => {
|
||||
try {
|
||||
const response = await apiClient.get('/api/v1/chat');
|
||||
const sessions: ChatSessionDB[] = response.data?.sessions || [];
|
||||
setChatSessions(sessions.map(mapSessionFromDB));
|
||||
} catch (error) {
|
||||
console.error('Failed to load chat sessions', error);
|
||||
}
|
||||
}, []);
|
||||
// Initialize theme on mount
|
||||
useEffect(() => {
|
||||
applyTheme();
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const handler = () => applyTheme();
|
||||
mediaQuery.addEventListener('change', handler);
|
||||
return () => mediaQuery.removeEventListener('change', handler);
|
||||
}, [applyTheme]);
|
||||
|
||||
// Check auth and load sessions
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (token) {
|
||||
setIsAuthenticated(true);
|
||||
}
|
||||
}, []);
|
||||
}, [setIsAuthenticated]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
loadChatSessions();
|
||||
loadSessions();
|
||||
}
|
||||
}, [isAuthenticated, loadChatSessions]);
|
||||
}, [isAuthenticated, loadSessions]);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return <AuthPage onLoginSuccess={() => setIsAuthenticated(true)} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen w-screen bg-slate-50 text-slate-800 font-sans overflow-hidden">
|
||||
<TopBar
|
||||
mode={mode}
|
||||
setMode={setMode}
|
||||
showSettings={showSettings}
|
||||
setShowSettings={setShowSettings}
|
||||
/>
|
||||
<div className="flex flex-col h-screen w-screen bg-bg-primary text-text-primary font-sans overflow-hidden">
|
||||
<TopBar />
|
||||
|
||||
<div className="flex flex-1 overflow-hidden relative">
|
||||
{showSettings ? (
|
||||
<SettingsLayout settingsTab={settingsTab} setSettingsTab={setSettingsTab} />
|
||||
<SettingsLayout />
|
||||
) : (
|
||||
<>
|
||||
<CollapsibleSidebar
|
||||
mode={mode}
|
||||
isOpen={isSidebarOpen}
|
||||
setIsOpen={setIsSidebarOpen}
|
||||
workTab={workTab}
|
||||
setWorkTab={setWorkTab}
|
||||
agentTab={agentTab}
|
||||
setAgentTab={setAgentTab}
|
||||
/>
|
||||
<CollapsibleSidebar />
|
||||
|
||||
<div className="flex-1 flex overflow-hidden">
|
||||
{mode === 'work' && workTab === 'chat' && (
|
||||
<div className="flex-1 p-6 flex overflow-hidden">
|
||||
<div className="flex-1 flex bg-white rounded-3xl shadow-md border border-slate-200 overflow-hidden relative">
|
||||
<LeftPanel
|
||||
activeTab="chats"
|
||||
selectedWorkflow={null}
|
||||
setSelectedWorkflow={() => {}}
|
||||
chatSessions={chatSessions}
|
||||
setChatSessions={setChatSessions}
|
||||
activeSessionId={activeSessionId}
|
||||
setActiveSessionId={setActiveSessionId}
|
||||
onSessionsChanged={loadChatSessions}
|
||||
/>
|
||||
<ChatPanel
|
||||
chatSessions={chatSessions}
|
||||
setChatSessions={setChatSessions}
|
||||
activeSessionId={activeSessionId}
|
||||
setActiveSessionId={setActiveSessionId}
|
||||
onSessionsChanged={loadChatSessions}
|
||||
/>
|
||||
<div className="flex-1 p-4 flex overflow-hidden gap-4">
|
||||
<div className="flex-1 flex bg-bg-card rounded-2xl shadow-sm border border-border-primary overflow-hidden relative">
|
||||
<LeftPanel activeTab="chats" />
|
||||
<ChatPanel />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{mode === 'work' && workTab === 'workflow' && (
|
||||
<>
|
||||
{selectedWorkflow === 'new' ? (
|
||||
<>
|
||||
<LeftPanel
|
||||
activeTab="workflows"
|
||||
selectedWorkflow={selectedWorkflow}
|
||||
setSelectedWorkflow={setSelectedWorkflow}
|
||||
/>
|
||||
<NewWorkflowDialog
|
||||
onClose={() => setSelectedWorkflow(null)}
|
||||
onSuccess={(traceId: string) => setSelectedWorkflow(traceId)}
|
||||
/>
|
||||
</>
|
||||
) : selectedWorkflow ? (
|
||||
<>
|
||||
<LeftPanel
|
||||
activeTab="workflows"
|
||||
selectedWorkflow={selectedWorkflow}
|
||||
setSelectedWorkflow={setSelectedWorkflow}
|
||||
/>
|
||||
<RightPanel selectedWorkflow={selectedWorkflow} />
|
||||
</>
|
||||
) : (
|
||||
<WorkflowListView onSelectWorkflow={setSelectedWorkflow} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{mode === 'work' && workTab === 'workflow' && <WorkflowShell />}
|
||||
|
||||
{mode === 'agent' && agentTab === 'agents' && (
|
||||
<AgentLayout agentTab={innerAgentTab} setAgentTab={setInnerAgentTab} />
|
||||
)}
|
||||
{mode === 'agent' && agentTab === 'agents' && <AgentLayout />}
|
||||
|
||||
{mode === 'agent' && agentTab === 'plugin' && (
|
||||
<PluginLayout resourceTab={resourceTab} setResourceTab={setResourceTab} />
|
||||
)}
|
||||
{mode === 'agent' && agentTab === 'plugin' && <PluginLayout />}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -174,4 +87,31 @@ function App() {
|
||||
);
|
||||
}
|
||||
|
||||
function WorkflowShell() {
|
||||
const { selectedWorkflow, setSelectedWorkflow } = useChatStore();
|
||||
|
||||
if (selectedWorkflow === 'new') {
|
||||
return (
|
||||
<>
|
||||
<LeftPanel activeTab="workflows" />
|
||||
<NewWorkflowDialog
|
||||
onClose={() => setSelectedWorkflow(null)}
|
||||
onSuccess={(traceId: string) => setSelectedWorkflow(traceId)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (selectedWorkflow) {
|
||||
return (
|
||||
<>
|
||||
<LeftPanel activeTab="workflows" />
|
||||
<RightPanel selectedWorkflow={selectedWorkflow} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return <WorkflowListView onSelectWorkflow={setSelectedWorkflow} />;
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
Reference in New Issue
Block a user