完成大量美化
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// frontend-react/src/components/ChatBox/ChatBox.jsx
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import useChatBoxStore from '../../../Store/Mid/ChatBoxSlice';
|
||||
import MarkdownRenderer from '../../shared/MarkdownRenderer';
|
||||
import './ChatBox.css';
|
||||
|
||||
const ChatBox = () => {
|
||||
@@ -10,6 +11,11 @@ const ChatBox = () => {
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [showOptions, setShowOptions] = useState(false);
|
||||
const optionsRef = useRef(null);
|
||||
|
||||
// 聊天选择器相关状态
|
||||
const [showChatSelector, setShowChatSelector] = useState(false);
|
||||
const [characterChats, setCharacterChats] = useState([]);
|
||||
const chatSelectorRef = useRef(null);
|
||||
|
||||
// 新增:管理每条消息的当前显示的swipe版本
|
||||
const [currentSwipeId, setCurrentSwipeId] = useState({});
|
||||
@@ -48,6 +54,24 @@ const ChatBox = () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [showOptions]);
|
||||
|
||||
// 点击外部关闭聊天选择器
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (chatSelectorRef.current && !chatSelectorRef.current.contains(event.target) &&
|
||||
!event.target.closest('.chat-selector-button')) {
|
||||
setShowChatSelector(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (showChatSelector) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [showChatSelector]);
|
||||
|
||||
const handleInputHeight = (e) => {
|
||||
const textarea = e.target;
|
||||
@@ -128,6 +152,53 @@ const ChatBox = () => {
|
||||
const toggleOptionsPanel = () => {
|
||||
setShowOptions(!showOptions);
|
||||
};
|
||||
|
||||
// 打开聊天选择器
|
||||
const handleOpenChatSelector = async () => {
|
||||
const { currentRole } = useChatBoxStore.getState();
|
||||
|
||||
// 如果没有当前角色,提示用户
|
||||
if (!currentRole) {
|
||||
alert('请先在左侧选择一个角色');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取当前角色的聊天列表
|
||||
const response = await fetch(`/api/chat/${encodeURIComponent(currentRole)}`);
|
||||
if (!response.ok) throw new Error('获取聊天列表失败');
|
||||
|
||||
const chats = await response.json();
|
||||
setCharacterChats(chats);
|
||||
|
||||
// 显示聊天选择器弹窗,让用户手动选择
|
||||
setShowChatSelector(true);
|
||||
} catch (error) {
|
||||
console.error('获取聊天列表失败:', error);
|
||||
alert('获取聊天列表失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// 选择聊天并加载
|
||||
const handleSelectChat = async (chatName) => {
|
||||
try {
|
||||
const { setChatBoxRoleAndChat, fetchChatHistory, currentRole } = useChatBoxStore.getState();
|
||||
|
||||
// 设置当前角色和聊天
|
||||
setChatBoxRoleAndChat(currentRole, chatName);
|
||||
|
||||
// 加载聊天历史
|
||||
await fetchChatHistory(currentRole, chatName);
|
||||
|
||||
// 关闭选择器
|
||||
setShowChatSelector(false);
|
||||
|
||||
console.log(`已切换到聊天: ${chatName}`);
|
||||
} catch (error) {
|
||||
console.error('切换聊天失败:', error);
|
||||
alert('切换聊天失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// 渲染单条消息
|
||||
const renderMessage = (message) => {
|
||||
@@ -211,8 +282,10 @@ const ChatBox = () => {
|
||||
<div className="bubble">
|
||||
{options.htmlRender && !isUser ? (
|
||||
<div dangerouslySetInnerHTML={{ __html: currentMes }} />
|
||||
) : options.markdownRender ? (
|
||||
<MarkdownRenderer content={currentMes} />
|
||||
) : (
|
||||
currentMes
|
||||
<div className="plain-text">{currentMes}</div>
|
||||
)}
|
||||
{hasSwipes && isLatestMessage && !isUser && (
|
||||
<div className="swipe-controls">
|
||||
@@ -269,6 +342,15 @@ const ChatBox = () => {
|
||||
</button>
|
||||
{showOptions && (
|
||||
<div className="chat-options">
|
||||
<label className="option-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={options.markdownRender}
|
||||
onChange={() => toggleOption('markdownRender')}
|
||||
/>
|
||||
<span className="checkmark"></span>
|
||||
<span className="option-label">Markdown渲染</span>
|
||||
</label>
|
||||
<label className="option-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -307,6 +389,18 @@ const ChatBox = () => {
|
||||
<span className="checkmark"></span>
|
||||
<span className="option-label">🎨 生图工作流</span>
|
||||
</label>
|
||||
|
||||
{/* 分隔线 - 区分多选框和按钮区域 */}
|
||||
<div className="option-divider"></div>
|
||||
|
||||
{/* 切换聊天按钮 */}
|
||||
<button
|
||||
className="switch-chat-btn"
|
||||
onClick={handleOpenChatSelector}
|
||||
title="切换到当前角色的最后聊天记录"
|
||||
>
|
||||
💬 切换聊天
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -336,6 +430,56 @@ const ChatBox = () => {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 聊天选择器弹窗 */}
|
||||
{showChatSelector && (
|
||||
<div className="chat-selector-overlay" onClick={() => setShowChatSelector(false)}>
|
||||
<div
|
||||
className="chat-selector-modal"
|
||||
ref={chatSelectorRef}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="chat-selector-header">
|
||||
<h3>{characterName || '未选择角色'} - 选择聊天</h3>
|
||||
<button
|
||||
className="close-btn"
|
||||
onClick={() => setShowChatSelector(false)}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="chat-selector-body">
|
||||
{characterChats.length > 0 ? (
|
||||
<div className="chat-list">
|
||||
{characterChats.map((chat, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="chat-option"
|
||||
>
|
||||
<div
|
||||
className="chat-option-content"
|
||||
onClick={() => handleSelectChat(chat.chat_name)}
|
||||
>
|
||||
<div className="chat-option-name">{chat.chat_name}</div>
|
||||
{chat.last_message && (
|
||||
<div className="chat-option-preview">
|
||||
{chat.last_message.substring(0, 100)}{chat.last_message.length > 100 ? '...' : ''}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="empty-chats">
|
||||
<p>暂无聊天记录</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user