v0.9.9
parent
06d58be444
commit
194928e0e1
|
|
@ -33,7 +33,7 @@ logs/
|
|||
*.temp
|
||||
|
||||
# Local models
|
||||
models
|
||||
backend/models
|
||||
|
||||
# AI
|
||||
.gemini-clipboard/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
导出所有数据库模型
|
||||
"""
|
||||
from app.core.database import Base
|
||||
from app.models.user import User
|
||||
from app.models.role import Role, UserRole
|
||||
from app.models.menu import SystemMenu, RoleMenu
|
||||
from app.models.project import Project, ProjectMember, ProjectMemberRole
|
||||
from app.models.document import DocumentMeta
|
||||
from app.models.document_vector import DocumentVector
|
||||
from app.models.share import ShareLink
|
||||
from app.models.log import OperationLog
|
||||
from app.models.mcp_bot import MCPBot
|
||||
from app.models.llm_model_config import LLMModelConfig
|
||||
from app.models.chat_session import ChatSession, ChatMessage
|
||||
from app.models.project_vectorization_task import ProjectVectorizationTask
|
||||
|
||||
__all__ = [
|
||||
"Base",
|
||||
"User",
|
||||
"Role",
|
||||
"UserRole",
|
||||
"SystemMenu",
|
||||
"RoleMenu",
|
||||
"Project",
|
||||
"ProjectMember",
|
||||
"ProjectMemberRole",
|
||||
"DocumentMeta",
|
||||
"DocumentVector",
|
||||
"ShareLink",
|
||||
"OperationLog",
|
||||
"MCPBot",
|
||||
"LLMModelConfig",
|
||||
"ChatSession",
|
||||
"ChatMessage",
|
||||
"ProjectVectorizationTask",
|
||||
]
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
知识库对话会话模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, Text, Boolean
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class ChatSession(Base):
|
||||
"""对话会话表"""
|
||||
|
||||
__tablename__ = "chat_session"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="会话ID")
|
||||
project_id = Column(BigInteger, nullable=False, index=True, comment="项目ID")
|
||||
user_id = Column(BigInteger, nullable=False, index=True, comment="用户ID")
|
||||
llm_config_id = Column(BigInteger, nullable=False, comment="LLM配置ID")
|
||||
title = Column(String(255), nullable=False, comment="会话标题")
|
||||
description = Column(Text, comment="会话描述")
|
||||
is_active = Column(Boolean, nullable=False, default=True, comment="是否激活")
|
||||
message_count = Column(Integer, nullable=False, default=0, comment="消息数")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ChatSession(id={self.id}, project_id={self.project_id}, user_id={self.user_id})>"
|
||||
|
||||
|
||||
class ChatMessage(Base):
|
||||
"""对话消息表"""
|
||||
|
||||
__tablename__ = "chat_message"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="消息ID")
|
||||
session_id = Column(BigInteger, nullable=False, index=True, comment="会话ID")
|
||||
role = Column(String(32), nullable=False, comment="角色(user/assistant)")
|
||||
content = Column(Text, nullable=False, comment="消息内容")
|
||||
referenced_files = Column(Text, comment="参考文件(JSON数组)")
|
||||
tokens_used = Column(Integer, comment="消耗的token数")
|
||||
is_deleted = Column(Boolean, nullable=False, default=False, comment="是否已删除")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ChatMessage(id={self.id}, session_id={self.session_id}, role='{self.role}')>"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
文档元数据模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class DocumentMeta(Base):
|
||||
"""文档元数据表模型"""
|
||||
|
||||
__tablename__ = "document_meta"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="元数据ID")
|
||||
project_id = Column(BigInteger, nullable=False, index=True, comment="项目ID")
|
||||
file_path = Column(String(500), nullable=False, comment="文件相对路径")
|
||||
title = Column(String(200), comment="文档标题")
|
||||
tags = Column(String(500), comment="标签(JSON数组)")
|
||||
author_id = Column(BigInteger, index=True, comment="作者ID")
|
||||
word_count = Column(Integer, default=0, comment="字数统计")
|
||||
view_count = Column(Integer, default=0, comment="浏览次数")
|
||||
last_editor_id = Column(BigInteger, comment="最后编辑者ID")
|
||||
last_edited_at = Column(DateTime, comment="最后编辑时间")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<DocumentMeta(id={self.id}, project_id={self.project_id}, file_path='{self.file_path}')>"
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
文档向量化模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, Integer, String, DateTime, Index, Text
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class DocumentVector(Base):
|
||||
"""文档向量表模型"""
|
||||
|
||||
__tablename__ = "document_vector"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="向量ID")
|
||||
project_id = Column(BigInteger, nullable=False, index=True, comment="项目ID")
|
||||
file_path = Column(String(500), nullable=False, comment="文件相对路径")
|
||||
chunk_index = Column(Integer, nullable=False, default=0, comment="分块序号(0起),同一文件可有多个分块")
|
||||
chunk_text = Column(Text, comment="分块首段文本,作为点击引用时的定位锚点")
|
||||
content_hash = Column(String(64), comment="整个文件内容哈希值,用于判断文件是否变更")
|
||||
zvec_id = Column(String(256), comment="ZVec返回的向量ID(每个分块独立)")
|
||||
zvec_response = Column(Text, comment="ZVec完整响应JSON")
|
||||
status = Column(String(32), nullable=False, default="success", comment="向量化状态:success/failed/pending")
|
||||
error_message = Column(String(500), comment="错误信息")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
__table_args__ = (
|
||||
Index("idx_project_file", "project_id", "file_path"),
|
||||
Index("idx_project_file_chunk", "project_id", "file_path", "chunk_index"),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
f"<DocumentVector(id={self.id}, project_id={self.project_id}, "
|
||||
f"file_path='{self.file_path}', chunk_index={self.chunk_index}, status='{self.status}')>"
|
||||
)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
"""
|
||||
项目Git仓库模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, SmallInteger, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class ProjectGitRepo(Base):
|
||||
"""项目Git仓库表模型"""
|
||||
|
||||
__tablename__ = "project_git_repos"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="ID")
|
||||
project_id = Column(BigInteger, ForeignKey("projects.id", ondelete="CASCADE"), nullable=False, index=True, comment="项目ID")
|
||||
name = Column(String(50), nullable=False, comment="仓库别名")
|
||||
repo_url = Column(String(255), nullable=False, comment="Git仓库地址")
|
||||
branch = Column(String(50), default="main", comment="Git分支")
|
||||
username = Column(String(100), comment="Git用户名")
|
||||
token = Column(String(255), comment="Git访问令牌/密码")
|
||||
is_default = Column(SmallInteger, default=0, comment="是否默认仓库")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
# 关系
|
||||
# project = relationship("Project", back_populates="git_repos")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ProjectGitRepo(id={self.id}, name='{self.name}', repo_url='{self.repo_url}')>"
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
"""
|
||||
LLM 模型配置模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, Boolean, JSON
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class LLMModelConfig(Base):
|
||||
"""大模型配置表模型"""
|
||||
|
||||
__tablename__ = "llm_model_config"
|
||||
|
||||
config_id = Column(BigInteger, primary_key=True, autoincrement=True, comment="配置ID")
|
||||
model_code = Column(String(128), nullable=False, unique=True, index=True, comment="模型编码")
|
||||
model_name = Column(String(255), nullable=False, comment="模型名称")
|
||||
model_type = Column(String(32), nullable=False, default="chat", index=True, comment="模型类型: chat/embedding")
|
||||
provider = Column(String(64), comment="模型提供方")
|
||||
endpoint_url = Column(String(512), comment="接口地址")
|
||||
api_key = Column(String(512), comment="API Key")
|
||||
llm_model_name = Column(String(128), nullable=False, comment="模型名称/部署名")
|
||||
llm_timeout = Column(Integer, nullable=False, default=120, comment="超时时间(秒)")
|
||||
type_config = Column(JSON, nullable=False, default=dict, comment="模型类型差异参数")
|
||||
description = Column(String(500), comment="描述")
|
||||
is_active = Column(Boolean, nullable=False, default=True, index=True, comment="是否启用")
|
||||
is_default = Column(Boolean, nullable=False, default=False, comment="是否默认")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def _type_config_value(self, key, default=None):
|
||||
return (self.type_config or {}).get(key, default)
|
||||
|
||||
@property
|
||||
def llm_temperature(self):
|
||||
return self._type_config_value("temperature", 0.70)
|
||||
|
||||
@property
|
||||
def llm_top_p(self):
|
||||
return self._type_config_value("top_p", 0.90)
|
||||
|
||||
@property
|
||||
def llm_max_tokens(self):
|
||||
return self._type_config_value("max_tokens", 8192)
|
||||
|
||||
@property
|
||||
def llm_system_prompt(self):
|
||||
return self._type_config_value("system_prompt")
|
||||
|
||||
@property
|
||||
def embedding_dimension(self):
|
||||
return self._type_config_value("dimension")
|
||||
|
||||
@property
|
||||
def chunk_size(self):
|
||||
return self._type_config_value("chunk_size", 800)
|
||||
|
||||
@property
|
||||
def chunk_overlap(self):
|
||||
return self._type_config_value("chunk_overlap", 150)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<LLMModelConfig(config_id={self.config_id}, model_code='{self.model_code}')>"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
操作日志模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, SmallInteger, Text
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class OperationLog(Base):
|
||||
"""操作日志表模型"""
|
||||
|
||||
__tablename__ = "operation_logs"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="日志ID")
|
||||
user_id = Column(BigInteger, index=True, comment="操作用户ID")
|
||||
username = Column(String(50), comment="用户名")
|
||||
operation_type = Column(String(50), nullable=False, comment="操作类型")
|
||||
resource_type = Column(String(50), nullable=False, index=True, comment="资源类型")
|
||||
resource_id = Column(BigInteger, index=True, comment="资源ID")
|
||||
detail = Column(Text, comment="操作详情(JSON)")
|
||||
ip_address = Column(String(50), comment="IP地址")
|
||||
user_agent = Column(String(500), comment="用户代理")
|
||||
status = Column(SmallInteger, default=1, comment="状态:0-失败 1-成功")
|
||||
error_message = Column(Text, comment="错误信息")
|
||||
created_at = Column(DateTime, server_default=func.now(), index=True, comment="操作时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<OperationLog(id={self.id}, operation_type='{self.operation_type}')>"
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
"""
|
||||
MCP bot credential model.
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, DateTime, SmallInteger
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class MCPBot(Base):
|
||||
"""Stores MCP access credentials mapped to a NexDocs user."""
|
||||
|
||||
__tablename__ = "mcp_bots"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="Bot credential ID")
|
||||
user_id = Column(BigInteger, nullable=False, unique=True, index=True, comment="Owner user ID")
|
||||
bot_id = Column(String(64), nullable=False, unique=True, index=True, comment="External MCP bot id")
|
||||
bot_secret = Column(String(255), nullable=False, comment="External MCP bot secret")
|
||||
status = Column(SmallInteger, default=1, index=True, comment="Status: 0-disabled 1-enabled")
|
||||
last_used_at = Column(DateTime, comment="Last successful MCP access time")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="Created at")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="Updated at")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<MCPBot(user_id={self.user_id}, bot_id='{self.bot_id}')>"
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
菜单模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, SmallInteger
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class SystemMenu(Base):
|
||||
"""系统菜单表模型"""
|
||||
|
||||
__tablename__ = "system_menus"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="菜单ID")
|
||||
parent_id = Column(BigInteger, default=0, comment="父菜单ID(0表示根菜单)")
|
||||
menu_name = Column(String(50), nullable=False, comment="菜单名称")
|
||||
menu_code = Column(String(50), nullable=False, unique=True, index=True, comment="菜单编码")
|
||||
menu_type = Column(SmallInteger, nullable=False, comment="菜单类型:1-目录 2-菜单 3-按钮/权限点")
|
||||
path = Column(String(255), comment="路由路径")
|
||||
component = Column(String(255), comment="组件路径")
|
||||
icon = Column(String(100), comment="图标")
|
||||
sort_order = Column(Integer, default=0, comment="排序号")
|
||||
visible = Column(SmallInteger, default=1, comment="是否可见:0-隐藏 1-显示")
|
||||
status = Column(SmallInteger, default=1, index=True, comment="状态:0-禁用 1-启用")
|
||||
permission = Column(String(100), comment="权限字符串")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<SystemMenu(id={self.id}, menu_name='{self.menu_name}')>"
|
||||
|
||||
|
||||
class RoleMenu(Base):
|
||||
"""角色菜单授权表模型"""
|
||||
|
||||
__tablename__ = "role_menus"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="关联ID")
|
||||
role_id = Column(BigInteger, nullable=False, index=True, comment="角色ID")
|
||||
menu_id = Column(BigInteger, nullable=False, index=True, comment="菜单ID")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<RoleMenu(role_id={self.role_id}, menu_id={self.menu_id})>"
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
"""
|
||||
通知模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, DateTime, SmallInteger, Text, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class Notification(Base):
|
||||
"""用户通知表模型"""
|
||||
|
||||
__tablename__ = "notifications"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="通知ID")
|
||||
user_id = Column(BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True, comment="接收用户ID")
|
||||
type = Column(String(20), default="info", comment="类型:info, success, warning, error")
|
||||
category = Column(String(50), default="system", comment="分类:system, project, collaboration")
|
||||
title = Column(String(200), nullable=False, comment="标题")
|
||||
content = Column(Text, comment="内容")
|
||||
link = Column(String(255), comment="跳转链接")
|
||||
is_read = Column(SmallInteger, default=0, comment="是否已读:0-未读 1-已读")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
read_at = Column(DateTime, comment="阅读时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Notification(id={self.id}, user_id={self.user_id}, title='{self.title}')>"
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
"""
|
||||
项目模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, SmallInteger, Enum
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
import enum
|
||||
|
||||
|
||||
class ProjectMemberRole(str, enum.Enum):
|
||||
"""项目成员角色枚举"""
|
||||
ADMIN = "admin"
|
||||
EDITOR = "editor"
|
||||
VIEWER = "viewer"
|
||||
|
||||
|
||||
class Project(Base):
|
||||
"""项目表模型"""
|
||||
|
||||
__tablename__ = "projects"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="项目ID")
|
||||
name = Column(String(100), nullable=False, index=True, comment="项目名称")
|
||||
description = Column(String(500), comment="项目描述")
|
||||
storage_key = Column(String(36), nullable=False, unique=True, comment="磁盘存储UUID")
|
||||
owner_id = Column(BigInteger, nullable=False, index=True, comment="项目所有者ID")
|
||||
is_public = Column(SmallInteger, default=0, comment="是否公开:0-私有 1-公开")
|
||||
is_template = Column(SmallInteger, default=0, comment="是否模板项目:0-否 1-是")
|
||||
status = Column(SmallInteger, default=1, index=True, comment="状态:0-归档 1-活跃")
|
||||
cover_image = Column(String(255), comment="封面图")
|
||||
sort_order = Column(Integer, default=0, comment="排序号")
|
||||
visit_count = Column(Integer, default=0, comment="访问次数")
|
||||
access_pass = Column(String(100), comment="访问密码(用于分享链接)")
|
||||
created_at = Column(DateTime, server_default=func.now(), index=True, comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Project(id={self.id}, name='{self.name}')>"
|
||||
|
||||
|
||||
class ProjectMember(Base):
|
||||
"""项目成员表模型"""
|
||||
|
||||
__tablename__ = "project_members"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="成员ID")
|
||||
project_id = Column(BigInteger, nullable=False, index=True, comment="项目ID")
|
||||
user_id = Column(BigInteger, nullable=False, index=True, comment="用户ID")
|
||||
role = Column(
|
||||
String(20),
|
||||
default="viewer",
|
||||
index=True,
|
||||
comment="项目角色: admin/editor/viewer"
|
||||
)
|
||||
invited_by = Column(BigInteger, comment="邀请人ID")
|
||||
joined_at = Column(DateTime, server_default=func.now(), comment="加入时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ProjectMember(project_id={self.project_id}, user_id={self.user_id}, role='{self.role}')>"
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
项目向量化任务模型
|
||||
"""
|
||||
from sqlalchemy import BigInteger, Column, DateTime, Index, Integer, String, Text
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class ProjectVectorizationTask(Base):
|
||||
"""项目向量化后台任务表"""
|
||||
|
||||
__tablename__ = "project_vectorization_task"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="任务ID")
|
||||
task_id = Column(String(64), nullable=False, unique=True, index=True, comment="任务唯一标识")
|
||||
project_id = Column(BigInteger, nullable=False, index=True, comment="项目ID")
|
||||
user_id = Column(BigInteger, nullable=False, index=True, comment="触发用户ID")
|
||||
task_type = Column(String(32), nullable=False, comment="任务类型:incremental/full")
|
||||
status = Column(String(32), nullable=False, default="pending", index=True, comment="任务状态:pending/running/success/failed")
|
||||
total = Column(Integer, nullable=False, default=0, comment="文件总数")
|
||||
processed = Column(Integer, nullable=False, default=0, comment="处理成功数")
|
||||
skipped = Column(Integer, nullable=False, default=0, comment="跳过数")
|
||||
failed = Column(Integer, nullable=False, default=0, comment="失败数")
|
||||
error_message = Column(Text, comment="错误信息")
|
||||
started_at = Column(DateTime, comment="开始时间")
|
||||
finished_at = Column(DateTime, comment="完成时间")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
__table_args__ = (
|
||||
Index("idx_vector_task_project_status", "project_id", "status"),
|
||||
Index("idx_vector_task_created_at", "created_at"),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ProjectVectorizationTask(task_id='{self.task_id}', project_id={self.project_id}, status='{self.status}')>"
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
"""
|
||||
角色模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, DateTime, SmallInteger
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class Role(Base):
|
||||
"""角色表模型"""
|
||||
|
||||
__tablename__ = "roles"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="角色ID")
|
||||
role_name = Column(String(50), nullable=False, unique=True, comment="角色名称")
|
||||
role_code = Column(String(50), nullable=False, unique=True, index=True, comment="角色编码")
|
||||
description = Column(String(255), comment="角色描述")
|
||||
status = Column(SmallInteger, default=1, index=True, comment="状态:0-禁用 1-启用")
|
||||
is_system = Column(SmallInteger, default=0, comment="是否系统角色:0-否 1-是")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Role(id={self.id}, role_code='{self.role_code}')>"
|
||||
|
||||
|
||||
class UserRole(Base):
|
||||
"""用户角色关联表模型"""
|
||||
|
||||
__tablename__ = "user_roles"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="关联ID")
|
||||
user_id = Column(BigInteger, nullable=False, index=True, comment="用户ID")
|
||||
role_id = Column(BigInteger, nullable=False, index=True, comment="角色ID")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<UserRole(user_id={self.user_id}, role_id={self.role_id})>"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
分享链接模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, DateTime, SmallInteger
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class ShareLink(Base):
|
||||
"""项目分享/文件分享链接"""
|
||||
|
||||
__tablename__ = "share_links"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="分享ID")
|
||||
project_id = Column(BigInteger, nullable=False, index=True, comment="项目ID")
|
||||
share_type = Column(String(20), nullable=False, index=True, comment="分享类型: project/file")
|
||||
share_code = Column(String(64), nullable=False, unique=True, index=True, comment="公开分享码")
|
||||
file_path = Column(String(500), comment="文件路径,仅文件分享使用")
|
||||
access_pass = Column(String(100), comment="访问密码")
|
||||
created_by = Column(BigInteger, index=True, comment="创建人ID")
|
||||
status = Column(SmallInteger, default=1, index=True, comment="状态:0-禁用 1-启用")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ShareLink(id={self.id}, type='{self.share_type}', code='{self.share_code}')>"
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
"""
|
||||
用户模型
|
||||
"""
|
||||
from sqlalchemy import Column, BigInteger, String, Integer, DateTime, SmallInteger
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class User(Base):
|
||||
"""用户表模型"""
|
||||
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, autoincrement=True, comment="用户ID")
|
||||
username = Column(String(50), nullable=False, unique=True, index=True, comment="用户名")
|
||||
password_hash = Column(String(255), nullable=False, comment="密码哈希")
|
||||
nickname = Column(String(50), comment="昵称")
|
||||
email = Column(String(100), index=True, comment="邮箱")
|
||||
phone = Column(String(20), comment="手机号")
|
||||
avatar = Column(String(255), comment="头像URL")
|
||||
status = Column(SmallInteger, default=1, index=True, comment="状态:0-禁用 1-启用")
|
||||
is_superuser = Column(SmallInteger, default=0, comment="是否超级管理员:0-否 1-是")
|
||||
last_login_at = Column(DateTime, comment="最后登录时间")
|
||||
last_login_ip = Column(String(50), comment="最后登录IP")
|
||||
created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<User(id={self.id}, username='{self.username}')>"
|
||||
|
|
@ -49,3 +49,4 @@ sentence-transformers>=3.0,<6
|
|||
weasyprint==61.2
|
||||
pydyf<0.11.0
|
||||
mcp==1.26.0
|
||||
zvec==0.6.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue