Python/agent/application/pages/index.py

254 lines
7.5 KiB
Python

# -*- coding: utf-8 -*-
"""
首页
"""
import reflex as rx
from application.pages import render_conversation, render_library
from application.pages.conversation import render_conversation
from application.states import AuthState, SidebarState
# 导航按钮字典
nav_buttons: dict = {
"conversation": {"src": "/conversation.svg", "text": "会话"},
"library": {"src": "/library.svg", "text": "知识库"},
}
"""
约定:
1 若组件仅用于当前页面则无需抽象为通用组件(application.components.*)
"""
def render_nav_button(
nav_button: str,
) -> rx.Component:
"""
渲染导航按钮
:param nav_button: 指定的导航按钮
:return : Component
"""
# 导航按钮激活状态
is_actived = nav_button == SidebarState.activated_nav_button
return rx.vstack(
# 渲染图标
rx.image(
nav_buttons[nav_button]["src"],
width="36px",
height="36px",
object_fit="contain",
padding="6px",
background_color=rx.cond(
is_actived, "var(--prismui-background-color-1)", "transparent"
),
border_radius="var(--prismui-border-radius-1)",
box_shadow=rx.cond(is_actived, "var(--prismui-box-shadow-1)", "none"),
),
# 渲染标签
rx.text(
nav_buttons[nav_button]["text"],
line_height="20px",
color="var(--prismui-color-1)",
font_size="var(--prismui-font-size-2)",
),
align_items="center",
gap="4px",
cursor="pointer",
# 点击事件:将指定导航按钮设置为侧边栏中激活的导航按钮
on_click=SidebarState.switch_nav_button(nav_button),
)
def render_sidebar() -> rx.Component:
"""
渲染侧边栏
:return: Component
"""
return rx.vstack(
rx.vstack(
rx.vstack(
# 品牌图标
rx.image(
src="/logo.png",
width="34px",
height="34px",
object_fit="contain",
),
# 品牌名称
rx.text(
"棱镜球",
line_height="20px",
font_size="11px",
font_weight="var(--prismui-font-weight-1)",
color="var(--prismui-color-1)",
),
align_items="center",
gap="4px",
),
# 渲染分隔线
rx.divider(
width="32px",
height="1px",
margin="16px 0",
background_color="var(--prismui-background-color-4)",
),
rx.vstack(
# 渲染会话导航按钮
render_nav_button("conversation"),
# 渲染知识库导航按钮
render_nav_button("library"),
gap="8px",
),
align_items="center",
width="100%",
margin_top="12px",
),
flex_shrink="0",
justify_content="space-between",
align_items="center",
width="60px",
min_width="60px",
max_width="60px",
height="100%",
)
def render_login_modal() -> rx.Component:
"""
渲染登录模态窗
:return: Component
"""
return rx.center(
rx.hstack(
rx.vstack(
rx.text(
"登录",
font_size="20px",
font_weight="600",
margin_bottom="24px",
),
rx.input(
placeholder="请输入邮箱地址",
value=AuthState.email,
on_change=AuthState.set_email,
width="100%",
),
rx.hstack(
rx.input(
placeholder="请输入验证码",
value=AuthState.captcha,
on_change=AuthState.set_captcha,
flex=1,
),
rx.button(
"获取验证码",
variant="outline",
width="120px",
on_click=AuthState.send_email_code,
),
gap="8px",
width="100%",
),
rx.cond(
AuthState.email == "",
rx.text("请输入邮箱地址", color="red", font_size="12px"),
rx.box(height="16px"),
),
rx.hstack(
rx.checkbox(
checked=AuthState.agree_policy,
on_change=AuthState.toggle_agree,
),
rx.text("我已阅读并同意 ", font_size="13px"),
rx.link("用户协议、隐私政策", font_size="13px", href="#"),
align_items="center",
),
rx.button(
"登录",
width="100%",
bg="#0a0e29",
color="white",
margin_top="12px",
on_click=AuthState.login_by_email_code,
),
rx.text(
"登录有问题?去反馈",
font_size="12px",
color="#666",
margin_top="8px",
),
width="360px",
gap="16px",
padding="40px 32px",
align_items="start",
),
rx.divider(orientation="vertical"),
rx.vstack(
rx.image(
src="/qrcode.png",
width="160px",
height="160px",
padding="8px",
border="1px solid #eee",
border_radius="8px",
bg="white",
),
rx.text(
"添加微信申请使用",
font_size="18px",
font_weight="600",
margin_top="16px",
),
align_items="center",
width="320px",
padding="40px 32px",
style={"background": "#f8f9fc"},
),
),
position="fixed",
top="0",
left="0",
width="100vw",
height="100vh",
bg="rgba(255, 255, 255, 0.85)",
z_index="9999",
overflow="hidden",
)
def render_index() -> rx.Component:
"""
首页
"""
return rx.fragment(
rx.hstack(
# 渲染侧边栏
render_sidebar(),
# 根据侧边栏状态中激活的导航按钮渲染相应页面(本项目采用卡片布局)
rx.match(
SidebarState.activated_nav_button,
# 渲染知识库页面
("library", render_library()),
# 渲染会话页面
render_conversation(),
),
width="100%",
height="100vh",
overflow="auto",
padding="8px 8px 8px 0",
background="var(--prismui-background-1)",
# 挂载事件:
on_mount=AuthState.check,
),
rx.cond(
AuthState.user_id == "",
render_login_modal(),
rx.fragment(),
),
)