138 lines
3.8 KiB
TypeScript
138 lines
3.8 KiB
TypeScript
/**
|
|
* SSASidebar - V11 左侧抽屉栏
|
|
*
|
|
* 100% 还原 V11 原型图
|
|
* - 汉堡菜单切换展开/收起
|
|
* - Logo + 新建按钮
|
|
* - 历史记录列表(展开时显示)
|
|
*/
|
|
import React, { useState, useEffect } from 'react';
|
|
import {
|
|
Menu,
|
|
BarChart3,
|
|
Plus,
|
|
MessageSquare
|
|
} from 'lucide-react';
|
|
import { useSSAStore } from '../stores/ssaStore';
|
|
import apiClient from '@/common/api/axios';
|
|
import type { SSASession } from '../types';
|
|
|
|
interface HistoryItem {
|
|
id: string;
|
|
title: string;
|
|
status: 'active' | 'completed' | 'archived';
|
|
}
|
|
|
|
export const SSASidebar: React.FC = () => {
|
|
const {
|
|
sidebarExpanded,
|
|
setSidebarExpanded,
|
|
currentSession,
|
|
hydrateFromHistory,
|
|
reset
|
|
} = useSSAStore();
|
|
|
|
const [historyItems, setHistoryItems] = useState<HistoryItem[]>([]);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (sidebarExpanded) {
|
|
fetchHistory();
|
|
}
|
|
}, [sidebarExpanded]);
|
|
|
|
const fetchHistory = async () => {
|
|
setIsLoading(true);
|
|
try {
|
|
const response = await apiClient.get('/api/v1/ssa/sessions');
|
|
setHistoryItems(response.data.sessions || []);
|
|
} catch (error) {
|
|
console.error('Failed to fetch history:', error);
|
|
setHistoryItems([]);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleToggleSidebar = () => {
|
|
setSidebarExpanded(!sidebarExpanded);
|
|
};
|
|
|
|
const handleNewAnalysis = () => {
|
|
reset();
|
|
};
|
|
|
|
const handleSelectSession = async (sessionId: string) => {
|
|
if (sessionId === currentSession?.id) return;
|
|
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/ssa/sessions/${sessionId}`);
|
|
const session: SSASession = response.data;
|
|
hydrateFromHistory(session);
|
|
} catch (error) {
|
|
console.error('Failed to load session:', error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<aside className={`ssa-sidebar ${sidebarExpanded ? 'expanded' : ''}`}>
|
|
{/* 顶部:汉堡菜单与 Logo */}
|
|
<div className="sidebar-header">
|
|
<button
|
|
className="sidebar-toggle-btn"
|
|
onClick={handleToggleSidebar}
|
|
>
|
|
<Menu size={18} />
|
|
</button>
|
|
{sidebarExpanded && (
|
|
<div className="sidebar-logo fade-in">
|
|
<div className="logo-icon">
|
|
<BarChart3 size={14} />
|
|
</div>
|
|
<span className="logo-text">SSA-Pro</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* 核心操作区 */}
|
|
<div className="sidebar-actions">
|
|
{/* 新建按钮 */}
|
|
<button
|
|
className={`sidebar-new-btn ${sidebarExpanded ? 'expanded' : ''}`}
|
|
onClick={handleNewAnalysis}
|
|
>
|
|
<Plus size={16} className="new-btn-icon" />
|
|
{sidebarExpanded && <span className="new-btn-text">新建分析</span>}
|
|
</button>
|
|
</div>
|
|
|
|
{/* 历史记录列表 (展开时显示) */}
|
|
{sidebarExpanded && (
|
|
<div className="sidebar-history fade-in">
|
|
<div className="history-label">近期分析</div>
|
|
<div className="history-list">
|
|
{isLoading ? (
|
|
<div className="history-loading">加载中...</div>
|
|
) : historyItems.length === 0 ? (
|
|
<div className="history-empty">暂无历史记录</div>
|
|
) : (
|
|
historyItems.map((item) => (
|
|
<button
|
|
key={item.id}
|
|
className={`history-item ${item.id === currentSession?.id ? 'active' : ''}`}
|
|
onClick={() => handleSelectSession(item.id)}
|
|
>
|
|
<MessageSquare size={14} className="history-item-icon" />
|
|
<span className="history-item-title">{item.title}</span>
|
|
</button>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</aside>
|
|
);
|
|
};
|
|
|
|
export default SSASidebar;
|