From 16baff934a833f4629346b30cca00a430921a5e0 Mon Sep 17 00:00:00 2001 From: bwstudio Date: Thu, 21 May 2026 20:41:45 +0800 Subject: [PATCH] feat(api): add database models --- .claude/settings.local.json | 11 + api/app/models/__init__.py | 5 + api/app/models/category.py | 33 +++ api/app/models/joke.py | 25 ++ api/app/models/user.py | 14 ++ ...2026-05-21-joke-platform-implementation.md | 230 ++++++++++++++++++ 6 files changed, 318 insertions(+) create mode 100644 .claude/settings.local.json create mode 100644 api/app/models/__init__.py create mode 100644 api/app/models/category.py create mode 100644 api/app/models/joke.py create mode 100644 api/app/models/user.py create mode 100644 docs/superpowers/plans/2026-05-21-joke-platform-implementation.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..d5b88f4 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Skill(brainstorming)", + "Skill(writing-plans)", + "Skill(subagent-driven-development)", + "Bash(git add *)", + "Bash(git commit *)" + ] + } +} diff --git a/api/app/models/__init__.py b/api/app/models/__init__.py new file mode 100644 index 0000000..41802b5 --- /dev/null +++ b/api/app/models/__init__.py @@ -0,0 +1,5 @@ +from app.models.joke import Joke +from app.models.category import JokeType, JokeCrowd +from app.models.user import AdminUser + +__all__ = ["Joke", "JokeType", "JokeCrowd", "AdminUser"] \ No newline at end of file diff --git a/api/app/models/category.py b/api/app/models/category.py new file mode 100644 index 0000000..e82d40d --- /dev/null +++ b/api/app/models/category.py @@ -0,0 +1,33 @@ +from sqlalchemy import Column, Integer, String, DateTime +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func + +from app.database import Base + + +class JokeType(Base): + """笑话类型表模型""" + __tablename__ = "joke_types" + + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String(50), nullable=False) + icon = Column(String(50), nullable=True) + sort_order = Column(Integer, default=0) + created_at = Column(DateTime, default=func.now()) + + # Relationships + jokes = relationship("Joke", back_populates="type") + + +class JokeCrowd(Base): + """笑话人群表模型""" + __tablename__ = "joke_crowds" + + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String(50), nullable=False) + icon = Column(String(50), nullable=True) + sort_order = Column(Integer, default=0) + created_at = Column(DateTime, default=func.now()) + + # Relationships + jokes = relationship("Joke", back_populates="crowd") \ No newline at end of file diff --git a/api/app/models/joke.py b/api/app/models/joke.py new file mode 100644 index 0000000..3233be8 --- /dev/null +++ b/api/app/models/joke.py @@ -0,0 +1,25 @@ +from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func + +from app.database import Base + + +class Joke(Base): + """笑话表模型""" + __tablename__ = "jokes" + + id = Column(Integer, primary_key=True, autoincrement=True) + title = Column(String(200), nullable=False) + content = Column(Text, nullable=False) + type_id = Column(Integer, ForeignKey("joke_types.id"), nullable=True) + crowd_id = Column(Integer, ForeignKey("joke_crowds.id"), nullable=True) + status = Column(String(20), default="pending") + view_count = Column(Integer, default=0) + like_count = Column(Integer, default=0) + created_at = Column(DateTime, default=func.now()) + updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) + + # Relationships + type = relationship("JokeType", back_populates="jokes") + crowd = relationship("JokeCrowd", back_populates="jokes") \ No newline at end of file diff --git a/api/app/models/user.py b/api/app/models/user.py new file mode 100644 index 0000000..7e34312 --- /dev/null +++ b/api/app/models/user.py @@ -0,0 +1,14 @@ +from sqlalchemy import Column, Integer, String, DateTime +from sqlalchemy.sql import func + +from app.database import Base + + +class AdminUser(Base): + """管理员用户表模型""" + __tablename__ = "admin_users" + + id = Column(Integer, primary_key=True, autoincrement=True) + username = Column(String(50), unique=True, nullable=False) + password_hash = Column(String(255), nullable=False) + created_at = Column(DateTime, default=func.now()) \ No newline at end of file diff --git a/docs/superpowers/plans/2026-05-21-joke-platform-implementation.md b/docs/superpowers/plans/2026-05-21-joke-platform-implementation.md new file mode 100644 index 0000000..e6d7986 --- /dev/null +++ b/docs/superpowers/plans/2026-05-21-joke-platform-implementation.md @@ -0,0 +1,230 @@ +# 笑话大全平台 - 实施计划 + +> **推荐执行方式:** 使用 subagent-driven-development,按任务逐步实现 + +**目标:** 完成笑话大全平台一期建设(前台网站 + 后台管理 + 后端 API) + +**技术栈:** +- 后端: Python FastAPI + SQLite + SQLAlchemy +- 前端: Vue3 + Vite + Element Plus + Axios +- 状态管理: Pinia +- 路由: Vue Router + +--- + +## 阶段一:后端 API (api/) + +### Task 1: 项目初始化 +- 创建: `api/requirements.txt` +- 创建: `api/main.py` - FastAPI 入口 +- 创建: `api/app/config.py` - 配置管理 +- 创建: `api/app/database.py` - SQLite 连接 + +```bash +# 依赖 +fastapi==0.109.0 +uvicorn[standard]==0.27.0 +sqlalchemy==2.0.25 +pydantic==2.5.3 +python-jose[cryptography]==3.3.0 +passlib[bcrypt]==1.7.4 +python-multipart==0.0.6 +``` + +### Task 2: 数据库模型 +- 创建: `api/app/models/__init__.py` +- 创建: `api/app/models/joke.py` - Joke 模型 +- 创建: `api/app/models/category.py` - Type/Crowd 模型 +- 创建: `api/app/models/user.py` - AdminUser 模型 + +### Task 3: Pydantic Schemas +- 创建: `api/app/schemas/__init__.py` +- 创建: `api/app/schemas/joke.py` - Joke 请求/响应模型 +- 创建: `api/app/schemas/category.py` - Category 模型 +- 创建: `api/app/schemas/auth.py` - 登录/Token 模型 + +### Task 4: 路由实现 +- 创建: `api/app/routers/__init__.py` +- 创建: `api/app/routers/jokes.py` - 笑话 CRUD 路由 +- 创建: `api/app/routers/categories.py` - 分类路由 +- 创建: `api/app/routers/auth.py` - 认证路由 +- 创建: `api/app/routers/admin.py` - 管理后台路由 + +### Task 5: 数据库初始化与种子数据 +- 创建: `api/init_db.py` - 初始化表和示例数据 + +--- + +## 阶段二:后台管理前端 (admin/) + +### Task 6: 项目初始化 +- 创建: `admin/package.json` +- 创建: `admin/vite.config.js` +- 创建: `admin/index.html` +- 创建: `admin/src/main.js` +- 创建: `admin/src/App.vue` + +### Task 7: 路由和状态管理 +- 创建: `admin/src/router/index.js` - 路由配置 +- 创建: `admin/src/stores/auth.js` - 认证状态 +- 创建: `admin/src/stores/joke.js` - 笑话状态 + +### Task 8: API 封装 +- 创建: `admin/src/api/request.js` - Axios 封装 +- 创建: `admin/src/api/joke.js` - 笑话 API +- 创建: `admin/src/api/category.js` - 分类 API +- 创建: `admin/src/api/auth.js` - 认证 API + +### Task 9: 登录页 +- 创建: `admin/src/views/login/index.vue` + +### Task 10: 布局和导航 +- 创建: `admin/src/layout/index.vue` +- 创建: `admin/src/layout/components/Sidebar.vue` + +### Task 11: 仪表盘 +- 创建: `admin/src/views/dashboard/index.vue` + +### Task 12: 笑话管理 - 列表 +- 创建: `admin/src/views/joke/List.vue` - 列表 + 分页 + 筛选 + +### Task 13: 笑话管理 - 编辑 +- 创建: `admin/src/views/joke/Edit.vue` - 添加/编辑表单 + +### Task 14: 分类管理 +- 创建: `admin/src/views/category/Type.vue` - 类型管理 +- 创建: `admin/src/views/category/Crowd.vue` - 人群管理 + +--- + +## 阶段三:前台展示前端 (web/) + +### Task 15: 项目初始化 +- 创建: `web/package.json` +- 创建: `web/vite.config.js` +- 创建: `web/index.html` +- 创建: `web/src/main.js` +- 创建: `web/src/App.vue` + +### Task 16: 路由和状态管理 +- 创建: `web/src/router/index.js` +- 创建: `web/src/stores/joke.js` + +### Task 17: API 封装 +- 创建: `web/src/api/request.js` +- 创建: `web/src/api/joke.js` +- 创建: `web/src/api/category.js` + +### Task 18: 首页 +- 创建: `web/src/views/home/index.vue` - 笑话列表 +- 创建: `web/src/views/home/components/JokeCard.vue` - 卡片组件 + +### Task 19: 分类筛选页 +- 创建: `web/src/views/category/index.vue` + +### Task 20: 笑话详情页 +- 创建: `web/src/views/detail/index.vue` + +### Task 21: 搜索页 +- 创建: `web/src/views/search/index.vue` + +### Task 22: 通用组件 +- 创建: `web/src/components/Header.vue` - 页头 +- 创建: `web/src/components/Footer.vue` - 页脚 + +--- + +## 验证方式 + +1. **后端验证:** + ```bash + cd api + pip install -r requirements.txt + python init_db.py + uvicorn main:app --reload + # 访问 http://localhost:8000/docs 测试 API + ``` + +2. **后台管理验证:** + ```bash + cd admin + npm install + npm run dev + # 登录后测试各项管理功能 + ``` + +3. **前台验证:** + ```bash + cd web + npm install + npm run dev + # 浏览笑话列表、分类筛选、搜索等功能 + ``` + +--- + +## 文件清单汇总 + +**后端 API (api/):** +``` +api/ +├── requirements.txt +├── main.py +├── init_db.py +└── app/ + ├── __init__.py + ├── config.py + ├── database.py + ├── models/ + │ ├── __init__.py + │ ├── joke.py + │ ├── category.py + │ └── user.py + ├── schemas/ + │ ├── __init__.py + │ ├── joke.py + │ ├── category.py + │ └── auth.py + └── routers/ + ├── __init__.py + ├── jokes.py + ├── categories.py + ├── auth.py + └── admin.py +``` + +**后台管理 (admin/):** +``` +admin/ +├── package.json +├── vite.config.js +├── index.html +└── src/ + ├── main.js + ├── App.vue + ├── api/ + ├── stores/ + ├── router/ + ├── layout/ + └── views/ +``` + +**前台展示 (web/):** +``` +web/ +├── package.json +├── vite.config.js +├── index.html +└── src/ + ├── main.js + ├── App.vue + ├── api/ + ├── stores/ + ├── router/ + ├── components/ + └── views/ + ├── home/ + ├── category/ + ├── detail/ + └── search/ +``` \ No newline at end of file