# -*- 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), )