refactor: TUI 布局重构 — 经典三行:状态栏 + 主显示区 + 固定底部输入

布局改为 grid-rows: auto 1fr 3:
- Row 1 (auto): 系统监控 + 插件状态 紧凑状态栏
- Row 2 (1fr): 合并日志/消息为单一可滚动主显示区
- Row 3 (3 lines): 固定高度输入栏,始终可见

同时:
- 移除 Header/Footer 节省空间
- show_message 路由到 log_display
- 清理未使用的 message_display 分离逻辑
- 移除未使用的 reactive/Horizontal imports

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
qinglong
2026-06-13 11:34:45 +08:00
parent 7518f4fd17
commit 6382c8019d
+41 -109
View File
@@ -6,9 +6,8 @@ import sys
import io
import time
from textual.app import App
from textual.containers import Container, ScrollableContainer, Horizontal
from textual.widgets import Static, Input, Header, Footer, LoadingIndicator
from textual.reactive import reactive
from textual.containers import Container, ScrollableContainer
from textual.widgets import Static, Input
from textual.suggester import Suggester
try:
@@ -552,105 +551,46 @@ class TUIFramework(App):
def _generate_css(self):
"""根据配置动态生成CSS - 增强版"""
try:
tui_config = self.config.get('tui', {})
layout_config = tui_config.get('layout', {})
styles_config = tui_config.get('styles', {})
# 获取布局配置,使用默认值
grid_rows = layout_config.get('grid_rows', '7fr 2fr 1fr')
# 获取样式配置,使用默认值
log_area_style = styles_config.get('log_area', 'border: solid green; overflow-y: auto;')
message_area_style = styles_config.get('message_area', 'border: solid yellow; overflow-y: auto;')
input_area_style = styles_config.get('input_area', 'border: solid red;')
css = f"""
Screen {{
layout: grid;
grid-size: 1 3;
grid-rows: {grid_rows};
}}
#log-area {{
{log_area_style}
overflow-y: auto;
scrollbar-size: 1 1;
}}
#message-area {{
{message_area_style}
overflow-y: auto;
scrollbar-size: 1 1;
}}
#input-area {{
{input_area_style}
}}
/* 自定义滚动条样式 */
ScrollableContainer {{
scrollbar-color: #666 #222;
scrollbar-color-hover: #888 #333;
overflow-y: auto;
}}
/* 确保内容正确换行 */
Static {{
width: 100%;
content-align: left middle;
overflow-y: auto;
}}
"""
logger.debug(f"生成的TUI CSS:\n{css}")
return css
except Exception as e:
logger.error(f"生成TUI CSS时出错: {str(e)}", exc_info=True)
# 返回默认CSS作为回退
return """
"""动态生成 CSS — 经典三行布局:状态栏 + 主内容 + 固定底部输入"""
return """
Screen {
layout: grid;
grid-size: 1 3;
grid-rows: 7fr 2fr 1fr;
grid-rows: auto 1fr 3;
}
#log-area {
border: solid green;
#monitor-area {
height: 2;
padding: 0 1;
background: $panel;
color: $text;
}
#main-area {
overflow-y: auto;
scrollbar-size: 1 1;
border: solid $primary;
}
#message-area {
border: solid yellow;
overflow-y: auto;
scrollbar-size: 1 1;
}
#input-area {
border: solid red;
height: 3;
border: solid $secondary;
padding: 0 1;
}
/* 自定义滚动条样式 */
ScrollableContainer {
scrollbar-color: #666 #222;
scrollbar-color-hover: #888 #333;
overflow-y: auto;
}
/* 确保内容正确换行 */
Static {
width: 100%;
content-align: left middle;
overflow-y: auto;
content-align: left top;
}
"""
def compose(self):
"""组合界面"""
yield Header()
"""组合界面 — 状态栏 / 主显示区(日志+消息) / 底部输入栏"""
yield Container(
self.system_monitor,
self.plugin_panel,
@@ -658,23 +598,18 @@ class TUIFramework(App):
)
yield ScrollableContainer(
self.log_display,
id="log-area"
)
yield ScrollableContainer(
self.message_display,
id="message-area"
id="main-area",
)
self.command_suggester = CommandSuggester(self.command_service)
self.command_input = Input(
placeholder="输入指令... Tab 补全",
placeholder="🐱 输入指令... Tab 补全",
suggester=self.command_suggester,
id="command-input",
)
yield Container(
self.command_input,
id="input-area"
id="input-area",
)
yield Footer()
async def on_mount(self):
"""挂载完成事件"""
@@ -720,16 +655,21 @@ class TUIFramework(App):
self.show_message(f"指令处理错误: {str(e)}", "error")
def show_message(self, message: str, msg_type: str = "info", persistent: bool = False):
"""显示消息"""
"""显示消息到主显示区(log_display"""
try:
self.message_display.add_message(message, msg_type, persistent)
prefix = {"info": "", "success": "", "error": "", "warning": "⚠️",
"command": "▶️", "debug": "🔍"}.get(msg_type, "📝")
for line in message.strip().split("\n"):
if line.strip():
self.log_display.add_log_line(f"{prefix} {line.strip()}")
except Exception as e:
print(f"❌ 显示TUI消息时出错: {str(e)}")
def clear_messages(self, clear_persistent: bool = False):
"""清空消息区域"""
"""清空主显示区"""
try:
self.message_display.clear_messages(clear_persistent)
self.log_display.log_lines.clear()
self.log_display.update("")
except Exception as e:
print(f"❌ 清空消息时出错: {str(e)}")
@@ -853,14 +793,10 @@ class TuiService:
result = []
if target in ["all", "log"]:
if target in ["all", "log", "message"]:
log_state = self.tui_app.log_display.toggle_auto_scroll(enabled)
result.append(f"📜 日志自动滚动: {'✅ 启用' if log_state else '❌ 禁用'}")
if target in ["all", "message"]:
msg_state = self.tui_app.message_display.toggle_auto_scroll(enabled)
result.append(f"💬 消息自动滚动: {'✅ 启用' if msg_state else '❌ 禁用'}")
result.append(f"📜 自动滚动: {'✅ 启用' if log_state else '❌ 禁用'}")
return "\n".join(result)
except Exception as e:
@@ -874,14 +810,10 @@ class TuiService:
result = []
if target in ["all", "log"]:
if target in ["all", "log", "message"]:
self.tui_app.log_display.scroll_to_bottom()
result.append("📜 日志区域已滚动到底部")
if target in ["all", "message"]:
self.tui_app.message_display.scroll_to_bottom()
result.append("💬 消息区域已滚动到底部")
result.append("📜 已滚动到底部")
return "\n".join(result)
except Exception as e: