初始提交:极码 GeekCode 全栈项目(FastAPI + Vue3)
This commit is contained in:
9
backend/models/__init__.py
Normal file
9
backend/models/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from models.user import User
|
||||
from models.conversation import Conversation, Message
|
||||
from models.post import Post
|
||||
from models.comment import Comment
|
||||
from models.like import Like, Collect
|
||||
from models.ai_model import AIModelConfig
|
||||
from models.bookmark import BookmarkSite
|
||||
from models.follow import Follow
|
||||
from models.notification import Notification
|
||||
25
backend/models/ai_model.py
Normal file
25
backend/models/ai_model.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""AI模型配置模型"""
|
||||
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class AIModelConfig(Base):
|
||||
"""AI模型配置表 - 存储各AI服务商的模型信息和API Key"""
|
||||
__tablename__ = "ai_model_configs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
provider = Column(String(50), nullable=False) # openai/anthropic/google/deepseek
|
||||
provider_name = Column(String(100), default="") # 显示名称
|
||||
model_id = Column(String(100), nullable=False) # 模型标识符
|
||||
model_name = Column(String(100), default="") # 模型显示名称
|
||||
api_key = Column(String(500), default="") # API Key
|
||||
base_url = Column(String(500), default="") # 自定义API地址
|
||||
task_type = Column(String(50), default="") # 任务类型: multimodal/reasoning/lightweight/embedding
|
||||
is_enabled = Column(Boolean, default=True) # 是否启用
|
||||
is_default = Column(Boolean, default=False) # 是否为该任务类型的默认模型
|
||||
web_search_enabled = Column(Boolean, default=False) # 是否启用联网搜索(仅豆包/火山方舟支持)
|
||||
web_search_count = Column(Integer, default=5) # 联网搜索结果条数(1-50,默认5)
|
||||
description = Column(Text, default="") # 描述说明
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
18
backend/models/attachment.py
Normal file
18
backend/models/attachment.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""附件模型"""
|
||||
from sqlalchemy import Column, Integer, String, BigInteger, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Attachment(Base):
|
||||
__tablename__ = "attachments"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
post_id = Column(Integer, nullable=True, default=None, index=True) # 新建文章时为null,发布后回填
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
filename = Column(String(255), nullable=False) # 原始文件名
|
||||
storage_key = Column(String(500), nullable=False) # COS对象键
|
||||
url = Column(String(500), nullable=False) # 完整访问URL
|
||||
file_size = Column(BigInteger, nullable=False) # 文件大小(字节)
|
||||
file_type = Column(String(100), nullable=False) # MIME类型
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
16
backend/models/bookmark.py
Normal file
16
backend/models/bookmark.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""网站收藏模型"""
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class BookmarkSite(Base):
|
||||
__tablename__ = "bookmark_sites"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
name = Column(String(100), nullable=False)
|
||||
url = Column(String(500), nullable=False)
|
||||
icon = Column(String(500), default="")
|
||||
sort_order = Column(Integer, default=0)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
13
backend/models/category.py
Normal file
13
backend/models/category.py
Normal file
@@ -0,0 +1,13 @@
|
||||
"""帖子分类模型"""
|
||||
from sqlalchemy import Column, Integer, String, Boolean
|
||||
from database import Base
|
||||
|
||||
|
||||
class Category(Base):
|
||||
"""帖子分类表"""
|
||||
__tablename__ = "categories"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(50), unique=True, nullable=False)
|
||||
sort_order = Column(Integer, default=0) # 排序,越小越靠前
|
||||
is_active = Column(Boolean, default=True) # 是否启用
|
||||
14
backend/models/comment.py
Normal file
14
backend/models/comment.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""评论模型"""
|
||||
from sqlalchemy import Column, Integer, Text, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Comment(Base):
|
||||
__tablename__ = "comments"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
content = Column(Text, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
33
backend/models/conversation.py
Normal file
33
backend/models/conversation.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""对话模型 - 用于需求助手和架构助手"""
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
import enum
|
||||
|
||||
|
||||
class ConversationType(str, enum.Enum):
|
||||
"""对话类型"""
|
||||
REQUIREMENT = "requirement" # 需求理解
|
||||
ARCHITECTURE = "architecture" # 架构选型
|
||||
|
||||
|
||||
class Conversation(Base):
|
||||
__tablename__ = "conversations"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
title = Column(String(200), default="新对话")
|
||||
type = Column(String(20), nullable=False) # requirement / architecture
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class Message(Base):
|
||||
__tablename__ = "messages"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
conversation_id = Column(Integer, ForeignKey("conversations.id"), nullable=False, index=True)
|
||||
role = Column(String(20), nullable=False) # user / assistant
|
||||
content = Column(Text, nullable=False)
|
||||
image_urls = Column(Text, default="") # JSON数组,存储图片路径
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
17
backend/models/follow.py
Normal file
17
backend/models/follow.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""关注关系模型"""
|
||||
from sqlalchemy import Column, Integer, DateTime, ForeignKey, UniqueConstraint
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Follow(Base):
|
||||
__tablename__ = "follows"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
follower_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
following_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("follower_id", "following_id", name="uq_follow"),
|
||||
)
|
||||
42
backend/models/knowledge_base.py
Normal file
42
backend/models/knowledge_base.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""团队知识库模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class KbCategory(Base):
|
||||
"""知识库分类"""
|
||||
__tablename__ = "kb_categories"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(100), nullable=False, unique=True)
|
||||
icon = Column(String(500), default="")
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class KbItem(Base):
|
||||
"""知识库条目(关联帖子)"""
|
||||
__tablename__ = "kb_items"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
category_id = Column(Integer, ForeignKey("kb_categories.id"), nullable=True, index=True)
|
||||
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False, index=True)
|
||||
title = Column(String(200), nullable=False)
|
||||
summary = Column(Text, default="")
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
added_by = Column(Integer, ForeignKey("users.id"), nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class KbAccessLog(Base):
|
||||
"""知识库访问日志"""
|
||||
__tablename__ = "kb_access_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
||||
action = Column(String(20), default="view") # view / search / ai_chat
|
||||
query = Column(Text, default="")
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
44
backend/models/like.py
Normal file
44
backend/models/like.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""点赞/收藏模型"""
|
||||
from sqlalchemy import Column, Integer, DateTime, ForeignKey, UniqueConstraint
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Like(Base):
|
||||
__tablename__ = "likes"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("post_id", "user_id", name="uq_like_post_user"),
|
||||
)
|
||||
|
||||
|
||||
class Collect(Base):
|
||||
__tablename__ = "collects"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("post_id", "user_id", name="uq_collect_post_user"),
|
||||
)
|
||||
|
||||
|
||||
class ProjectCollect(Base):
|
||||
"""开源项目收藏"""
|
||||
__tablename__ = "project_collects"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("project_id", "user_id", name="uq_project_collect_user"),
|
||||
)
|
||||
15
backend/models/nav_category.py
Normal file
15
backend/models/nav_category.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""导航分类模型"""
|
||||
from sqlalchemy import Column, Integer, String, Boolean, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class NavCategory(Base):
|
||||
__tablename__ = "nav_categories"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(100), nullable=False)
|
||||
icon = Column(String(500), default="")
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
22
backend/models/nav_link.py
Normal file
22
backend/models/nav_link.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""导航链接模型"""
|
||||
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class NavLink(Base):
|
||||
__tablename__ = "nav_links"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
category_id = Column(Integer, ForeignKey("nav_categories.id"), nullable=False, index=True)
|
||||
name = Column(String(100), nullable=False)
|
||||
url = Column(String(500), nullable=False)
|
||||
icon = Column(String(500), default="")
|
||||
description = Column(String(200), default="")
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
# 审核相关: approved=已通过, pending=待审核, rejected=已拒绝
|
||||
status = Column(String(20), default="approved", nullable=False, index=True)
|
||||
submitted_by = Column(Integer, ForeignKey("users.id"), nullable=True)
|
||||
reject_reason = Column(String(200), default="")
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
17
backend/models/notification.py
Normal file
17
backend/models/notification.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""消息通知模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Notification(Base):
|
||||
__tablename__ = "notifications"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
type = Column(String(20), nullable=False) # like / comment / follow / system
|
||||
content = Column(Text, default="")
|
||||
related_id = Column(Integer, default=None) # 关联的帖子/用户ID
|
||||
from_user_id = Column(Integer, ForeignKey("users.id"), default=None) # 触发通知的用户
|
||||
is_read = Column(Boolean, default=False, index=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
23
backend/models/post.py
Normal file
23
backend/models/post.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""经验帖模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Post(Base):
|
||||
__tablename__ = "posts"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
title = Column(String(200), nullable=False)
|
||||
content = Column(Text, nullable=False)
|
||||
category = Column(String(50), default="") # 分类:前端/后端/部署/踩坑/最佳实践
|
||||
tags = Column(Text, default="") # JSON数组存储标签
|
||||
is_public = Column(Boolean, default=True)
|
||||
is_draft = Column(Boolean, default=False, index=True) # 草稿状态
|
||||
view_count = Column(Integer, default=0)
|
||||
like_count = Column(Integer, default=0)
|
||||
collect_count = Column(Integer, default=0)
|
||||
comment_count = Column(Integer, default=0)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
24
backend/models/project.py
Normal file
24
backend/models/project.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""开源项目模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Project(Base):
|
||||
__tablename__ = "projects"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(200), nullable=False)
|
||||
description = Column(Text, default="")
|
||||
url = Column(String(500), nullable=False)
|
||||
homepage = Column(String(500), default="")
|
||||
icon = Column(String(500), default="")
|
||||
language = Column(String(50), default="")
|
||||
category = Column(String(50), default="", index=True)
|
||||
stars = Column(Integer, default=0)
|
||||
forks = Column(Integer, default=0)
|
||||
collect_count = Column(Integer, default=0)
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
59
backend/models/shared_api.py
Normal file
59
backend/models/shared_api.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""共享API管理模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class SharedApiCategory(Base):
|
||||
"""API分类"""
|
||||
__tablename__ = "shared_api_categories"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(100), nullable=False, unique=True)
|
||||
icon = Column(String(500), default="")
|
||||
sort_order = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class SharedApi(Base):
|
||||
"""共享API"""
|
||||
__tablename__ = "shared_apis"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
category_id = Column(Integer, ForeignKey("shared_api_categories.id"), nullable=True, index=True)
|
||||
name = Column(String(200), nullable=False)
|
||||
description = Column(Text, default="")
|
||||
base_url = Column(String(500), nullable=False)
|
||||
doc_url = Column(String(500), default="")
|
||||
# 认证方式: none / api_key / bearer / basic
|
||||
auth_type = Column(String(20), default="none")
|
||||
# 加密存储的API Key
|
||||
api_key_encrypted = Column(Text, default="")
|
||||
# API Key 放在哪个请求头中, 如 Authorization, X-API-Key
|
||||
api_key_header = Column(String(100), default="Authorization")
|
||||
# 健康检查
|
||||
health_check_url = Column(String(500), default="")
|
||||
last_check_time = Column(DateTime(timezone=True), nullable=True)
|
||||
last_check_status = Column(String(20), default="unknown") # ok / error / unknown
|
||||
# 元信息
|
||||
added_by = Column(Integer, ForeignKey("users.id"), nullable=True)
|
||||
tags = Column(String(500), default="") # 逗号分隔
|
||||
call_count = Column(Integer, default=0)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class SharedApiLog(Base):
|
||||
"""API使用日志"""
|
||||
__tablename__ = "shared_api_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
api_id = Column(Integer, ForeignKey("shared_apis.id"), nullable=False, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
||||
action = Column(String(20), default="test") # test / health_check
|
||||
request_url = Column(String(500), default="")
|
||||
response_status = Column(Integer, nullable=True)
|
||||
response_time_ms = Column(Integer, nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
15
backend/models/system_config.py
Normal file
15
backend/models/system_config.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""系统配置模型 - 键值对存储"""
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class SystemConfig(Base):
|
||||
"""系统配置表 - 存储OSS等系统级配置"""
|
||||
__tablename__ = "system_configs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
key = Column(String(100), unique=True, index=True, nullable=False)
|
||||
value = Column(Text, default="")
|
||||
description = Column(String(200), default="")
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
18
backend/models/user.py
Normal file
18
backend/models/user.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""用户模型"""
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Boolean
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
username = Column(String(50), unique=True, index=True, nullable=False)
|
||||
email = Column(String(100), unique=True, index=True, nullable=False)
|
||||
password_hash = Column(String(200), nullable=False)
|
||||
avatar = Column(String(500), default="")
|
||||
is_admin = Column(Boolean, default=False, nullable=False)
|
||||
is_banned = Column(Boolean, default=False, nullable=False)
|
||||
is_approved = Column(Boolean, default=False, nullable=False) # 新用户需管理员审核
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
Reference in New Issue
Block a user