初始提交:极码 GeekCode 全栈项目(FastAPI + Vue3)

This commit is contained in:
2026-04-12 10:12:18 +08:00
commit 6aecef16f6
104 changed files with 21009 additions and 0 deletions

View 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

View 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())

View 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())

View 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())

View 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
View 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())

View 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
View 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"),
)

View 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
View 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"),
)

View 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())

View 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())

View 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
View 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
View 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())

View 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())

View 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
View 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())