This commit is contained in:
liubiren 2026-07-22 20:12:22 +08:00
parent e39a445608
commit e65044cc78
11 changed files with 202 additions and 265 deletions

View File

@ -9,43 +9,6 @@ app = rx.App(
theme=rx.theme(), theme=rx.theme(),
stylesheets=["/styles.css"], stylesheets=["/styles.css"],
style={ style={
"--prismui-background-color-1": "#ffffff", # 背景颜色:白色
"--prismui-background-color-2": "#ebebeb",
"--prismui-background-color-3": "#f6f6f8",
"--prismui-background-color-4": "#babbc0",
"--prismui-background-color-5": "#ffffff33",
"--prismui-background-1": "linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%)", # 背景:用于主页面渐变背景
"--prismui-background-2": "linear-gradient(180deg, #fffffff2, #f8fafff2 99%)", # 背景:用于登录窗和工作区渐变背景
"--prismui-font-family": "HuaweiFont,Helvetica,Arial,PingFangSC-Regular,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Microsoft JhengHei", # 字体
"--prismui-font-size-1": "12px",
"--prismui-font-size-2": "14px", # 字体大小:常用于正文
"--prismui-font-size-3": "20px",
"--prismui-font-weight-1": "normal", # 字体粗细:常用于正文
"--prismui-font-weight-2": "500",
"--prismui-font-weight-3": "700",
"--prismui-color-1": "#252b3a", # 颜色:深灰色,常用于标题和正文颜色
"--prismui-color-2": "#575d6c", # 颜色:中灰色,常用于副标题
"--prismui-color-3": "#babbc0", # 颜色:浅灰色,常用于占位符
"--prismui-color-4": "#060a263d", # 颜色:浅灰色,常用于不可点击元素
"--prismui-color-5": "#5e7ce0", # 颜色:蓝色,常用于可点击元素
"--prismui-color-6": "#f66f6a", # 颜色:红色,常用于错误提示
"--prismui-color-7": "#f2f2f3", # 颜色:浅灰色,常用于背景
"--prismui-color-9": "#ffffff", # 颜色:白色
"--prismui-border-1": "1px solid #060a260f", # 边框样式
"--prismui-border-2": "1px solid #2222220f",
"--mc-float-block-shadow": "#d5d5d5",
"--devui-global-bg": "#f6f6f8",
"--mc-box-shadow": "#191919",
"--devui-shadow-length-connected-overlay": "0px 0px 12px 0px #000000",
"--prismui-box-shadow-1": "0 4px 64px 0 #0000001a", # 登录卡片阴影
"--prismui-box-shadow-2": "0 4px 12px #0000001a", # 导航按钮阴影
"--devui-icon-fill-weak": "#babbc0",
"--prismui-background-color-weak": "#babbc0",
"--devui-border-radius-feedback": "4px",
"--prismui-border-1": "1px solid rgba(6, 10, 38, 0.06)",
"--prismui-border-radius-1": "8px",
"--prismui-border-radius-2": "12px",
"--prismui-border-radius-3": "20px",
"box-shadow": "none", "box-shadow": "none",
"background-color": "var(--prismui-background-color-1)", # 默认背景颜色 "background-color": "var(--prismui-background-color-1)", # 默认背景颜色
"font_family": "var(--prismui-font-family)", "font_family": "var(--prismui-font-family)",

View File

@ -6,7 +6,7 @@ from application.models.tables import (
RunResults, RunResults,
Users, Users,
) )
from application.models.memories import Conversation, Dialog, ThoughtNode from application.models.domains import Conversation, Dialog, ThoughtNode
__all__ = [ __all__ = [

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
内存模型 领域模型
""" """
from datetime import datetime from datetime import datetime
from typing import Dict from typing import Dict
@ -10,7 +10,7 @@ from pydantic import BaseModel, Field
class ThoughtNode(BaseModel): class ThoughtNode(BaseModel):
""" """
思考节点内存模型 思考节点领域模型
""" """
kind: str kind: str
@ -19,7 +19,7 @@ class ThoughtNode(BaseModel):
class Dialog(BaseModel): class Dialog(BaseModel):
""" """
对话内存模型 对话领域模型
""" """
question: str = Field(..., description="问题") question: str = Field(..., description="问题")
@ -37,7 +37,7 @@ class Dialog(BaseModel):
class Conversation(BaseModel): class Conversation(BaseModel):
""" """
会话内存模型 会话领域模型
""" """
description: str = Field(default="新会话", description="会话描述") description: str = Field(default="新会话", description="会话描述")

View File

@ -1,12 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
模型
""" """
from datetime import datetime, timedelta from datetime import datetime, timedelta
from random import choices
from pydantic_ai._uuid import uuid7 from pydantic_ai._uuid import uuid7
from sqlmodel import Field, JSON, SQLModel from sqlmodel import Field, JSON, SQLModel
from random import choices
# 验证码表 # 验证码表

View File

@ -5,49 +5,51 @@
import reflex as rx import reflex as rx
from application.models import Conversation, Dialog, ThoughtNode from application.models import Conversation, Dialog, ThoughtNode
from application.states import ConversationState from application.states import ConversationState, AuthState
def render_conversation_history_item( def render_conversation_history_item(
conversation_id: str, conversation: Conversation item: rx.Var[tuple[str, Conversation]],
) -> rx.Component: ) -> rx.Component:
""" """
渲染会话历史条目 渲染会话历史条目
:param conversation_id: 会话唯一标识 :param item: 会话历史条目
:param conversation: 会话实例
:return: Component :return: Component
""" """
# 解构会话唯一标识和会话实例
conversation_id, conversation = item[0], item[1] # type: ignore
# 会话激活状态 # 会话激活状态
is_actived = conversation_id == ConversationState.conversation_id is_conversation_actived = conversation_id == ConversationState.conversation_id
return rx.box( return rx.box(
rx.vstack(
rx.hstack( rx.hstack(
# 渲染对话描述 # 对话描述
rx.text( rx.text(
conversation.description, conversation.description,
flex=1, flex=1,
height="22px", height="22px",
line_height="22px", line_height="22px",
font_size="var(--devui-font-size)",
padding_right="4px", padding_right="4px",
color="var(--prismui-color-2)",
overflow="hidden", overflow="hidden",
text_overflow="ellipsis", text_overflow="ellipsis",
white_space="nowrap", white_space="nowrap",
), ),
# 渲染更多按钮 # 更多按钮
rx.box( rx.box(
rx.popover.root( rx.popover.root(
# 触发事件:点击更多按钮 # 触发事件:点击更多按钮
rx.popover.trigger( rx.popover.trigger(
rx.box( rx.box(
rx.icon( rx.icon(
"ellipsis", size=14, color="var(--devui-text-weak)" "ellipsis", size=14, color="var(--prismui-color-2)"
), ),
cursor="pointer", cursor="pointer",
) )
), ),
# 渲染气泡卡片 # 气泡卡片
rx.popover.content( rx.popover.content(
rx.vstack( rx.vstack(
rx.box( rx.box(
@ -57,8 +59,7 @@ def render_conversation_history_item(
transform="translateX(-50%) rotate(45deg)", transform="translateX(-50%) rotate(45deg)",
width="8px", width="8px",
height="8px", height="8px",
background_color="#ffffff", background_color="var(--prismui-background-color-1)",
box_shadow="-2px -2px 4px rgba(0,0,0,0.05)",
), ),
rx.popover.close( rx.popover.close(
rx.box( rx.box(
@ -66,34 +67,33 @@ def render_conversation_history_item(
width="100%", width="100%",
height="24px", height="24px",
padding="4px", padding="4px",
border_radius="4px", border_radius="var(--prismui-border-radius-1)",
line_height="16px", line_height="16px",
font_family="HuaweiFont,Helvetica,Arial,PingFangSC-Regular,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Microsoft JhengHei", font_size="var(--prismui-font-size-1)",
font_size="12px", color="var(--prismui-color-1)",
color="#252b3a",
style={ style={
"_hover": { "_hover": {
"background_color": "#f2f2f3", "background_color": "var(--prismui-background-color-6)",
} }
}, },
# 点击事件:删除对话 # 点击事件:删除对话
on_click=lambda: ConversationState.delete_conversation( on_click=lambda: ConversationState.delete_conversation(
conversation_id conversation_id
), ),
) ),
), ),
position="relative", position="relative",
width="100%", width="100%",
), ),
side="bottom",
side_offset=8,
position="relative", position="relative",
align="center", align="center",
padding="8px", padding="8px",
border_radius="4px", border_radius="var(--prismui-border-radius-1)",
background_color="#ffffff",
box_shadow="0 2px 12px rgba(0,0,0,0.1)", box_shadow="0 2px 12px rgba(0,0,0,0.1)",
font_family="var(--prismui-font-family)",
overflow="visible", overflow="visible",
side="bottom",
side_offset=9,
), ),
open_delay=0, open_delay=0,
), ),
@ -101,31 +101,32 @@ def render_conversation_history_item(
cursor="pointer", cursor="pointer",
style={ style={
"opacity": rx.cond( "opacity": rx.cond(
is_actived, "1", "0" is_conversation_actived, "1", "0"
), # 若当前会话已激活则不透明,否则透明 ), # 若当前会话已激活则不透明,否则透明
"transition": "opacity 0.18s ease", "transition": "opacity 0.18s ease",
"pointer_events": rx.cond(is_actived, "auto", "none"), "pointer_events": rx.cond(
is_conversation_actived, "auto", "none"
),
}, },
), ),
display="flex", display="flex",
align_items="center", align_items="center",
width="100%", width="100%",
margin_bottom="8px", margin_bottom="8px",
cursor="pointer",
),
), ),
width="100%", width="100%",
padding="16px", padding="16px",
margin_bottom="8px", margin_bottom="8px",
border_radius="8px", background=rx.cond(
line_height="1.5", is_conversation_actived,
color="var(--devui-text-weak)",
cursor="pointer",
style={
"background": rx.cond(
is_actived,
"linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)", "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
"var(--devui-base-bg)", "var(--prismui-background-color-1)",
), ),
"box_shadow": rx.cond(is_actived, "2px 2px 8px #e9e9e9", "none"), border_radius="var(--prismui-border-radius-2)",
box_shadow=rx.cond(is_conversation_actived, "2px 2px 8px #e9e9e9", "none"),
style={
"&:hover": { "&:hover": {
"background": "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)", "background": "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
"box_shadow": "2px 2px 8px #e9e9e9", "box_shadow": "2px 2px 8px #e9e9e9",
@ -135,15 +136,16 @@ def render_conversation_history_item(
"pointer_events": "auto !important", "pointer_events": "auto !important",
}, # 鼠标悬停强制显示右侧三点按钮 }, # 鼠标悬停强制显示右侧三点按钮
}, },
cursor="pointer",
# 点击事件:将指定对话唯一标识设置为当前对话唯一标识 # 点击事件:将指定对话唯一标识设置为当前对话唯一标识
on_click=ConversationState.switch_conversation(conversation_id), on_click=ConversationState.switch_conversation(conversation_id),
) )
def render_conversation_history_collapse(is_collapse_expanded: bool) -> rx.Component: def render_collapse(is_expanded: bool) -> rx.Component:
""" """
渲染对话历史折叠面板 渲染折叠面板
:param is_collapse_expanded: 对话历史折叠面板展开状态 :param is_expanded: 折叠面板展开状态
:return: Component :return: Component
""" """
return rx.box( return rx.box(
@ -153,11 +155,9 @@ def render_conversation_history_collapse(is_collapse_expanded: bool) -> rx.Compo
rx.text( rx.text(
"会话历史", "会话历史",
margin_bottom="8px", margin_bottom="8px",
font_size="var(--devui-font-size-lg)", font_weight="var(--prismui-font-weight-3)",
font_weight="700",
white_space="nowrap", white_space="nowrap",
), ),
display="flex",
align_items="center", align_items="center",
justify_content="space-between", justify_content="space-between",
), ),
@ -165,7 +165,7 @@ def render_conversation_history_collapse(is_collapse_expanded: bool) -> rx.Compo
rx.auto_scroll( rx.auto_scroll(
rx.foreach( rx.foreach(
ConversationState.conversation_history, ConversationState.conversation_history,
lambda item, _: render_conversation_history_item(item[0], item[1]), render_conversation_history_item,
), ),
flex="1", flex="1",
margin_top="8px", margin_top="8px",
@ -187,9 +187,9 @@ def render_conversation_history_collapse(is_collapse_expanded: bool) -> rx.Compo
gap="12px", gap="12px",
color="var(--prismui-color-text)", color="var(--prismui-color-text)",
), ),
width=rx.cond(is_collapse_expanded, "25%", "0px"), width=rx.cond(is_expanded, "25%", "0px"),
min_width=rx.cond(is_collapse_expanded, "240px", "0px"), min_width=rx.cond(is_expanded, "240px", "0px"),
max_width=rx.cond(is_collapse_expanded, "380px", "0px"), max_width=rx.cond(is_expanded, "380px", "0px"),
height="100%", height="100%",
overflow="hidden", overflow="hidden",
transition="all 0.3s ease-in-out", transition="all 0.3s ease-in-out",
@ -244,11 +244,11 @@ def render_greeting() -> rx.Component:
gap="12px", gap="12px",
color="var(--prismui-color-text)", color="var(--prismui-color-text)",
), ),
# 猜你想问 # 演示案例
rx.vstack( rx.vstack(
rx.hstack( rx.hstack(
rx.text( rx.text(
"猜你想问", "演示案例",
line_height="24px", line_height="24px",
font_size="16px", font_size="16px",
font_weight="700", font_weight="700",
@ -261,7 +261,7 @@ def render_greeting() -> rx.Component:
), ),
rx.hstack( rx.hstack(
rx.box( rx.box(
"需求梳理", "智能客服",
padding="10px 16px", padding="10px 16px",
background_color="var(--devui-dividing-line)", background_color="var(--devui-dividing-line)",
border_radius="var(--devui-border-radius-full)", border_radius="var(--devui-border-radius-full)",
@ -357,7 +357,7 @@ def render_dialog_history_item(dialog_id: str, dialog: Dialog) -> rx.Component:
max_width="600px", max_width="600px",
padding="12px 16px", padding="12px 16px",
background_color="var(--prismui-background-color-3)", background_color="var(--prismui-background-color-3)",
border_radius="12px", border_radius="var(--prismui-border-radius-2)",
word_wrap="break-word", word_wrap="break-word",
word_break="break-all", word_break="break-all",
white_space="pre-line", white_space="pre-line",
@ -373,7 +373,7 @@ def render_dialog_history_item(dialog_id: str, dialog: Dialog) -> rx.Component:
color="var(--prismui-color-2)", color="var(--prismui-color-2)",
), ),
padding="4px", padding="4px",
border_radius="4px", border_radius="var(--prismui-border-radius-1)",
cursor="pointer", cursor="pointer",
style={ style={
"_hover": { "_hover": {
@ -657,7 +657,7 @@ def render_input() -> rx.Component:
padding="0 12px", padding="0 12px",
background_color="var(--devui-primary)", background_color="var(--devui-primary)",
border="none", border="none",
border_radius="20px", border_radius="20pxvar(--devui-border-radius-4)",
align_items="center", align_items="center",
justify_content="center", justify_content="center",
white_space="nowrap", white_space="nowrap",
@ -712,7 +712,7 @@ def render_input() -> rx.Component:
) )
def render_conversation_workplace() -> rx.Component: def render_workplace() -> rx.Component:
""" """
渲染会话工作区 渲染会话工作区
:return: Component :return: Component
@ -745,35 +745,27 @@ def render_conversation_history_collapse_button(
is_expanded: bool, is_expanded: bool,
) -> rx.Component: ) -> rx.Component:
""" """
渲染会话历史折叠面板的打开/关闭按钮 渲染会话历史折叠面板的按钮
:param is_expanded: 会话历史折叠面板展开状态 :param is_expanded: 会话历史折叠面板展开状态
:return: Component :return: Component
""" """
return rx.button( return rx.button(
rx.cond(
is_expanded,
rx.icon( rx.icon(
"chevron-left", rx.cond(is_expanded, "chevron-left", "chevron-right"),
stroke_width=1,
width="16px", width="16px",
height="16px", height="16px",
color="var(--devui-icon-fill-weak)", color="var(--prismui-color-3)",
),
rx.icon(
"chevron-right",
width="16px",
height="16px",
color="var(--devui-icon-fill-weak)",
),
), ),
position="absolute", position="absolute",
top="50%", top="calc(50% - 20px)",
left=rx.cond(is_expanded, "calc(clamp(240px, 25%, 380px) - 8px)", "0"), left=rx.cond(is_expanded, "calc(clamp(240px, 25%, 380px) - 8px)", "0"),
z_index=99, z_index=99,
width="16px", width="16px",
height="40px", height="40px",
background="var(--prismui-background-color-1)", background_color="var(--prismui-background-color-1)",
box_shadow="2px 0 4px 0 var(--mc-float-block-shadow)",
border_radius=rx.cond(is_expanded, "6px", "0 6px 6px 0"), border_radius=rx.cond(is_expanded, "6px", "0 6px 6px 0"),
box_shadow="var(--prismui-box-shadow-4)",
transition="all 0.3s ease-in-out", transition="all 0.3s ease-in-out",
cursor="pointer", cursor="pointer",
# 点击事件:切换会话历史折叠面板展开状态 # 点击事件:切换会话历史折叠面板展开状态
@ -783,18 +775,17 @@ def render_conversation_history_collapse_button(
def render_conversation() -> rx.Component: def render_conversation() -> rx.Component:
""" """
渲染会话页面布局参考 MetaChat左侧为会话历史右侧为对话历史和输入框 渲染会话页面布局参考 MetaChat左侧为折叠面板右侧为展示和操作区其中若对话历史为空则展示欢迎文案否则展示对话历史
""" """
# 会话历史折叠面板的展开状态 # 会话历史展示状态
is_expanded = ConversationState.is_conversation_history_shown is_conversation_history_shown = ConversationState.is_conversation_history_shown
return rx.box( return rx.box(
# 渲染折叠面板
rx.hstack( rx.hstack(
# 渲染折叠面板 # 渲染折叠面板
render_conversation_history_collapse(is_expanded), render_collapse(is_conversation_history_shown),
# 渲染会话工作区 # 渲染会话工作区
render_conversation_workplace(), render_workplace(),
position="relative", position="relative",
display="flex", display="flex",
flex="1", flex="1",
@ -804,12 +795,12 @@ def render_conversation() -> rx.Component:
transition="all 0.3s ease-in-out", transition="all 0.3s ease-in-out",
), ),
# 渲染对话历史折叠面板打开/关闭按钮 # 渲染对话历史折叠面板打开/关闭按钮
render_conversation_history_collapse_button(is_expanded), render_conversation_history_collapse_button(is_conversation_history_shown),
position="relative", position="relative",
width="100%", width="100%",
height="100%", height="100%",
border_radius="12px", border_radius="var(--prismui-border-radius-3)",
overflow="hidden", overflow="hidden",
# 挂载事件:初始化会话历史 # 挂载事件:同步用户唯一标识
on_mount=ConversationState.on_mount, on_mount=AuthState.sync_user_id,
) )

View File

@ -30,7 +30,7 @@ def render_nav_button(
:return : Component :return : Component
""" """
# 导航按钮激活状态 # 导航按钮激活状态
is_actived = nav_button == AuthState.activated_nav_button is_nav_button_actived = nav_button == AuthState.activated_nav_button
return rx.vstack( return rx.vstack(
# 渲染图标 # 渲染图标
@ -41,10 +41,14 @@ def render_nav_button(
object_fit="contain", object_fit="contain",
padding="6px", padding="6px",
background_color=rx.cond( background_color=rx.cond(
is_actived, "var(--prismui-background-color-1)", "transparent" is_nav_button_actived,
"var(--prismui-background-color-1)",
"transparent",
),
border_radius="var(--prismui-border-radius-2)",
box_shadow=rx.cond(
is_nav_button_actived, "var(--prismui-box-shadow-2)", "none"
), ),
border_radius="var(--prismui-border-radius-1)",
box_shadow=rx.cond(is_actived, "var(--prismui-box-shadow-2)", "none"),
), ),
# 渲染标签 # 渲染标签
rx.text( rx.text(
@ -84,35 +88,36 @@ def render_settings_button():
align_items="center", align_items="center",
width="36px", width="36px",
height="36px", height="36px",
border_radius="var(--prismui-border-radius-1)", border_radius="var(--prismui-border-radius-2)",
cursor="pointer",
style={ style={
"&:hover": { "&:hover": {
"background": "var(--prismui-background-color-5)", "background": "var(--prismui-background-color-5)",
}, # 鼠标悬停渲染背景颜色 }, # 鼠标悬停渲染背景颜色
}, },
cursor="pointer",
) )
), ),
# 渲染悬停卡片 # 渲染悬停卡片
rx.hover_card.content( rx.hover_card.content(
rx.vstack( rx.box(
rx.box( rx.box(
transform="translateX(-50%) rotate(45deg)", transform="translateX(-50%) rotate(45deg)",
position="absolute", position="absolute",
top="16px", top="calc(50% - 4px)",
left="0", left="0",
width="8px", width="8px",
height="8px", height="8px",
background_color="#ffffff", background_color="var(--prismui-background-color-1)",
box_shadow="var(--prismui-box-shadow-3)",
), ),
rx.box( rx.box(
"退出登录", "退出登录",
display="flex",
justify_content="center",
align_items="center",
width="100%", width="100%",
height="24px", height="24px",
padding="4px",
border_radius="4px",
line_height="16px", line_height="16px",
border_radius="var(--prismui-border-radius-1)",
style={ style={
"_hover": { "_hover": {
"background_color": "var(--prismui-color-7, #f2f2f3)", "background_color": "var(--prismui-color-7, #f2f2f3)",
@ -121,15 +126,15 @@ def render_settings_button():
# 点击事件:退出登录 # 点击事件:退出登录
on_click=lambda: AuthState.logout(), on_click=lambda: AuthState.logout(),
), ),
cursor="pointer",
), ),
side="left", side="left",
side_offset=8, side_offset=8,
position="relative", position="relative",
align="center", align="center",
padding="8px", padding="4px 12px",
border_radius="4px", box_shadow="var(--prismui-box-shadow-3)",
background_color="#ffffff", font_family="var(--prismui-font-family)",
box_shadow="0 2px 12px rgba(0,0,0,0.1)",
overflow="visible", overflow="visible",
style={ style={
"font-size": "var(--prismui-font-size-1) !important", "font-size": "var(--prismui-font-size-1) !important",
@ -165,9 +170,8 @@ def render_sidebar() -> rx.Component:
rx.text( rx.text(
"棱镜球", "棱镜球",
line_height="20px", line_height="20px",
font_size="var(--prismui-font-size-1)", font_size="calc(var(--prismui-font-size-1) - 1px)", # 较导航按钮标签弱化
font_weight="var(--prismui-font-weight-2)", font_weight="var(--prismui-font-weight-2)",
color="var(--prismui-color-1)",
), ),
align_items="center", align_items="center",
gap="4px", gap="4px",
@ -231,7 +235,7 @@ def render_login_window() -> rx.Component:
height="45px", height="45px",
margin_bottom="24px", margin_bottom="24px",
padding="4px", padding="4px",
border_radius="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
line_height="16px", line_height="16px",
# 值变化事件:设置邮箱 # 值变化事件:设置邮箱
on_change=AuthState.set_email, on_change=AuthState.set_email,
@ -262,7 +266,7 @@ def render_login_window() -> rx.Component:
rx.button( rx.button(
# 若验证码发送倒计时大于0则显示倒计时否则显示获取验证码 # 若验证码发送倒计时大于0则显示倒计时否则显示获取验证码
rx.cond( rx.cond(
AuthState.resend_captcha_countdown, AuthState.resend_captcha_countdown > 0,
f"{AuthState.resend_captcha_countdown} s", f"{AuthState.resend_captcha_countdown} s",
"获取验证码", "获取验证码",
), ),
@ -283,7 +287,7 @@ def render_login_window() -> rx.Component:
height="45px", height="45px",
align_items="center", align_items="center",
border="var(--prismui-border-1)", border="var(--prismui-border-1)",
border_radius="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
), ),
rx.text( rx.text(
AuthState.login_error_message, AuthState.login_error_message,
@ -359,7 +363,7 @@ def render_login_window() -> rx.Component:
"登录", "登录",
width="100%", width="100%",
height="38px", height="38px",
border_radius="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
background_color="var(--prismui-color-5)", background_color="var(--prismui-color-5)",
color="var(--prismui-color-9)", color="var(--prismui-color-9)",
cursor="pointer", cursor="pointer",
@ -367,11 +371,11 @@ def render_login_window() -> rx.Component:
loading=AuthState.is_logging_in, loading=AuthState.is_logging_in,
), ),
rx.text( rx.text(
"登录遇到问题?加微信去吐槽", "登录遇到问题?加微信去吐槽",
margin="20px 0 40px 0", margin="20px 0 40px 0",
line_height="14px", line_height="14px",
font_size="12px", font_size="12px",
color="var(--prismui-color-5)", color="var(--prismui-color-2)",
), ),
width="396px", width="396px",
height="100%", height="100%",
@ -387,10 +391,10 @@ def render_login_window() -> rx.Component:
padding="20px", padding="20px",
background_color="var(--prismui-background-color-1)", background_color="var(--prismui-background-color-1)",
border="var(--prismui-border-2)", border="var(--prismui-border-2)",
border_radius="var(--prismui-border-radius-3)", border_radius="var(--prismui-border-radius-4)",
), ),
rx.text( rx.text(
"加微信好友申请使用", "加微信好友",
margin="10px 0 12px 0", margin="10px 0 12px 0",
line_height="32px", line_height="32px",
font_size="var(--prismui-font-size-2)", font_size="var(--prismui-font-size-2)",
@ -404,7 +408,7 @@ def render_login_window() -> rx.Component:
), ),
background="var(--prismui-background-2)", background="var(--prismui-background-2)",
border="1px solid #2222220f", border="1px solid #2222220f",
border_radius="var(--prismui-border-radius-3)", border_radius="var(--prismui-border-radius-4)",
box_shadow="0 4px 64px 0 #0000001a", box_shadow="0 4px 64px 0 #0000001a",
overflow="hidden", overflow="hidden",
), ),

View File

@ -50,14 +50,6 @@ class AuthState(rx.State):
# 激活的导航按钮 # 激活的导航按钮
activated_nav_button: str = "conversation" activated_nav_button: str = "conversation"
@rx.event
async def check(self) -> None:
"""
检查
"""
self.user_id = ""
@rx.event @rx.event
def reset_error_message(self) -> None: def reset_error_message(self) -> None:
""" """
@ -195,6 +187,15 @@ class AuthState(rx.State):
""" """
self.is_policies_agreed = not self.is_policies_agreed self.is_policies_agreed = not self.is_policies_agreed
@rx.event
async def sync_user_id(self):
"""
同步用户唯一标识
"""
# 同步会话状态中用户唯一标识
conversation_state = await self.get_state(ConversationState)
await conversation_state.set_user_id(user_id=self.user_id)
@rx.event @rx.event
async def login(self) -> None: async def login(self) -> None:
""" """
@ -233,9 +234,9 @@ class AuthState(rx.State):
# 创建用户记录 # 创建用户记录
user_id = await database_state.create_users_record(email=self.email) user_id = await database_state.create_users_record(email=self.email)
# 初始化 # 设置会话状态中用户唯一标识
conversation_state = await self.get_state(ConversationState) conversation_state = await self.get_state(ConversationState)
await conversation_state.init(user_id=user_id) await conversation_state.set_user_id(user_id=user_id)
self.user_id = user_id self.user_id = user_id

View File

@ -25,7 +25,6 @@ from pydantic_ai.run import AgentRunResultEvent
import reflex as rx import reflex as rx
from application.models import Conversation, Dialog, ThoughtNode from application.models import Conversation, Dialog, ThoughtNode
from application.states.auth import AuthState
from application.states.database import DatabaseState from application.states.database import DatabaseState
@ -80,9 +79,9 @@ class ConversationState(rx.State):
# 会话创建状态True表示正在创建False表示未正在创建 # 会话创建状态True表示正在创建False表示未正在创建
is_conversation_creating: bool = False is_conversation_creating: bool = False
async def init(self, user_id: str) -> None: async def set_user_id(self, user_id: str) -> None:
""" """
初始化 设置用户唯一标识
:param user_id: 用户唯一标识 :param user_id: 用户唯一标识
:return: None :return: None
""" """
@ -107,16 +106,6 @@ class ConversationState(rx.State):
# 将最后一个会话的唯一标识设置为当前会话唯一标识 # 将最后一个会话的唯一标识设置为当前会话唯一标识
self.conversation_id = next(reversed(self.conversations.keys())) self.conversation_id = next(reversed(self.conversations.keys()))
@rx.event
async def on_mount(self):
"""
挂载时
"""
# 获取当前用户唯一标识
auth_state = await self.get_state(AuthState)
# 初始化
await self.init(user_id=auth_state.user_id)
@rx.event @rx.event
def toggle_conversation_history_shown(self) -> None: def toggle_conversation_history_shown(self) -> None:
""" """

View File

@ -23,7 +23,7 @@ from application.models import (
) )
# 思考节点内存模型类型适配器 # 思考节点领域模型类型适配器
ThoughtNodeTypeAdapter = TypeAdapter(dict[int, ThoughtNode]) ThoughtNodeTypeAdapter = TypeAdapter(dict[int, ThoughtNode])
@ -43,15 +43,9 @@ class DatabaseState(rx.State):
await session.exec( await session.exec(
update(Captchas) update(Captchas)
.where( .where(
cast(ColumnElement[bool], Captchas.email == email), Captchas.email == email, # type: ignore
cast( Captchas.is_valid == True, # type: ignore
ColumnElement[bool], Captchas.is_unused == True, # type: ignore
Captchas.is_valid == True,
),
cast(
ColumnElement[bool],
Captchas.is_unused == True,
),
) )
.values(is_valid=False) .values(is_valid=False)
) )
@ -120,10 +114,7 @@ class DatabaseState(rx.State):
select(Conversations, Dialogs) select(Conversations, Dialogs)
.outerjoin( .outerjoin(
Dialogs, Dialogs,
cast( Conversations.id == Dialogs.conversation_id, # type: ignore
ColumnElement[bool],
Conversations.id == Dialogs.conversation_id,
),
) )
.where( .where(
Conversations.user_id == user_id, Conversations.user_id == user_id,

View File

@ -4,6 +4,7 @@
--prismui-background-color-3: #f6f6f8; --prismui-background-color-3: #f6f6f8;
--prismui-background-color-4: #babbc0; --prismui-background-color-4: #babbc0;
--prismui-background-color-5: #ffffff33; --prismui-background-color-5: #ffffff33;
--prismui-background-color-6: #f2f2f3;
--prismui-background-1: linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%); --prismui-background-1: linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%);
--prismui-background-2: linear-gradient(180deg, #fffffff2, #f8fafff2 99%); --prismui-background-2: linear-gradient(180deg, #fffffff2, #f8fafff2 99%);
--prismui-font-family: HuaweiFont,Helvetica,Arial,PingFangSC-Regular,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Microsoft JhengHei; --prismui-font-family: HuaweiFont,Helvetica,Arial,PingFangSC-Regular,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Microsoft JhengHei;
@ -21,18 +22,15 @@
--prismui-color-6: #f66f6a; --prismui-color-6: #f66f6a;
--prismui-color-7: #f2f2f3; --prismui-color-7: #f2f2f3;
--prismui-color-9: #ffffff; --prismui-color-9: #ffffff;
--prismui-border-1: 1px solid rgba(6, 10, 38, 0.06); --prismui-border-1: 1px solid #060a260f;
--prismui-border-radius-1: 8px; --prismui-border-radius-1: 4px;
--prismui-border-radius-2: 12px; --prismui-border-radius-2: 8px;
--prismui-border-radius-3: 20px; --prismui-border-radius-3: 12px;
--mc-float-block-shadow: #d5d5d5; --prismui-border-radius-4: 20px;
--devui-global-bg: #f6f6f8;
--mc-box-shadow: #191919;
--devui-shadow-length-connected-overlay: 0px 0px 12px 0px #000000;
--prismui-box-shadow-1: 0 4px 64px 0 #0000001a; --prismui-box-shadow-1: 0 4px 64px 0 #0000001a;
--prismui-box-shadow-2: 0 4px 12px #0000001a; --prismui-box-shadow-2: 0 4px 12px #0000001a;
--prismui-box-shadow-3: 0 2px 12px 0 #252b3a3d; --prismui-box-shadow-3: 0 2px 12px 0 #252b3a3d;
--devui-icon-fill-weak: #babbc0; --prismui-box-shadow-4: 2px 0 4px 0 #d5d5d540;
--prismui-background-color-weak: #babbc0; --prismui-box-shadow-5: -2px -2px 4px #0000000d;
--devui-border-radius-feedback: 4px; background-color: var(--prismui-background-color-1);
} }

Binary file not shown.