feat: enhance LocalAgent configuration and UI components
- Updated .env.example to provide clearer configuration instructions and API key setup. - Removed debug_env.py as it was no longer needed. - Refactored main.py to streamline application initialization and workspace setup. - Introduced a new HistoryManager for managing task execution history. - Enhanced UI components in chat_view.py and task_guide_view.py to improve user interaction and code preview functionality. - Added loading indicators and improved task history display in the UI. - Implemented unit tests for history management and intent classification.
This commit is contained in:
106
ui/chat_view.py
106
ui/chat_view.py
@@ -1,6 +1,6 @@
|
||||
"""
|
||||
聊天视图组件
|
||||
处理普通对话的 UI 展示 - 支持流式消息
|
||||
处理普通对话的 UI 展示 - 支持流式消息和加载动画
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
@@ -8,6 +8,58 @@ from tkinter import scrolledtext
|
||||
from typing import Callable, Optional
|
||||
|
||||
|
||||
class LoadingIndicator:
|
||||
"""加载动画指示器"""
|
||||
|
||||
FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
|
||||
|
||||
def __init__(self, parent: tk.Widget, text: str = "处理中"):
|
||||
self.parent = parent
|
||||
self.text = text
|
||||
self.frame_index = 0
|
||||
self.running = False
|
||||
self.after_id = None
|
||||
|
||||
# 创建标签
|
||||
self.label = tk.Label(
|
||||
parent,
|
||||
text="",
|
||||
font=('Microsoft YaHei UI', 10),
|
||||
fg='#ffd54f',
|
||||
bg='#1e1e1e'
|
||||
)
|
||||
|
||||
def start(self, text: str = None):
|
||||
"""开始动画"""
|
||||
if text:
|
||||
self.text = text
|
||||
self.running = True
|
||||
self.label.pack(pady=5)
|
||||
self._animate()
|
||||
|
||||
def stop(self):
|
||||
"""停止动画"""
|
||||
self.running = False
|
||||
if self.after_id:
|
||||
self.parent.after_cancel(self.after_id)
|
||||
self.after_id = None
|
||||
self.label.pack_forget()
|
||||
|
||||
def update_text(self, text: str):
|
||||
"""更新提示文字"""
|
||||
self.text = text
|
||||
|
||||
def _animate(self):
|
||||
"""动画帧更新"""
|
||||
if not self.running:
|
||||
return
|
||||
|
||||
frame = self.FRAMES[self.frame_index]
|
||||
self.label.config(text=f"{frame} {self.text}...")
|
||||
self.frame_index = (self.frame_index + 1) % len(self.FRAMES)
|
||||
self.after_id = self.parent.after(100, self._animate)
|
||||
|
||||
|
||||
class ChatView:
|
||||
"""
|
||||
聊天视图
|
||||
@@ -22,7 +74,8 @@ class ChatView:
|
||||
def __init__(
|
||||
self,
|
||||
parent: tk.Widget,
|
||||
on_send: Callable[[str], None]
|
||||
on_send: Callable[[str], None],
|
||||
on_show_history: Optional[Callable[[], None]] = None
|
||||
):
|
||||
"""
|
||||
初始化聊天视图
|
||||
@@ -30,14 +83,19 @@ class ChatView:
|
||||
Args:
|
||||
parent: 父容器
|
||||
on_send: 发送消息回调函数
|
||||
on_show_history: 显示历史记录回调函数
|
||||
"""
|
||||
self.parent = parent
|
||||
self.on_send = on_send
|
||||
self.on_show_history = on_show_history
|
||||
|
||||
# 流式消息状态
|
||||
self._stream_active = False
|
||||
self._stream_tag = None
|
||||
|
||||
# 加载指示器
|
||||
self.loading: Optional[LoadingIndicator] = None
|
||||
|
||||
self._create_widgets()
|
||||
|
||||
def _create_widgets(self):
|
||||
@@ -46,15 +104,37 @@ class ChatView:
|
||||
self.frame = tk.Frame(self.parent, bg='#1e1e1e')
|
||||
self.frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
|
||||
# 标题栏(包含标题和历史按钮)
|
||||
title_frame = tk.Frame(self.frame, bg='#1e1e1e')
|
||||
title_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# 标题
|
||||
title_label = tk.Label(
|
||||
self.frame,
|
||||
title_frame,
|
||||
text="LocalAgent - 本地 AI 助手",
|
||||
font=('Microsoft YaHei UI', 16, 'bold'),
|
||||
fg='#61dafb',
|
||||
bg='#1e1e1e'
|
||||
)
|
||||
title_label.pack(pady=(0, 10))
|
||||
title_label.pack(side=tk.LEFT, expand=True)
|
||||
|
||||
# 历史记录按钮
|
||||
if self.on_show_history:
|
||||
self.history_btn = tk.Button(
|
||||
title_frame,
|
||||
text="📜 历史",
|
||||
font=('Microsoft YaHei UI', 10),
|
||||
bg='#424242',
|
||||
fg='#ce93d8',
|
||||
activebackground='#616161',
|
||||
activeforeground='#ce93d8',
|
||||
relief=tk.FLAT,
|
||||
padx=10,
|
||||
pady=3,
|
||||
cursor='hand2',
|
||||
command=self.on_show_history
|
||||
)
|
||||
self.history_btn.pack(side=tk.RIGHT)
|
||||
|
||||
# 消息显示区域
|
||||
self.message_area = scrolledtext.ScrolledText(
|
||||
@@ -118,6 +198,9 @@ class ChatView:
|
||||
"- 输入文件处理需求(如\"复制文件\"、\"整理图片\")将触发执行模式"
|
||||
)
|
||||
self.add_message(welcome_msg, 'system')
|
||||
|
||||
# 创建加载指示器(放在消息区域下方)
|
||||
self.loading = LoadingIndicator(self.frame)
|
||||
|
||||
def _on_enter_pressed(self, event):
|
||||
"""回车键处理"""
|
||||
@@ -214,6 +297,21 @@ class ChatView:
|
||||
self.input_entry.config(state=state)
|
||||
self.send_button.config(state=state)
|
||||
|
||||
def show_loading(self, text: str = "处理中"):
|
||||
"""显示加载动画"""
|
||||
if self.loading:
|
||||
self.loading.start(text)
|
||||
|
||||
def hide_loading(self):
|
||||
"""隐藏加载动画"""
|
||||
if self.loading:
|
||||
self.loading.stop()
|
||||
|
||||
def update_loading_text(self, text: str):
|
||||
"""更新加载提示文字"""
|
||||
if self.loading:
|
||||
self.loading.update_text(text)
|
||||
|
||||
def get_frame(self) -> tk.Frame:
|
||||
"""获取主框架"""
|
||||
return self.frame
|
||||
|
||||
Reference in New Issue
Block a user