Compare commits

...

2 Commits

Author SHA1 Message Date
liubiren b9fa4109f4 Merge branch 'main' of https://gitea.liubiren.cloud/liubiren/Python 2026-07-23 20:11:05 +08:00
liubiren acbdd8216b 1 2026-07-23 20:10:39 +08:00
5 changed files with 81 additions and 52 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
表模型 数据表模型
""" """
from datetime import datetime, timedelta from datetime import datetime, timedelta
from random import choices from random import choices
@ -9,30 +9,31 @@ from pydantic_ai._uuid import uuid7
from sqlmodel import Field, JSON, SQLModel from sqlmodel import Field, JSON, SQLModel
# 验证码表 class CaptchaTable(SQLModel, table=True):
class Captchas(SQLModel, table=True): """
验证码表
"""
email: str = Field(..., primary_key=True, description="邮箱") email: str = Field(..., primary_key=True, description="邮箱")
captcha: str = Field( captcha: str = Field(
default_factory=lambda: "".join(choices("0123456789", k=6)), default_factory=lambda: "".join(choices("0123456789", k=6)),
primary_key=True,
description="验证码", description="验证码",
) )
is_valid: bool = Field( is_verified: bool = Field(
default=True, index=True, description="是否有效True 表示有效False 表示无效" default=False,
)
is_unused: bool = Field(
default=True,
index=True, index=True,
description="是否未使用True 表示未使用False 表示已使用。", description="已核验True 表示已核验False 表示未核验",
) )
expired_at: datetime = Field( expired_at: datetime = Field(
default_factory=lambda: datetime.now() + timedelta(minutes=30), default_factory=lambda: datetime.now() + timedelta(minutes=30),
primary_key=True, primary_key=True,
description="过期时间", description="失效时间",
) )
# 用户表 # 用户表
class Users(SQLModel, table=True): class UserTable(SQLModel, table=True):
id: str = Field( id: str = Field(
default_factory=lambda: str(uuid7()), default_factory=lambda: str(uuid7()),
primary_key=True, primary_key=True,
@ -42,7 +43,7 @@ class Users(SQLModel, table=True):
# 会话表 # 会话表
class Conversations(SQLModel, table=True): class ConversationTable(SQLModel, table=True):
id: str = Field( id: str = Field(
default_factory=lambda: str(uuid7()), default_factory=lambda: str(uuid7()),
primary_key=True, primary_key=True,
@ -50,8 +51,8 @@ class Conversations(SQLModel, table=True):
) )
user_id: str = Field(..., index=True, description="用户唯一标识") user_id: str = Field(..., index=True, description="用户唯一标识")
description: str = Field(..., description="会话描述") description: str = Field(..., description="会话描述")
is_deleted: bool = Field(default=False, index=True, description="是否删除")
created_at: datetime = Field(default_factory=datetime.now, description="创建时间") created_at: datetime = Field(default_factory=datetime.now, description="创建时间")
is_deleted: bool = Field(default=False, index=True, description="已删除True 表示已删除False 表示未删除")
# 思考节点表(仅定义) # 思考节点表(仅定义)

View File

@ -6,18 +6,19 @@ import reflex as rx
from application.models import Conversation, Dialog, ThoughtNode from application.models import Conversation, Dialog, ThoughtNode
from application.states import ConversationState, AuthState from application.states import ConversationState, AuthState
from reflex_base.vars.object import ObjectVar
def render_conversation_history_item( def render_conversation_history_item(
item: rx.Var[tuple[str, Conversation]], item: rx.Var[tuple],
) -> rx.Component: ) -> rx.Component:
""" """
渲染会话历史条目 渲染会话历史条目
:param item: 会话历史条目 :param item: 会话历史条目
:return: Component :return: Component
""" """
# 解构会话唯一标识和会话实例 conversation_id: rx.Var[str] = item[0]
conversation_id, conversation = item[0], item[1] # type: ignore conversation: ObjectVar[Conversation] = item[1].to(Conversation)
# 会话激活状态 # 会话激活状态
is_conversation_actived = conversation_id == ConversationState.conversation_id is_conversation_actived = conversation_id == ConversationState.conversation_id
@ -44,7 +45,10 @@ def render_conversation_history_item(
rx.popover.trigger( rx.popover.trigger(
rx.box( rx.box(
rx.icon( rx.icon(
"ellipsis", size=14, color="var(--prismui-color-2)" "ellipsis",
width="14px",
height="14px",
color="var(--prismui-color-2)",
), ),
cursor="pointer", cursor="pointer",
) )
@ -115,6 +119,14 @@ def render_conversation_history_item(
margin_bottom="8px", margin_bottom="8px",
cursor="pointer", cursor="pointer",
), ),
rx.hstack(
rx.spacer(),
# 创建时间
rx.text(
"1",
margin_bottom="8px",
),
),
), ),
width="100%", width="100%",
padding="16px", padding="16px",
@ -124,7 +136,7 @@ def render_conversation_history_item(
"linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)", "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
"var(--prismui-background-color-1)", "var(--prismui-background-color-1)",
), ),
border_radius="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
box_shadow=rx.cond(is_conversation_actived, "2px 2px 8px #e9e9e9", "none"), box_shadow=rx.cond(is_conversation_actived, "2px 2px 8px #e9e9e9", "none"),
style={ style={
"&:hover": { "&:hover": {
@ -142,10 +154,12 @@ def render_conversation_history_item(
) )
def render_collapse(is_expanded: bool) -> rx.Component: def conversation_history_collapse(
is_conversation_history_shown: bool,
) -> rx.Component:
""" """
渲染折叠面板 会话历史折叠面板
:param is_expanded: 折叠面板展开状态 :param is_conversation_history_shown: 会话历史展示状态
:return: Component :return: Component
""" """
return rx.box( return rx.box(
@ -161,22 +175,22 @@ def render_collapse(is_expanded: bool) -> rx.Component:
align_items="center", align_items="center",
justify_content="space-between", justify_content="space-between",
), ),
# 渲染列表 # 渲染会话历史列表
rx.auto_scroll( rx.auto_scroll(
rx.foreach( rx.foreach(
ConversationState.conversation_history, ConversationState.conversation_history,
render_conversation_history_item, render_conversation_history_item,
), ),
flex="1", flex="1",
margin_top="8px",
width="100%",
align_items="stretch", align_items="stretch",
overflow="auto", width="100%",
margin_top="8px",
style={ style={
"&::-webkit-scrollbar": { "&::-webkit-scrollbar": {
"display": "none", "display": "none",
}, },
}, },
overflow="auto",
), ),
display="flex", display="flex",
flex_direction="column", flex_direction="column",
@ -185,14 +199,13 @@ def render_collapse(is_expanded: bool) -> rx.Component:
background_color="#f9f9f9cc", background_color="#f9f9f9cc",
backdrop_filter="blur(50px)", backdrop_filter="blur(50px)",
gap="12px", gap="12px",
color="var(--prismui-color-text)",
), ),
width=rx.cond(is_expanded, "25%", "0px"), width=rx.cond(is_conversation_history_shown, "25%", "0px"),
min_width=rx.cond(is_expanded, "240px", "0px"), min_width=rx.cond(is_conversation_history_shown, "240px", "0px"),
max_width=rx.cond(is_expanded, "380px", "0px"), max_width=rx.cond(is_conversation_history_shown, "380px", "0px"),
height="100%", height="100%",
overflow="hidden",
transition="all 0.3s ease-in-out", transition="all 0.3s ease-in-out",
overflow="hidden",
) )
@ -357,7 +370,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="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
word_wrap="break-word", word_wrap="break-word",
word_break="break-all", word_break="break-all",
white_space="pre-line", white_space="pre-line",
@ -712,9 +725,9 @@ def render_input() -> rx.Component:
) )
def render_workplace() -> rx.Component: def workbench() -> rx.Component:
""" """
渲染会话工作区 工作台
:return: Component :return: Component
""" """
return rx.box( return rx.box(
@ -742,16 +755,16 @@ def render_workplace() -> rx.Component:
def render_conversation_history_collapse_button( def render_conversation_history_collapse_button(
is_expanded: bool, is_conversation_history_shown: bool,
) -> rx.Component: ) -> rx.Component:
""" """
渲染会话历史折叠面板按钮 渲染会话历史折叠面板按钮
:param is_expanded: 会话历史折叠面板展开状态 :param is_conversation_history_shown: 会话历史展示状态
:return: Component :return: Component
""" """
return rx.button( return rx.button(
rx.icon( rx.icon(
rx.cond(is_expanded, "chevron-left", "chevron-right"), rx.cond(is_conversation_history_shown, "chevron-left", "chevron-right"),
stroke_width=1, stroke_width=1,
width="16px", width="16px",
height="16px", height="16px",
@ -759,12 +772,18 @@ def render_conversation_history_collapse_button(
), ),
position="absolute", position="absolute",
top="calc(50% - 20px)", top="calc(50% - 20px)",
left=rx.cond(is_expanded, "calc(clamp(240px, 25%, 380px) - 8px)", "0"), left=rx.cond(
is_conversation_history_shown, "calc(clamp(240px, 25%, 380px) - 8px)", "0"
),
z_index=99, z_index=99,
width="16px", width="16px",
height="40px", height="40px",
background_color="var(--prismui-background-color-1)", background_color="var(--prismui-background-color-1)",
border_radius=rx.cond(is_expanded, "6px", "0 6px 6px 0"), border_radius=rx.cond(
is_conversation_history_shown,
"var(--prismui-border-radius-2)",
"0 var(--prismui-border-radius-2)",
),
box_shadow="var(--prismui-box-shadow-4)", 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",
@ -782,10 +801,17 @@ def render_conversation() -> rx.Component:
return rx.box( return rx.box(
rx.hstack( rx.hstack(
<<<<<<< HEAD
# 会话历史折叠面板
conversation_history_collapse(is_conversation_history_shown),
# 工作台
workbench(),
=======
# 渲染折叠面板 # 渲染折叠面板
render_collapse(is_conversation_history_shown), render_collapse(is_conversation_history_shown),
# 渲染工作区 # 渲染工作区
render_workplace(), render_workplace(),
>>>>>>> 7f6a992830604a43946173a1d6573aa63f835d55
position="relative", position="relative",
display="flex", display="flex",
flex="1", flex="1",
@ -794,12 +820,12 @@ def render_conversation() -> rx.Component:
overflow="hidden", overflow="hidden",
transition="all 0.3s ease-in-out", transition="all 0.3s ease-in-out",
), ),
# 渲染对话历史折叠面板打开/关闭按钮 # 渲染会话历史折叠面板按钮
render_conversation_history_collapse_button(is_conversation_history_shown), render_conversation_history_collapse_button(is_conversation_history_shown),
position="relative", position="relative",
width="100%", width="100%",
height="100%", height="100%",
border_radius="var(--prismui-border-radius-3)", border_radius="var(--prismui-border-radius-4)",
overflow="hidden", overflow="hidden",
# 挂载事件:同步用户唯一标识 # 挂载事件:同步用户唯一标识
on_mount=AuthState.sync_user_id, on_mount=AuthState.sync_user_id,

View File

@ -45,7 +45,7 @@ def render_nav_button(
"var(--prismui-background-color-1)", "var(--prismui-background-color-1)",
"transparent", "transparent",
), ),
border_radius="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
box_shadow=rx.cond( box_shadow=rx.cond(
is_nav_button_actived, "var(--prismui-box-shadow-2)", "none" is_nav_button_actived, "var(--prismui-box-shadow-2)", "none"
), ),
@ -88,7 +88,7 @@ def render_settings_button():
align_items="center", align_items="center",
width="36px", width="36px",
height="36px", height="36px",
border_radius="var(--prismui-border-radius-2)", border_radius="var(--prismui-border-radius-3)",
style={ style={
"&:hover": { "&:hover": {
"background": "var(--prismui-background-color-5)", "background": "var(--prismui-background-color-5)",
@ -120,7 +120,7 @@ def render_settings_button():
border_radius="var(--prismui-border-radius-1)", border_radius="var(--prismui-border-radius-1)",
style={ style={
"_hover": { "_hover": {
"background_color": "var(--prismui-color-7, #f2f2f3)", "background_color": "var(--prismui-background-color-6)",
}, },
}, },
# 点击事件:退出登录 # 点击事件:退出登录
@ -133,6 +133,7 @@ def render_settings_button():
position="relative", position="relative",
align="center", align="center",
padding="4px 12px", padding="4px 12px",
border_radius="var(--prismui-border-radius-1)",
box_shadow="var(--prismui-box-shadow-3)", box_shadow="var(--prismui-box-shadow-3)",
font_family="var(--prismui-font-family)", font_family="var(--prismui-font-family)",
overflow="visible", overflow="visible",
@ -235,7 +236,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-3)", border_radius="var(--prismui-border-radius-4)",
line_height="16px", line_height="16px",
# 值变化事件:设置邮箱 # 值变化事件:设置邮箱
on_change=AuthState.set_email, on_change=AuthState.set_email,
@ -287,7 +288,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-3)", border_radius="var(--prismui-border-radius-4)",
), ),
rx.text( rx.text(
AuthState.login_error_message, AuthState.login_error_message,
@ -363,7 +364,7 @@ def render_login_window() -> rx.Component:
"登录", "登录",
width="100%", width="100%",
height="38px", height="38px",
border_radius="var(--prismui-border-radius-3)", border_radius="var(--prismui-border-radius-4)",
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",
@ -391,7 +392,7 @@ 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-4)", border_radius="var(--prismui-border-radius-5)",
), ),
rx.text( rx.text(
"加微信好友", "加微信好友",
@ -408,7 +409,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-4)", border_radius="var(--prismui-border-radius-5)",
box_shadow="0 4px 64px 0 #0000001a", box_shadow="0 4px 64px 0 #0000001a",
overflow="hidden", overflow="hidden",
), ),

View File

@ -24,9 +24,10 @@
--prismui-color-9: #ffffff; --prismui-color-9: #ffffff;
--prismui-border-1: 1px solid #060a260f; --prismui-border-1: 1px solid #060a260f;
--prismui-border-radius-1: 4px; --prismui-border-radius-1: 4px;
--prismui-border-radius-2: 8px; --prismui-border-radius-2: 6px;
--prismui-border-radius-3: 12px; --prismui-border-radius-3: 8px;
--prismui-border-radius-4: 20px; --prismui-border-radius-4: 12px;
--prismui-border-radius-5: 20px;
--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;

Binary file not shown.