From 80084d607b79b41697f7205180eec57ee1440af8 Mon Sep 17 00:00:00 2001
From: zdl <3489966805@qq.com>
Date: Mon, 24 Nov 2025 15:11:19 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=20LeftSidebar=20(~280=20=E8=A1=8C)=20-?=
=?UTF-8?q?=20=E5=AF=B9=E8=AF=9D=E5=8E=86=E5=8F=B2=E5=88=97=E8=A1=A8=20+?=
=?UTF-8?q?=20=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E5=8D=A1=E7=89=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../components/LeftSidebar/SessionCard.js | 76 +++++
.../AgentChat/components/LeftSidebar/index.js | 313 ++++++++++++++++++
2 files changed, 389 insertions(+)
create mode 100644 src/views/AgentChat/components/LeftSidebar/SessionCard.js
create mode 100644 src/views/AgentChat/components/LeftSidebar/index.js
diff --git a/src/views/AgentChat/components/LeftSidebar/SessionCard.js b/src/views/AgentChat/components/LeftSidebar/SessionCard.js
new file mode 100644
index 00000000..63a4ef23
--- /dev/null
+++ b/src/views/AgentChat/components/LeftSidebar/SessionCard.js
@@ -0,0 +1,76 @@
+// src/views/AgentChat/components/LeftSidebar/SessionCard.js
+// 会话卡片组件
+
+import React from 'react';
+import { motion } from 'framer-motion';
+import { Card, CardBody, Flex, Box, Text, Badge } from '@chakra-ui/react';
+
+/**
+ * SessionCard - 会话卡片组件
+ *
+ * @param {Object} props
+ * @param {Object} props.session - 会话数据
+ * @param {boolean} props.isActive - 是否为当前选中的会话
+ * @param {Function} props.onPress - 点击回调函数
+ * @returns {JSX.Element}
+ */
+const SessionCard = ({ session, isActive, onPress }) => {
+ return (
+
+
+
+
+
+
+ {session.title || '新对话'}
+
+
+ {new Date(session.created_at || session.timestamp).toLocaleString('zh-CN', {
+ month: 'numeric',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ })}
+
+
+ {session.message_count && (
+
+ {session.message_count}
+
+ )}
+
+
+
+
+ );
+};
+
+export default SessionCard;
diff --git a/src/views/AgentChat/components/LeftSidebar/index.js b/src/views/AgentChat/components/LeftSidebar/index.js
new file mode 100644
index 00000000..9f9e810d
--- /dev/null
+++ b/src/views/AgentChat/components/LeftSidebar/index.js
@@ -0,0 +1,313 @@
+// src/views/AgentChat/components/LeftSidebar/index.js
+// 左侧栏组件 - 对话历史列表
+
+import React, { useState } from 'react';
+import { motion, AnimatePresence } from 'framer-motion';
+import {
+ Box,
+ Text,
+ Input,
+ Avatar,
+ Badge,
+ Spinner,
+ Tooltip,
+ IconButton,
+ HStack,
+ VStack,
+ Flex,
+} from '@chakra-ui/react';
+import { MessageSquare, Plus, Search, ChevronLeft } from 'lucide-react';
+import { animations } from '../../constants/animations';
+import { groupSessionsByDate } from '../../utils/sessionUtils';
+import SessionCard from './SessionCard';
+
+/**
+ * LeftSidebar - 左侧栏组件
+ *
+ * @param {Object} props
+ * @param {boolean} props.isOpen - 侧边栏是否展开
+ * @param {Function} props.onClose - 关闭侧边栏回调
+ * @param {Array} props.sessions - 会话列表
+ * @param {string|null} props.currentSessionId - 当前选中的会话 ID
+ * @param {Function} props.onSessionSwitch - 切换会话回调
+ * @param {Function} props.onNewSession - 新建会话回调
+ * @param {boolean} props.isLoadingSessions - 会话加载中状态
+ * @param {Object} props.user - 用户信息
+ * @returns {JSX.Element|null}
+ */
+const LeftSidebar = ({
+ isOpen,
+ onClose,
+ sessions,
+ currentSessionId,
+ onSessionSwitch,
+ onNewSession,
+ isLoadingSessions,
+ user,
+}) => {
+ const [searchQuery, setSearchQuery] = useState('');
+
+ // 按日期分组会话
+ const sessionGroups = groupSessionsByDate(sessions);
+
+ // 搜索过滤
+ const filteredSessions = searchQuery
+ ? sessions.filter(
+ (s) =>
+ s.title?.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ s.session_id?.toLowerCase().includes(searchQuery.toLowerCase())
+ )
+ : sessions;
+
+ return (
+
+ {isOpen && (
+
+
+ {/* 标题栏 */}
+
+
+
+
+
+ 对话历史
+
+
+
+
+
+ }
+ onClick={onNewSession}
+ bg="rgba(255, 255, 255, 0.05)"
+ color="gray.300"
+ backdropFilter="blur(10px)"
+ border="1px solid"
+ borderColor="rgba(255, 255, 255, 0.1)"
+ _hover={{
+ bg: 'rgba(59, 130, 246, 0.2)',
+ borderColor: 'blue.400',
+ color: 'blue.300',
+ boxShadow: '0 0 12px rgba(59, 130, 246, 0.3)',
+ }}
+ />
+
+
+
+
+ }
+ onClick={onClose}
+ bg="rgba(255, 255, 255, 0.05)"
+ color="gray.300"
+ backdropFilter="blur(10px)"
+ border="1px solid"
+ borderColor="rgba(255, 255, 255, 0.1)"
+ _hover={{
+ bg: 'rgba(255, 255, 255, 0.1)',
+ borderColor: 'purple.400',
+ color: 'white',
+ }}
+ />
+
+
+
+
+
+ {/* 搜索框 */}
+
+
+
+
+ setSearchQuery(e.target.value)}
+ size="sm"
+ variant="outline"
+ pl={10}
+ bg="rgba(255, 255, 255, 0.05)"
+ backdropFilter="blur(10px)"
+ border="1px solid"
+ borderColor="rgba(255, 255, 255, 0.1)"
+ color="white"
+ _placeholder={{ color: 'gray.500' }}
+ _hover={{
+ borderColor: 'rgba(255, 255, 255, 0.2)',
+ }}
+ _focus={{
+ borderColor: 'purple.400',
+ boxShadow:
+ '0 0 0 1px var(--chakra-colors-purple-400), 0 0 12px rgba(139, 92, 246, 0.3)',
+ bg: 'rgba(255, 255, 255, 0.08)',
+ }}
+ />
+
+
+
+ {/* 会话列表 */}
+
+ {/* 按日期分组显示会话 */}
+ {sessionGroups.today.length > 0 && (
+
+
+ 今天
+
+
+ {sessionGroups.today.map((session, idx) => (
+
+ onSessionSwitch(session.session_id)}
+ />
+
+ ))}
+
+
+ )}
+
+ {sessionGroups.yesterday.length > 0 && (
+
+
+ 昨天
+
+
+ {sessionGroups.yesterday.map((session) => (
+ onSessionSwitch(session.session_id)}
+ />
+ ))}
+
+
+ )}
+
+ {sessionGroups.thisWeek.length > 0 && (
+
+
+ 本周
+
+
+ {sessionGroups.thisWeek.map((session) => (
+ onSessionSwitch(session.session_id)}
+ />
+ ))}
+
+
+ )}
+
+ {sessionGroups.older.length > 0 && (
+
+
+ 更早
+
+
+ {sessionGroups.older.map((session) => (
+ onSessionSwitch(session.session_id)}
+ />
+ ))}
+
+
+ )}
+
+ {/* 加载状态 */}
+ {isLoadingSessions && (
+
+
+
+ )}
+
+ {/* 空状态 */}
+ {sessions.length === 0 && !isLoadingSessions && (
+
+
+ 还没有对话历史
+ 开始一个新对话吧!
+
+ )}
+
+
+ {/* 用户信息卡片 */}
+
+
+
+
+
+ {user?.nickname || '未登录'}
+
+
+ {user?.subscription_type || 'free'}
+
+
+
+
+
+
+ )}
+
+ );
+};
+
+export default LeftSidebar;