Python/智能体/application/components/frame.py

236 lines
7.4 KiB
Python

# -*- coding: utf-8 -*-
"""
渲染框架相关组件
"""
import reflex as rx
from application.state.conversation import ConversationState
from application.state.create_conversation_modal import CreateConversationModalState
from application.state.frame import FrameState
from application.models import SidebarIconNavButtonKind
def render_conversation(chat_id: str, chat_description: str) -> rx.Component:
"""
渲染对话
:param chat_id: 聊天唯一标识
:param description: 聊天描述
:return: Component
"""
return rx.drawer.close(
rx.hstack(
rx.button(
chat_description,
on_click=lambda: ChatState.switch_chat(chat_id), # 点击按钮将切换会话
width="80%",
variant="surface",
), # 点击按钮将切换聊天
rx.button(
rx.icon(
tag="trash",
on_click=lambda: ChatState.delete_chat(chat_id), # 点击按钮删除聊天
stroke_width=1,
),
width="20%",
variant="surface",
color_scheme="red",
),
width="100%",
),
key=chat_id, # 使用聊天唯一标识作为键
)
def render_chat_list(trigger) -> rx.Component:
"""
渲染聊天列表
"""
return rx.drawer.root(
rx.drawer.trigger(trigger),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.vstack(
rx.heading("聊天列表", color=rx.color("mauve", 11)),
rx.divider(),
rx.foreach(
ChatState.get_chats, # 获取聊天列表
lambda chat_id, chat: render_chat_item(
chat_id=chat_id,
chat_description=chat.description,
), # 创建聊天组件
),
align_items="stretch",
width="100%",
),
top="auto",
right="auto",
height="100%",
width="20em",
padding="2em",
background_color=rx.color("mauve", 2),
outline="none",
)
),
direction="left",
)
def render_create_chat_modal(trigger) -> rx.Component:
"""
渲染新建聊天模态窗
"""
return rx.dialog.root(
rx.dialog.trigger(trigger),
rx.dialog.content(
rx.form(
rx.hstack(
rx.input(
name="chat_description",
placeholder="请输入聊天描述(可选)",
flex="auto",
min_width="20ch",
),
rx.button("新建"),
spacing="2",
wrap="wrap",
width="100%",
),
on_submit=ChatState.create_chat,
),
background_color=rx.color("mauve", 1),
), # 模态窗内容容器
open=CreateChatState.is_open,
on_open_change=CreateChatState.toggle,
)
def render_sidebar() -> rx.Component:
"""
渲染侧边栏
"""
return rx.box(
rx.vstack(
rx.vstack(
# 智能体图标和名称
rx.vstack(
rx.icon("info"),
rx.text("智能体"),
spacing="2",
margin_bottom="16px",
),
# 分隔线
rx.divider(margin_bottom="12px"),
# 对话
rx.button(
rx.vstack(
rx.icon("message-square", size=18),
rx.text("对话"),
spacing="2",
),
width="100%",
justify_content="flex-start",
variant=rx.cond(
ChatState.active_sidebar_tab == "chat", "soft", "surface"
),
color_scheme="blue",
on_click=ChatState.set_active_tab("chat"),
),
spacing="10px",
),
# 底部语言、设置按钮
rx.vstack(
rx.button(rx.text("EN"), variant="surface", width="100%"),
rx.button(rx.icon("settings"), variant="surface", width="100%"),
spacing="6px",
),
height="100vh",
width="64px",
padding_y="20px",
padding_x="12px",
align_items="stretch",
justify_content="space-between",
),
width="64px",
min_width="64px",
background=rx.color("mauve", 2),
border_right=f"1px solid {rx.color('mauve', 3)}",
position="sticky",
top=0,
)
def render_sidebar_icon_nav_button(sidebar_icon_nav_button: SidebarIconNavButton) -> rx.Component:
"""
渲染侧边栏图标导航按钮
:param sidebar_icon_nav_button: 侧边栏图标导航按钮
"""
# 获取侧边栏图标导航按钮名称
sidebar_icon_nav_button_name = sidebar_icon_nav_buttons[sidebar_icon_nav_button]["name"]
# 获取侧边栏图标导航按钮图标名称
sidebar_icon_nav_button_icon = sidebar_icon_nav_buttons[sidebar_icon_nav_button]["icon"]
# 若当前侧边栏图标导航按钮非指定图标导航按钮则正常渲染,否则高亮渲染
return rx.cond(
FrameState.sidebar_icon_nav_button != sidebar_icon_nav_button,
rx.button(
rx.vstack(
rx.icon(sidebar_icon_nav_button, size=18),
rx.text(sidebar_icon_nav_button),
spacing="2",
align_items="center",
),
width="100%",
justify_content="center",
variant="surface",
color_scheme="blue",
on_click=FrameState.set_active_sidebar_tab(sidebar_icon_nav_button_name),
padding_y="10px",
),
rx.button(
rx.vstack(
rx.icon(sidebar_icon_nav_button_name, size=18),
rx.text(sidebar_icon_nav_button_name),
spacing="2",
align_items="center",
),
width="100%",
justify_content="center",
variant="soft",
color_scheme="blue",
on_click=FrameState.set_active_sidebar_tab(sidebar_icon_nav_button_name),
padding_y="10px",
),
)
def render_frame() -> rx.Component:
"""
渲染框架,参考 MateChat
"""
return rx.hstack(
rx.badge(
ConversationState.get_current_chat_description,
size="3",
variant="soft",
margin_inline_end="auto",
),
render_create_chat_modal(
rx.box(rx.tooltip(rx.icon("message-square-plus"), content="新建聊天"))
),
render_chat_list(
rx.box(
rx.tooltip(
rx.icon("messages-square"),
content="聊天历史",
)
)
),
justify_content="space-between",
align_items="center",
padding="12px",
border_bottom=f"1px solid {rx.color('mauve', 3)}",
background_color=rx.color("mauve", 2),
)