258 lines
7.8 KiB
Python
258 lines
7.8 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
|
|
|
|
|
|
# 导航按钮字典
|
|
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 == AuthState.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=AuthState.switch_activated_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_window() -> 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(
|
|
rx.cond(
|
|
AuthState.captcha_sending_countdown > 0,
|
|
f"{AuthState.captcha_sending_countdown} s111111",
|
|
"获取验证码",
|
|
),
|
|
variant="outline",
|
|
width="120px",
|
|
on_click=AuthState.send_captcha,
|
|
disabled=AuthState.captcha_sending_countdown > 0,
|
|
),
|
|
gap="8px",
|
|
width="100%",
|
|
),
|
|
rx.text(AuthState.notification, color="red", font_size="12px"),
|
|
rx.hstack(
|
|
rx.checkbox(
|
|
checked=AuthState.is_policies_agreed,
|
|
on_change=AuthState.toggle_policies_agreed,
|
|
),
|
|
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,
|
|
loading=AuthState.is_logging_in,
|
|
disabled=AuthState.is_logging_in,
|
|
),
|
|
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(
|
|
AuthState.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_window(),
|
|
rx.fragment(),
|
|
),
|
|
)
|