完成前端初步重构、实现显示选中角色功能
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
|
// frontend-react/src/App.jsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Toolbar from './components/ToolBar/ToolBar';
|
import Toolbar from './components/ToolBar/ToolBar';
|
||||||
import ChatBox from './components/ChatBox/ChatBox';
|
import ChatBox from './components/ChatBox/ChatBox';
|
||||||
import DicePanel from './components/DicePanel/DicePanel';
|
import SideBarLeft from './components/SideBarLeft/SideBarLeft';
|
||||||
import ImageDisplay from './components/ImageDisplay/ImageDisplay';
|
import SideBarRight from './components/SideBarRight/SideBarRight';
|
||||||
import PresetPanel from './components/PresetPanel/PresetPanel';
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
@@ -15,7 +15,7 @@ function App() {
|
|||||||
<div className="main-container">
|
<div className="main-container">
|
||||||
{/* 左侧栏 - 预设面板 */}
|
{/* 左侧栏 - 预设面板 */}
|
||||||
<div className="sidebar-left">
|
<div className="sidebar-left">
|
||||||
<PresetPanel />
|
<SideBarLeft />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 中间栏:聊天框 */}
|
{/* 中间栏:聊天框 */}
|
||||||
@@ -25,12 +25,7 @@ function App() {
|
|||||||
|
|
||||||
{/* 右侧栏 */}
|
{/* 右侧栏 */}
|
||||||
<div className="sidebar-right">
|
<div className="sidebar-right">
|
||||||
<div className="right-top">
|
<SideBarRight />
|
||||||
<ImageDisplay /> {/* 图片展示放在顶部 */}
|
|
||||||
</div>
|
|
||||||
<div className="right-bottom">
|
|
||||||
<DicePanel /> {/* 骰子面板放在底部 */}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import useRoleSelectorStore from '../../store/Slices/RoleSelectorSlice';
|
import useRoleSelectorStore from '../../Store/Slices/RoleSelectorSlice';
|
||||||
import useChatBoxStore from '../../Store/Slices/ChatBoxSlice';
|
import useChatBoxStore from '../../Store/Slices/ChatBoxSlice';
|
||||||
|
|
||||||
import './RoleSelector.css';
|
import './RoleSelector.css';
|
||||||
|
|||||||
42
frontend-react/src/components/SideBarLeft/SideBarLeft.css
Normal file
42
frontend-react/src/components/SideBarLeft/SideBarLeft.css
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/* frontend-react/src/components/SideBarLeft/SideBarLeft.css */
|
||||||
|
.sidebar-left {
|
||||||
|
width: 250px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tabs {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px 5px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button.active {
|
||||||
|
border-bottom: 2px solid #4a90e2;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
44
frontend-react/src/components/SideBarLeft/SideBarLeft.jsx
Normal file
44
frontend-react/src/components/SideBarLeft/SideBarLeft.jsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// frontend-react/src/components/SideBarLeft/SideBarLeft.jsx
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import './SideBarLeft.css';
|
||||||
|
|
||||||
|
const SideBarLeft = () => {
|
||||||
|
const [activeTab, setActiveTab] = useState('gallery');
|
||||||
|
|
||||||
|
const handleTabChange = (tab) => {
|
||||||
|
setActiveTab(tab);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="sidebar-left">
|
||||||
|
<div className="sidebar-tabs">
|
||||||
|
<button
|
||||||
|
className={`tab-button ${activeTab === 'gallery' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleTabChange('gallery')}
|
||||||
|
>
|
||||||
|
🖼️ 画廊
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`tab-button ${activeTab === 'config' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleTabChange('config')}
|
||||||
|
>
|
||||||
|
⚙️ 配置
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`tab-button ${activeTab === 'worldbook' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleTabChange('worldbook')}
|
||||||
|
>
|
||||||
|
🌍 世界书
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sidebar-content">
|
||||||
|
{activeTab === 'gallery' && <div className="tab-content">画廊内容</div>}
|
||||||
|
{activeTab === 'config' && <div className="tab-content">配置内容</div>}
|
||||||
|
{activeTab === 'worldbook' && <div className="tab-content">世界书内容</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SideBarLeft;
|
||||||
56
frontend-react/src/components/SideBarRight/SideBarRight.css
Normal file
56
frontend-react/src/components/SideBarRight/SideBarRight.css
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* frontend-react/src/components/SideBarRight/SideBarRight.css */
|
||||||
|
.sidebar-right {
|
||||||
|
width: 300px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-top, .right-bottom {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-top {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-bottom {
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tabs {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px 5px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button.active {
|
||||||
|
border-bottom: 2px solid #4a90e2;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
68
frontend-react/src/components/SideBarRight/SideBarRight.jsx
Normal file
68
frontend-react/src/components/SideBarRight/SideBarRight.jsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// frontend-react/src/components/SideBarRight/SideBarRight.jsx
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import './SideBarRight.css';
|
||||||
|
import DicePanel from '../DicePanel/DicePanel';
|
||||||
|
import ImageDisplay from '../ImageDisplay/ImageDisplay';
|
||||||
|
|
||||||
|
const SideBarRight = () => {
|
||||||
|
const [topActiveTab, setTopActiveTab] = useState('dice');
|
||||||
|
const [bottomActiveTab, setBottomActiveTab] = useState('macros');
|
||||||
|
|
||||||
|
const handleTopTabChange = (tab) => {
|
||||||
|
setTopActiveTab(tab);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBottomTabChange = (tab) => {
|
||||||
|
setBottomActiveTab(tab);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="sidebar-right">
|
||||||
|
<div className="right-top">
|
||||||
|
<div className="sidebar-tabs">
|
||||||
|
<button
|
||||||
|
className={`tab-button ${topActiveTab === 'dice' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleTopTabChange('dice')}
|
||||||
|
>
|
||||||
|
🎲 骰子与工具
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`tab-button ${topActiveTab === 'debug' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleTopTabChange('debug')}
|
||||||
|
>
|
||||||
|
🔍 上下文调试
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sidebar-content">
|
||||||
|
{topActiveTab === 'dice' && <DicePanel />}
|
||||||
|
{topActiveTab === 'debug' && <div className="tab-content">上下文调试内容</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="right-bottom">
|
||||||
|
<div className="sidebar-tabs">
|
||||||
|
<button
|
||||||
|
className={`tab-button ${bottomActiveTab === 'macros' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleBottomTabChange('macros')}
|
||||||
|
>
|
||||||
|
🔧 快捷宏
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`tab-button ${bottomActiveTab === 'table' ? 'active' : ''}`}
|
||||||
|
onClick={() => handleBottomTabChange('table')}
|
||||||
|
>
|
||||||
|
📊 动态表格
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sidebar-content">
|
||||||
|
{bottomActiveTab === 'macros' && <div className="tab-content">快捷宏内容</div>}
|
||||||
|
{bottomActiveTab === 'table' && <div className="tab-content">动态表格内容</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SideBarRight;
|
||||||
@@ -34,17 +34,18 @@
|
|||||||
|
|
||||||
/* 工具栏图标 */
|
/* 工具栏图标 */
|
||||||
.toolbar-icon {
|
.toolbar-icon {
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
padding: 0 12px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
gap: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
color: #555;
|
color: #555;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-icon:hover {
|
.toolbar-icon:hover {
|
||||||
@@ -59,6 +60,15 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 图标标签文本 */
|
||||||
|
.icon-label {
|
||||||
|
font-size: 14px;
|
||||||
|
max-width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* ==================== 弹出面板通用样式 ==================== */
|
/* ==================== 弹出面板通用样式 ==================== */
|
||||||
|
|
||||||
.close-panel-button {
|
.close-panel-button {
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
// frontend-react/src/components/ToolBar/ToolBar.jsx
|
||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
import RoleSelector from '../RoleSelector/RoleSelector';
|
import RoleSelector from '../RoleSelector/RoleSelector';
|
||||||
|
import useRoleSelectorStore from '../../Store/Slices/RoleSelectorSlice';
|
||||||
import './ToolBar.css';
|
import './ToolBar.css';
|
||||||
|
|
||||||
const Toolbar = () => {
|
const Toolbar = () => {
|
||||||
const [activePanel, setActivePanel] = useState(null);
|
const [activePanel, setActivePanel] = useState(null);
|
||||||
const panelRef = useRef(null);
|
const panelRef = useRef(null);
|
||||||
|
const selectedRole = useRoleSelectorStore((state) => state.selectedRole);
|
||||||
|
const selectedChat = useRoleSelectorStore((state) => state.selectedChat);
|
||||||
|
|
||||||
// 点击外部关闭面板
|
// 点击外部关闭面板
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@@ -20,6 +24,13 @@ const Toolbar = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// 监听selectedRole和selectedChat的变化
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('当前选中的角色:', selectedRole);
|
||||||
|
console.log('当前选中的聊天:', selectedChat);
|
||||||
|
// 这里可以添加其他需要响应角色变化的逻辑
|
||||||
|
}, [selectedRole, selectedChat]);
|
||||||
|
|
||||||
// 处理面板切换
|
// 处理面板切换
|
||||||
const handlePanelToggle = (panelName) => {
|
const handlePanelToggle = (panelName) => {
|
||||||
if (activePanel === panelName) {
|
if (activePanel === panelName) {
|
||||||
@@ -34,38 +45,73 @@ const Toolbar = () => {
|
|||||||
setActivePanel(null);
|
setActivePanel(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 截断文本
|
||||||
|
const truncateText = (text, maxLength = 20) => {
|
||||||
|
if (!text) return '未选择';
|
||||||
|
return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构建显示文本
|
||||||
|
const getDisplayText = () => {
|
||||||
|
if (!selectedRole) return '未选择';
|
||||||
|
return selectedChat ? `${selectedRole} / ${selectedChat}` : selectedRole;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="toolbar">
|
<div className="toolbar">
|
||||||
{/* 左侧工具栏图标 */}
|
{/* 左侧:当前角色 */}
|
||||||
<div className="toolbar-section">
|
<div className="toolbar-section">
|
||||||
<div className="toolbar-icons">
|
<div className="toolbar-icons">
|
||||||
{/* Logo图标 */}
|
|
||||||
<div
|
<div
|
||||||
className="toolbar-icon"
|
className="toolbar-icon"
|
||||||
title="首页"
|
title="当前角色"
|
||||||
onClick={() => handlePanelToggle(null)}
|
onClick={() => handlePanelToggle('currentRole')}
|
||||||
>
|
>
|
||||||
🤖
|
👤
|
||||||
|
<span className="icon-label">当前角色</span>
|
||||||
|
</div>
|
||||||
|
<div className="toolbar-display-box">
|
||||||
|
{truncateText(getDisplayText())}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 中间操作图标 */}
|
{/* 中间:角色管理 */}
|
||||||
<div className="toolbar-section">
|
<div className="toolbar-section">
|
||||||
<div className="toolbar-icons">
|
<div className="toolbar-icons">
|
||||||
{/* 角色选择图标 */}
|
|
||||||
<div
|
<div
|
||||||
className={`toolbar-icon ${activePanel === 'role' ? 'active' : ''}`}
|
className={`toolbar-icon ${activePanel === 'role' ? 'active' : ''}`}
|
||||||
title="角色管理"
|
title="角色管理"
|
||||||
onClick={() => handlePanelToggle('role')}
|
onClick={() => handlePanelToggle('role')}
|
||||||
>
|
>
|
||||||
👤
|
🎭
|
||||||
|
<span className="icon-label">全局世界书</span>
|
||||||
|
</div>
|
||||||
|
<div className="toolbar-display-box">
|
||||||
|
{truncateText(getDisplayText())}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 右侧工具栏图标 */}
|
{/* 全局世界书 */}
|
||||||
|
<div className="toolbar-section">
|
||||||
|
<div className="toolbar-icons">
|
||||||
|
<div
|
||||||
|
className="toolbar-icon"
|
||||||
|
title="全局世界书"
|
||||||
|
onClick={() => handlePanelToggle('worldBook')}
|
||||||
|
>
|
||||||
|
📚
|
||||||
|
<span className="icon-label">全局世界书</span>
|
||||||
|
</div>
|
||||||
|
<div className="toolbar-display-box">
|
||||||
|
全局世界书
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 右侧:设置和拓展 */}
|
||||||
<div className="toolbar-section">
|
<div className="toolbar-section">
|
||||||
<div className="toolbar-icons" style={{ justifyContent: 'flex-end' }}>
|
<div className="toolbar-icons" style={{ justifyContent: 'flex-end' }}>
|
||||||
<div
|
<div
|
||||||
@@ -77,10 +123,10 @@ const Toolbar = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="toolbar-icon"
|
className="toolbar-icon"
|
||||||
title="帮助"
|
title="拓展"
|
||||||
onClick={() => handlePanelToggle('help')}
|
onClick={() => handlePanelToggle('extensions')}
|
||||||
>
|
>
|
||||||
❓
|
➕
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -91,7 +137,7 @@ const Toolbar = () => {
|
|||||||
<div className="panel-overlay" ref={panelRef}>
|
<div className="panel-overlay" ref={panelRef}>
|
||||||
<div className="panel-content">
|
<div className="panel-content">
|
||||||
<div className="panel-header">
|
<div className="panel-header">
|
||||||
<h3>角色管理</h3>
|
<h3>用户角色管理</h3>
|
||||||
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
@@ -103,33 +149,69 @@ const Toolbar = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activePanel === 'settings' && (
|
{/* 当前角色面板(暂时留空) */}
|
||||||
|
{activePanel === 'currentRole' && (
|
||||||
<div className="panel-overlay" ref={panelRef}>
|
<div className="panel-overlay" ref={panelRef}>
|
||||||
<div className="panel-content">
|
<div className="panel-content">
|
||||||
<div className="panel-header">
|
<div className="panel-header">
|
||||||
<h3>设置</h3>
|
<h3>当前ai角色</h3>
|
||||||
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-body">
|
<div className="panel-body">
|
||||||
<p>设置内容...</p>
|
<p>当前角色详情...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activePanel === 'help' && (
|
{/* 全局世界书面板 */}
|
||||||
|
{activePanel === 'worldBook' && (
|
||||||
<div className="panel-overlay" ref={panelRef}>
|
<div className="panel-overlay" ref={panelRef}>
|
||||||
<div className="panel-content">
|
<div className="panel-content">
|
||||||
<div className="panel-header">
|
<div className="panel-header">
|
||||||
<h3>帮助</h3>
|
<h3>全局世界书</h3>
|
||||||
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-body">
|
<div className="panel-body">
|
||||||
<p>帮助内容...</p>
|
<p>全局世界书内容...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 设置面板 */}
|
||||||
|
{activePanel === 'settings' && (
|
||||||
|
<div className="panel-overlay" ref={panelRef}>
|
||||||
|
<div className="panel-content">
|
||||||
|
<div className="panel-header">
|
||||||
|
<h3>系统设置</h3>
|
||||||
|
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="panel-body">
|
||||||
|
<p>系统设置内容...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 拓展面板 */}
|
||||||
|
{activePanel === 'extensions' && (
|
||||||
|
<div className="panel-overlay" ref={panelRef}>
|
||||||
|
<div className="panel-content">
|
||||||
|
<div className="panel-header">
|
||||||
|
<h3>功能拓展</h3>
|
||||||
|
<button className="close-panel-button" onClick={handleClosePanel} title="关闭">
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="panel-body">
|
||||||
|
<p>功能拓展内容...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
/* frontend-react/src/index.css */
|
||||||
html, body {
|
html, body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 100vh; /* 使用视口高度作为基准 */
|
height: 100vh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
height: 100%; /* 继承body的100vh */
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@@ -28,58 +29,48 @@ html, body {
|
|||||||
html, body, .app {
|
html, body, .app {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden; /* 防止出现滚动条 */
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 主内容区域 */
|
/* 主内容区域 */
|
||||||
.main-container {
|
.main-container {
|
||||||
flex: 1; /* 这会让主容器占据剩余的所有空间 */
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: hidden; /* 防止内容溢出 */
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 左侧栏 */
|
/* 左侧栏 */
|
||||||
.sidebar-left {
|
.sidebar-left {
|
||||||
width: 250px; /* 或者你想要的宽度 */
|
width: 250px;
|
||||||
height: 继承父元素高度; /* 确保高度填满 */
|
height: 100%;
|
||||||
overflow-y: auto; /* 内容过多时显示滚动条 */
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 中间聊天区域 */
|
/* 中间聊天区域 */
|
||||||
.chat-area {
|
.chat-area {
|
||||||
flex: 1; /* 占据剩余空间 */
|
flex: 1;
|
||||||
height: 100%; /* 确保高度填满 */
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden; /* 防止内容溢出 */
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 右侧栏 */
|
/* 右侧栏 */
|
||||||
.sidebar-right {
|
.sidebar-right {
|
||||||
width: 300px; /* 或者你想要的宽度 */
|
width: 300px;
|
||||||
height: 100%; /* 确保高度填满 */
|
height: 100%;
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 右侧栏顶部 */
|
|
||||||
.right-top {
|
|
||||||
flex: 1; /* 占据剩余空间 */
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 右侧栏底部 */
|
|
||||||
.right-bottom {
|
|
||||||
height: 200px; /* 或者你想要的高度 */
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
.toolbar {
|
||||||
height: 60px; /* 或其他合适的固定高度 */
|
height: 60px;
|
||||||
flex-shrink: 0; /* 防止被压缩 */
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user