Compare commits
2 Commits
023380d14b
...
detached3
| Author | SHA1 | Date | |
|---|---|---|---|
| 09d78f57a5 | |||
| 8f0d019627 |
7
backend/.dockerignore
Normal file
7
backend/.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
.env
|
||||||
|
.git
|
||||||
|
*.md
|
||||||
|
venv
|
||||||
|
.venv
|
||||||
28
backend/.env.production
Normal file
28
backend/.env.production
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# ACG Blog 生产环境配置
|
||||||
|
# 复制此文件为 .env 并修改对应值
|
||||||
|
|
||||||
|
# 应用配置
|
||||||
|
APP_NAME=ACG Blog
|
||||||
|
APP_VERSION=1.0.0
|
||||||
|
DEBUG=false
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
DB_HOST=postgres
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=postgres
|
||||||
|
DB_NAME=acg_blog
|
||||||
|
|
||||||
|
# Redis 配置
|
||||||
|
REDIS_HOST=redis
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_DB=0
|
||||||
|
|
||||||
|
# JWT 配置 (请修改为随机字符串)
|
||||||
|
SECRET_KEY=your-super-secret-key-change-this-in-production
|
||||||
|
ALGORITHM=HS256
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||||
|
REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||||
|
|
||||||
|
# CORS 配置 (前端域名)
|
||||||
|
BACKEND_CORS_ORIGINS=http://localhost,https://your-domain.com
|
||||||
25
backend/Dockerfile
Normal file
25
backend/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# FastAPI Backend
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 安装系统依赖
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc \
|
||||||
|
libpq-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 复制依赖文件
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
# 安装 Python 依赖
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# 复制应用代码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# 启动命令
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
136
backend/schema.sql
Normal file
136
backend/schema.sql
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
-- ACG Blog 数据库建表脚本
|
||||||
|
-- PostgreSQL
|
||||||
|
-- 运行前请先创建数据库: CREATE DATABASE acg_blog;
|
||||||
|
|
||||||
|
-- 启用 UUID 扩展
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
|
-- ==================== 用户表 ====================
|
||||||
|
CREATE TABLE IF NOT EXISTS "users" (
|
||||||
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"username" VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
"email" VARCHAR(255) UNIQUE NOT NULL,
|
||||||
|
"password_hash" VARCHAR(255) NOT NULL,
|
||||||
|
"avatar" VARCHAR(500),
|
||||||
|
"bio" TEXT,
|
||||||
|
"is_active" BOOLEAN DEFAULT TRUE,
|
||||||
|
"is_superuser" BOOLEAN DEFAULT FALSE,
|
||||||
|
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ==================== 分类表 ====================
|
||||||
|
CREATE TABLE IF NOT EXISTS "categories" (
|
||||||
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"name" VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
"slug" VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
"description" TEXT,
|
||||||
|
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ==================== 标签表 ====================
|
||||||
|
CREATE TABLE IF NOT EXISTS "tags" (
|
||||||
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"name" VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
"slug" VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ==================== 文章表 ====================
|
||||||
|
CREATE TABLE IF NOT EXISTS "posts" (
|
||||||
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"title" VARCHAR(200) NOT NULL,
|
||||||
|
"slug" VARCHAR(200) UNIQUE NOT NULL,
|
||||||
|
"content" TEXT NOT NULL,
|
||||||
|
"summary" TEXT,
|
||||||
|
"cover_image" VARCHAR(500),
|
||||||
|
|
||||||
|
-- 外键关联
|
||||||
|
"author_id" UUID NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
|
||||||
|
"category_id" UUID REFERENCES "categories"("id") ON DELETE SET NULL,
|
||||||
|
|
||||||
|
-- 统计数据
|
||||||
|
"view_count" INTEGER DEFAULT 0,
|
||||||
|
"like_count" INTEGER DEFAULT 0,
|
||||||
|
"comment_count" INTEGER DEFAULT 0,
|
||||||
|
|
||||||
|
-- 状态: draft/published/archived
|
||||||
|
"status" VARCHAR(20) DEFAULT 'draft',
|
||||||
|
|
||||||
|
-- SEO
|
||||||
|
"meta_title" VARCHAR(200),
|
||||||
|
"meta_description" TEXT,
|
||||||
|
|
||||||
|
-- 时间戳
|
||||||
|
"published_at" TIMESTAMP,
|
||||||
|
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 索引
|
||||||
|
CREATE INDEX IF NOT EXISTS "idx_posts_status_published_at" ON "posts"("status", "published_at");
|
||||||
|
CREATE INDEX IF NOT EXISTS "idx_posts_author_status" ON "posts"("author_id", "status");
|
||||||
|
|
||||||
|
-- ==================== 文章标签关联表 ====================
|
||||||
|
CREATE TABLE IF NOT EXISTS "post_tags" (
|
||||||
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"post_id" UUID NOT NULL REFERENCES "posts"("id") ON DELETE CASCADE,
|
||||||
|
"tag_id" UUID NOT NULL REFERENCES "tags"("id") ON DELETE CASCADE,
|
||||||
|
UNIQUE("post_id", "tag_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ==================== 评论表 ====================
|
||||||
|
CREATE TABLE IF NOT EXISTS "comments" (
|
||||||
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
"content" TEXT NOT NULL,
|
||||||
|
"is_approved" BOOLEAN DEFAULT TRUE,
|
||||||
|
|
||||||
|
-- 外键关联
|
||||||
|
"author_id" UUID NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
|
||||||
|
"post_id" UUID NOT NULL REFERENCES "posts"("id") ON DELETE CASCADE,
|
||||||
|
"parent_id" UUID REFERENCES "comments"("id") ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- 时间戳
|
||||||
|
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 索引
|
||||||
|
CREATE INDEX IF NOT EXISTS "idx_comments_post_id" ON "comments"("post_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "idx_comments_author_id" ON "comments"("author_id");
|
||||||
|
|
||||||
|
-- ==================== 初始化数据 ====================
|
||||||
|
|
||||||
|
-- 插入默认分类
|
||||||
|
INSERT INTO "categories" ("name", "slug", "description") VALUES
|
||||||
|
('动漫资讯', 'anime', '最新动漫新闻、番剧更新、业界动态'),
|
||||||
|
('游戏攻略', 'game', '游戏通关指南、角色培养、剧情解析'),
|
||||||
|
('二次元美图', 'pictures', '精选壁纸、Cosplay、插画作品'),
|
||||||
|
('同人创作', 'fanwork', '同人小说、同人绘画、手办模型')
|
||||||
|
ON CONFLICT ("slug") DO NOTHING;
|
||||||
|
|
||||||
|
-- 插入默认标签
|
||||||
|
INSERT INTO "tags" ("name", "slug") VALUES
|
||||||
|
('原神', 'genshin'),
|
||||||
|
('崩坏星穹铁道', 'honkai-star-rail'),
|
||||||
|
('我的世界', 'minecraft'),
|
||||||
|
('EVA', 'evangelion'),
|
||||||
|
('约定的梦幻岛', 'neverland'),
|
||||||
|
('咒术回战', 'jujutsu-kaisen'),
|
||||||
|
('Cosplay', 'cosplay'),
|
||||||
|
('手办', 'figure')
|
||||||
|
ON CONFLICT ("slug") DO NOTHING;
|
||||||
|
|
||||||
|
-- 插入管理员用户 (密码: admin123)
|
||||||
|
-- 密码哈希基于 bcrypt,使用前请替换为实际哈希值
|
||||||
|
INSERT INTO "users" ("username", "email", "password_hash", "is_superuser") VALUES
|
||||||
|
('admin', 'admin@acgblog.com', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/X4.TZND60LMTUBu.K', TRUE)
|
||||||
|
ON CONFLICT ("username") DO NOTHING;
|
||||||
|
|
||||||
|
-- ==================== 注释 ====================
|
||||||
|
COMMENT ON TABLE "users" IS '用户表';
|
||||||
|
COMMENT ON TABLE "categories" IS '文章分类表';
|
||||||
|
COMMENT ON TABLE "tags" IS '文章标签表';
|
||||||
|
COMMENT ON TABLE "posts" IS '文章表';
|
||||||
|
COMMENT ON TABLE "post_tags" IS '文章标签关联表';
|
||||||
|
COMMENT ON TABLE "comments" IS '评论表';
|
||||||
78
docker-compose.yml
Normal file
78
docker-compose.yml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# PostgreSQL 数据库
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: acg_blog_db
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: acg_blog
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
- ./backend/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
networks:
|
||||||
|
- acg_blog_network
|
||||||
|
|
||||||
|
# Redis 缓存
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: acg_blog_redis
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
networks:
|
||||||
|
- acg_blog_network
|
||||||
|
|
||||||
|
# 后端 API
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: acg_blog_backend
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- DB_HOST=postgres
|
||||||
|
- DB_PORT=5432
|
||||||
|
- DB_USER=postgres
|
||||||
|
- DB_PASSWORD=postgres
|
||||||
|
- DB_NAME=acg_blog
|
||||||
|
- REDIS_HOST=redis
|
||||||
|
- REDIS_PORT=6379
|
||||||
|
- SECRET_KEY=your-secret-key-change-in-production
|
||||||
|
- DEBUG=false
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- acg_blog_network
|
||||||
|
|
||||||
|
# 前端 Nginx
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: acg_blog_frontend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- acg_blog_network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
redis_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
acg_blog_network:
|
||||||
|
driver: bridge
|
||||||
69
docker-deploy.md
Normal file
69
docker-deploy.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Docker 部署指南
|
||||||
|
|
||||||
|
## 快速启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动所有服务
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 查看服务状态
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## 服务地址
|
||||||
|
|
||||||
|
| 服务 | 地址 |
|
||||||
|
|------|------|
|
||||||
|
| 前端 | http://localhost |
|
||||||
|
| 后端 API | http://localhost:8000 |
|
||||||
|
| API 文档 | http://localhost:8000/docs |
|
||||||
|
| PostgreSQL | localhost:5432 |
|
||||||
|
| Redis | localhost:6379 |
|
||||||
|
|
||||||
|
## 初始化数据库
|
||||||
|
|
||||||
|
首次启动时,数据库会自动创建表结构和初始数据。
|
||||||
|
|
||||||
|
管理员账户:
|
||||||
|
- 用户名: `admin`
|
||||||
|
- 邮箱: `admin@acgblog.com`
|
||||||
|
- 密码: `admin123`
|
||||||
|
|
||||||
|
**重要**: 请在部署后修改管理员密码!
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 重新构建镜像
|
||||||
|
docker-compose build --no-cache
|
||||||
|
|
||||||
|
# 停止所有服务
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 停止并删除数据卷
|
||||||
|
docker-compose down -v
|
||||||
|
|
||||||
|
# 进入后端容器
|
||||||
|
docker exec -it acg_blog_backend sh
|
||||||
|
|
||||||
|
# 进入数据库
|
||||||
|
docker exec -it acg_blog_db psql -U postgres -d acg_blog
|
||||||
|
```
|
||||||
|
|
||||||
|
## 生产环境部署
|
||||||
|
|
||||||
|
1. 修改 `backend/.env.production` 中的配置:
|
||||||
|
- `SECRET_KEY` - 使用随机字符串
|
||||||
|
- `BACKEND_CORS_ORIGINS` - 改为你的域名
|
||||||
|
|
||||||
|
2. 修改 `docker-compose.yml` 中的端口映射(移除端口暴露,仅通过 nginx 反向代理)
|
||||||
|
|
||||||
|
3. 使用 Nginx 或 Traefik 等反向代理配置 HTTPS
|
||||||
|
|
||||||
|
4. 定期备份数据库:
|
||||||
|
```bash
|
||||||
|
docker exec acg_blog_db pg_dump -U postgres acg_blog > backup.sql
|
||||||
|
```
|
||||||
6
frontend/.dockerignore
Normal file
6
frontend/.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.git
|
||||||
|
.env
|
||||||
|
*.md
|
||||||
|
.vscode
|
||||||
29
frontend/Dockerfile
Normal file
29
frontend/Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Vue 3 Frontend
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制依赖文件
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# 复制源代码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 构建生产版本
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ==================== Nginx 运行阶段 ====================
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# 复制构建产物
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# 复制 Nginx 配置
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
32
frontend/nginx.conf
Normal file
32
frontend/nginx.conf
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip 压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||||||
|
gzip_min_length 1000;
|
||||||
|
|
||||||
|
# 前端路由(SPA)
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API 代理
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend:8000/api/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态资源缓存
|
||||||
|
location /assets/ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
275
readme.md
275
readme.md
@@ -1,124 +1,189 @@
|
|||||||
# 二次元风格博客技术文档
|
# ACG Blog - 二次元风格博客系统
|
||||||
打算自己写个博客博客项目练练手,并把原来博客的东西都搬过去,先把仓库和前端写了
|
|
||||||
|
|
||||||
### 项目基本信息
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/badge/Python-3.11+-blue.svg" alt="Python">
|
||||||
|
<img src="https://img.shields.io/badge/FastAPI-0.110-green.svg" alt="FastAPI">
|
||||||
|
<img src="https://img.shields.io/badge/Vue-3.5-brightgreen.svg" alt="Vue">
|
||||||
|
<img src="https://img.shields.io/badge/TypeScript-5.9-blue.svg" alt="TypeScript">
|
||||||
|
<img src="https://img.shields.io/badge/Docker-Ready-blue.svg" alt="Docker">
|
||||||
|
</p>
|
||||||
|
|
||||||
- **项目名称**:ACG Blog(二次元风格博客)
|
基于 **FastAPI** 与 **Vue 3** 的前后端分离博客系统,主打二次元视觉体验与高性能响应。支持 Markdown 文章发布、访问量统计、分类标签管理、深色模式切换等功能。
|
||||||
- **项目简介**:基于 **FastAPI** 与 **Vue 3** 的前后端分离博客系统,主打二次元视觉体验与高性能响应。支持 Markdown 文章发布、动态看板娘、访问量统计、热搜排行、深色模式切换等特色功能。
|
|
||||||
- **技术栈概览**:
|
|
||||||
- 后端:Python + FastAPI + SupaBase + Tortoise‑ORM + Redis + JWT
|
|
||||||
- 前端:Vue 3 (Vite) + Pinia + Naive UI + Tailwind CSS + GSAP
|
|
||||||
- **系统架构**:**B/S 架构**(Browser/Server,浏览器/服务器架构)
|
|
||||||
- 前端:单页应用(SPA)运行于浏览器
|
|
||||||
- 后端:RESTful API 服务器
|
|
||||||
- 通信协议:HTTP/HTTPS + JSON
|
|
||||||
- **后端架构模式**:**类 MVC 模式**
|
|
||||||
- **Model(模型层)**:`models/` 目录,Tortoise-ORM 数据模型定义
|
|
||||||
- **View(视图层)**:`api/endpoints/` 目录,FastAPI 路由返回 JSON 响应
|
|
||||||
- **Controller(控制器层)**:`api/endpoints/` 中的路由处理函数,协调业务逻辑
|
|
||||||
- **Service(服务层)**:`services/` 目录,封装核心业务(如看板娘互动、统计逻辑)
|
|
||||||
- **Schema(数据传输层)**:`schemas/` 目录,Pydantic 模型校验请求与响应
|
|
||||||
- **CRUD(数据操作层)**:`crud/` 目录,封装数据库增删改查逻辑,辅助 Model 层
|
|
||||||
- **Core(核心配置)**:`core/` 目录,管理环境变量、日志、JWT 安全等基础设施
|
|
||||||
- **开发状态**:规划中
|
|
||||||
|
|
||||||
> 详细技术选型及项目结构请参见下文。
|
## 技术栈
|
||||||
|
|
||||||
### 后端技术栈
|
### 后端
|
||||||
|
| 技术 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| FastAPI | 高性能异步 Web 框架 |
|
||||||
|
| Tortoise-ORM | 异步 ORM,支持 PostgreSQL |
|
||||||
|
| PostgreSQL | 关系型数据库 |
|
||||||
|
| Redis | 缓存与会话存储 |
|
||||||
|
| JWT | 无状态身份认证 |
|
||||||
|
| Pydantic | 数据验证 |
|
||||||
|
| Loguru | 日志处理 |
|
||||||
|
|
||||||
| **模块** | **技术选型** | **说明** |
|
### 前端
|
||||||
| -------------- | --------------------- | ------------------------------------------------------------ |
|
| 技术 | 说明 |
|
||||||
| **核心框架** | **FastAPI** | 高性能、原生异步(Async),满足二次元素材(图片/视频)的高并发加载需求。 |
|
|------|------|
|
||||||
| **数据库** | **SupaBace** | **内置 Auth**,支持第三方登录 (Github/Google) |
|
| Vue 3 | 组合式 API (Script Setup) |
|
||||||
| **ORM (异步)** | **Tortoise-ORM** | 语法类似 Django,且原生支持异步操作。 |
|
| Vite | 快速构建工具 |
|
||||||
| **缓存/任务** | **Redis** | 用于文章点击量统计、热搜排行以及 Session 存储。 |
|
| TypeScript | 类型安全 |
|
||||||
| **认证** | **JWT (python-jose)** | 无状态认证,方便前后端分离部署。 |
|
| Pinia | 状态管理 |
|
||||||
| **数据校验** | **Pydantic v2** | 确保前端传来的数据不会让后端“炸掉”。 |
|
| Naive UI | UI 组件库 |
|
||||||
| **日志** | **Loguru** | 极简且强大的异步日志处理,便于排错 |
|
| Tailwind CSS | 样式引擎 |
|
||||||
|
| Axios | HTTP 客户端 |
|
||||||
|
|
||||||
### 前端技术栈 (The Visuals)
|
## 项目结构
|
||||||
|
|
||||||
| **模块** | **技术选型** | **说明** |
|
```
|
||||||
| ------------- | ---------------- | ------------------------------------------------------------ |
|
├── backend/ # FastAPI 后端
|
||||||
| **框架** | **Vue 3 (Vite)** | 组合式 API (Script Setup) 开发体验极佳,构建速度快。 |
|
|
||||||
| **状态管理** | **Pinia** | 轻量、简洁,存储用户偏好(如:深色/浅色模式、看板娘状态)。 |
|
|
||||||
| **UI 组件库** | **Naive UI** | 设计感极强,配置主题非常自由,适合定制二次元配色。 |
|
|
||||||
| **样式引擎** | **Tailwind CSS** | 极其方便编写自定义 UI。你可以轻松实现“毛玻璃”、“卡片悬浮”等特效。 |
|
|
||||||
| **编辑器** | **V-MD-Editor** | 基于 Vue 3 的 Markdown 编辑器,支持预览、代码高亮和 LaTeX 公式。 |
|
|
||||||
| **动画库** | **GSAP** | 强大的动效库。二次元风格需要细腻的入场和交互动画。 |
|
|
||||||
|
|
||||||
### 预计项目结构
|
|
||||||
|
|
||||||
```bash
|
|
||||||
acg-blog/
|
|
||||||
├── backend/ # FastAPI 后端项目
|
|
||||||
│ ├── app/
|
│ ├── app/
|
||||||
│ │ ├── api/ # 接口层 (v1, v2...)
|
│ │ ├── api/endpoints/ # API 端点 (auth, posts, comments, users)
|
||||||
│ │ │ ├── endpoints/ # 具体业务接口 (posts.py, users.py, etc.)
|
│ │ ├── core/ # 核心配置 (config, security, database, logger)
|
||||||
│ │ │ └── api.py # 路由汇总
|
│ │ ├── crud/ # 数据库增删改查
|
||||||
│ │ ├── core/ # 核心配置
|
│ │ ├── models/ # Tortoise-ORM 数据模型
|
||||||
│ │ │ ├── config.py # 环境变量与全局配置
|
|
||||||
│ │ │ ├── logger.py # 日志拦截与配置
|
|
||||||
│ │ │ └── security.py # JWT 与权限相关
|
|
||||||
│ │ ├── crud/ # 数据库增删改查逻辑
|
|
||||||
│ │ ├── db/ # 数据库连接与初始化
|
|
||||||
│ │ ├── models/ # Tortoise-ORM 数据库模型
|
|
||||||
│ │ ├── schemas/ # Pydantic 数据验证模型
|
│ │ ├── schemas/ # Pydantic 数据验证模型
|
||||||
│ │ ├── services/ # 业务服务逻辑 (如:看板娘互动 API)
|
│ │ └── main.py # 应用入口
|
||||||
│ │ └── main.py # 后端入口
|
│ ├── Dockerfile # 后端容器配置
|
||||||
│ ├── logs/ # 日志存储目录 (自动生成 .log 文件)
|
│ ├── schema.sql # 数据库建表脚本
|
||||||
│ ├── static/ # 静态资源 (用户上传的插图、头像)
|
│ └── requirements.txt # Python 依赖
|
||||||
│ ├── tests/ # 测试用例
|
│
|
||||||
│ ├── .env # 敏感配置文件
|
├── frontend/ # Vue 3 前端
|
||||||
│ ├── pyproject.toml # Poetry 配置或使用 requirements
|
|
||||||
│ └── requirements.txt # 依赖清单
|
|
||||||
├── frontend/ # Vue 3 前端项目 (Vite)
|
|
||||||
│ ├── public/ # 公共静态资源 (Live2D 模型、Favicon)
|
|
||||||
│ ├── src/
|
│ ├── src/
|
||||||
│ │ ├── api/ # Axios 接口封装
|
│ │ ├── api/ # Axios 接口封装
|
||||||
│ │ ├── assets/ # 样式、二次元字体、插画
|
│ │ ├── components/ # 公共组件
|
||||||
│ │ ├── components/ # 组件 (看板娘、播放器、卡片)
|
│ │ ├── views/ # 页面视图
|
||||||
│ │ ├── router/ # 路由配置
|
|
||||||
│ │ ├── store/ # Pinia 状态管理
|
│ │ ├── store/ # Pinia 状态管理
|
||||||
│ │ ├── views/ # 页面布局 (首页、文章页、归档)
|
│ │ ├── router/ # 路由配置
|
||||||
│ │ ├── App.vue # 根组件
|
│ │ └── types/ # TypeScript 类型定义
|
||||||
│ │ └── main.ts # 前端入口
|
│ ├── Dockerfile # 前端容器配置
|
||||||
│ ├── tailwind.config.js # Tailwind CSS 配置
|
│ └── nginx.conf # Nginx 配置
|
||||||
│ └── package.json # 前端依赖
|
│
|
||||||
├── docker-compose.yml # 全栈 Docker 编排
|
├── docker-compose.yml # Docker 编排
|
||||||
└── README.md
|
├── schema.sql # 数据库建表脚本
|
||||||
|
└── docker-deploy.md # 部署文档
|
||||||
```
|
```
|
||||||
|
|
||||||
### 后端requirements
|
## 快速开始
|
||||||
|
|
||||||
|
### 环境要求
|
||||||
|
- Python 3.11+
|
||||||
|
- Node.js 18+
|
||||||
|
- PostgreSQL 14+
|
||||||
|
- Redis 7+ (可选)
|
||||||
|
|
||||||
|
### 本地开发
|
||||||
|
|
||||||
|
**1. 克隆项目**
|
||||||
|
```bash
|
||||||
|
git clone <repository-url>
|
||||||
|
cd acg-blog
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. 启动后端**
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
# 创建虚拟环境
|
||||||
|
python -m venv venv
|
||||||
|
source venv/bin/activate # Linux/Mac
|
||||||
|
# 或 venv\Scripts\activate # Windows
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# 配置环境变量
|
||||||
|
cp .env.example .env # 修改数据库连接信息
|
||||||
|
|
||||||
|
# 初始化数据库 (确保 PostgreSQL 运行中)
|
||||||
|
psql -U postgres -c "CREATE DATABASE acg_blog;"
|
||||||
|
psql -U postgres -d acg_blog -f schema.sql
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
uvicorn main:app --reload --port 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. 启动前端**
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 启动开发服务器
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. 访问应用**
|
||||||
|
- 前端: http://localhost:5173
|
||||||
|
- 后端 API: http://localhost:8000
|
||||||
|
- API 文档: http://localhost:8000/docs
|
||||||
|
|
||||||
|
### Docker 部署
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Web 框架
|
# 启动所有服务
|
||||||
fastapi==0.110.0
|
docker-compose up -d
|
||||||
uvicorn[standard]==0.27.1
|
|
||||||
|
|
||||||
# 数据库与异步 ORM
|
# 查看服务状态
|
||||||
tortoise-orm==0.20.0
|
docker-compose ps
|
||||||
aerich==0.7.2 # 数据库迁移工具
|
|
||||||
asyncpg==0.29.0 # PostgreSQL 驱动
|
|
||||||
aioredis==2.0.1 # Redis 驱动
|
|
||||||
|
|
||||||
# 日志系统
|
|
||||||
loguru==0.7.2 # 极简且强大的异步日志处理
|
|
||||||
|
|
||||||
# 配置与安全
|
|
||||||
pydantic[email]==2.6.3 # 包含 Email 校验
|
|
||||||
pydantic-settings==2.2.1 # 处理 .env 环境变量
|
|
||||||
python-jose[cryptography]==3.3.0 # JWT
|
|
||||||
passlib[bcrypt]==1.7.4 # 密码哈希
|
|
||||||
|
|
||||||
# 业务
|
|
||||||
python-multipart==0.0.9 # 处理表单与文件上传
|
|
||||||
mistune==3.0.2 # 快速 Markdown 解析
|
|
||||||
pillow==10.2.0 # 处理图片
|
|
||||||
httpx==0.27.0 # 异步 HTTP 请求
|
|
||||||
|
|
||||||
# 开发与部署
|
|
||||||
python-dotenv==1.0.1
|
|
||||||
gunicorn==21.2.0 # 生产环境容器部署使用
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
访问 http://localhost 即可使用。
|
||||||
|
|
||||||
|
## API 接口
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| POST | /api/v1/auth/register | 用户注册 |
|
||||||
|
| POST | /api/v1/auth/login | 用户登录 |
|
||||||
|
| POST | /api/v1/auth/refresh | 刷新 Token |
|
||||||
|
| GET | /api/v1/auth/me | 获取当前用户 |
|
||||||
|
| GET | /api/v1/posts | 获取文章列表 |
|
||||||
|
| GET | /api/v1/posts/{id} | 获取文章详情 |
|
||||||
|
| POST | /api/v1/posts | 创建文章 |
|
||||||
|
| PUT | /api/v1/posts/{id} | 更新文章 |
|
||||||
|
| DELETE | /api/v1/posts/{id} | 删除文章 |
|
||||||
|
| GET | /api/v1/categories | 获取分类列表 |
|
||||||
|
| GET | /api/v1/tags | 获取标签列表 |
|
||||||
|
| GET | /api/v1/comments/post/{id} | 获取文章评论 |
|
||||||
|
|
||||||
|
## 默认账户
|
||||||
|
|
||||||
|
- 用户名: `admin`
|
||||||
|
- 邮箱: `admin@acgblog.com`
|
||||||
|
- 密码: `admin123`
|
||||||
|
|
||||||
|
**请在部署后立即修改管理员密码!**
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- [x] 用户认证 (JWT)
|
||||||
|
- [x] 文章管理 (CRUD)
|
||||||
|
- [x] 分类与标签
|
||||||
|
- [x] Markdown 编辑器
|
||||||
|
- [x] 评论系统
|
||||||
|
- [x] 浏览量统计
|
||||||
|
- [x] 深色/浅色模式
|
||||||
|
- [x] 响应式设计
|
||||||
|
- [x] Docker 部署
|
||||||
|
|
||||||
|
## 开发说明
|
||||||
|
|
||||||
|
### 前端组件
|
||||||
|
- `Navbar.vue` - 顶部导航栏
|
||||||
|
- `Hero.vue` - 首页横幅
|
||||||
|
- `PostCard.vue` - 文章卡片
|
||||||
|
- `Sidebar.vue` - 侧边栏
|
||||||
|
- `Footer.vue` - 页脚
|
||||||
|
|
||||||
|
### 管理后台
|
||||||
|
- `/admin/dashboard` - 仪表盘
|
||||||
|
- `/admin/posts` - 文章管理
|
||||||
|
- `/admin/categories` - 分类管理
|
||||||
|
- `/admin/tags` - 标签管理
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|||||||
Reference in New Issue
Block a user