# 二次元博客 **Repository Path**: crrzyboy/anime-blog ## Basic Information - **Project Name**: 二次元博客 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-07-25 - **Last Updated**: 2025-08-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 二次元博客 #### 介绍 #### 软件架构 **一、整体架构概览** 系统采用前后端分离架构,前端负责页面展示与用户交互,后端提供 API 接口处理业务逻辑,通过 HTTP/HTTPS 协议实现数据通信。整体架构图如下: 用户 → 前端层(浏览器/移动端) → API服务层(Django REST Framework) → 数据持久层(数据库) **二、各层级详细设计** 1. 前端层(用户界面层) 核心职责:负责页面渲染、用户交互、数据展示,以及与后端 API 的通信。 技术实现: 基于 HTML5、Tailwind CSS 构建页面结构与样式,通过自定义工具类实现动画效果(如流星动画、卡片悬停); 使用原生 JavaScript 实现交互逻辑(导航栏滚动效果、移动端菜单切换、平滑滚动); 集成第三方资源:live2d-widget(看板娘插件)、font-awesome(图标库)增强视觉体验; 通过 AJAX/ Fetch API 调用后端 API,实现数据的获取与提交(如文章列表、评论、图片上传)。 核心页面: 首页(含导航、英雄区)、关于页(当前实现)、热门页、文章详情页、分类页等; 响应式设计:适配桌面端 / 移动端,通过 Tailwind 的md:/lg:前缀实现不同屏幕尺寸的布局调整。 2. API 服务层(后端逻辑层) 核心职责:处理前端请求、实现业务逻辑、数据验证、权限控制,并与数据库交互。 技术栈:Django + Django REST Framework(DRF)。 核心模块: 模块 功能说明 核心视图 / 类 用户认证模块 处理注册、登录、登出、个人信息查询,实现用户身份验证与权限管理。 UserRegistrationView、UserLoginView等 文章管理模块 文章的 CRUD(创建、查询、更新、删除),支持按作者、分类、关键词筛选。 ArticleListView、ArticleDetailView 互动功能模块 文章点赞、评论管理,实现用户与内容的交互。 LikeArticleView、CommentListView 媒体上传模块 处理图片上传,生成唯一文件名避免冲突,支持关联到具体文章。 ImageUploadView 分类管理模块 文章分类的 CRUD,用于内容归类与筛选。 CategoryListView、CategoryDetailView 页面视图模块 提供基础页面渲染(首页、关于页等),作为前端入口。 index、about、hot 核心技术特性: 权限控制:通过 DRF 的permissions类实现权限管理(如登录用户可创建文章,匿名用户仅可查询); 序列化:使用 DRF 的Serializer将数据库模型转换为 JSON 格式(如ArticleSerializer、UserSerializer); 请求处理:支持 GET(查询)、POST(创建)、PUT/PATCH(更新)、DELETE(删除)等 HTTP 方法,符合 RESTful 规范; 数据验证:在视图层和序列化器中实现数据合法性校验(如登录时检查账号密码是否为空)。 3. 数据持久层(存储层) 核心职责:负责数据的持久化存储,支持 API 服务层的数据读写操作。 技术实现: 数据库:默认使用 Django 内置的 SQLite(开发环境),生产环境可切换为 MySQL/PostgreSQL; 数据模型:根据后端视图反推,核心模型包括: User:用户信息(用户名、密码、头像等); Article:文章信息(标题、内容、作者、分类、发布时间等); Category:文章分类(分类名称、描述等); Comment:评论(关联文章、关联用户、评论内容等); Like:点赞记录(关联文章、关联用户,用于去重); Image:图片(文件路径、关联文章等)。 **三、数据交互流程** 以 “用户发布带图片的文章” 为例,各层级交互流程如下: 前端:用户在编辑页面填写文章标题、内容,选择分类,上传图片,点击 “发布”; 前端→API 层:通过 POST 请求将文章数据(含分类 ID)发送至ArticleListView,同时通过ImageUploadView上传图片(携带文章 ID); API 层: 验证用户登录状态(未登录则返回 401 错误); 验证文章数据合法性(如标题不为空); 创建Article记录(关联作者、分类); 处理图片上传,生成唯一文件名,创建Image记录(关联文章); 数据层:将文章和图片信息写入数据库; API 层→前端:返回创建成功的文章数据(含图片 URL); 前端:显示 “发布成功” 提示,跳转到文章详情页。 #### 安装教程 1. git clone 项目, 安装依赖。 2. 创建表:create table blog_api_category ( id int auto_increment primary key, name varchar(100) not null comment '分类名称', description text null comment '分类描述', created_at datetime default CURRENT_TIMESTAMP null, updated_at datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP, constraint unique_category_name unique (name) ) comment '文章分类表' charset = utf8mb4; create table blog_api_project ( id int auto_increment comment '项目ID(自增主键)' primary key, name varchar(100) not null comment '项目名称', description text null comment '项目描述', owner_id varchar(36) null comment '项目负责人ID', is_active tinyint(1) default 1 not null comment '是否激活(1-激活,0-禁用)', last_executed_at datetime null comment '最后执行时间', created_at datetime default CURRENT_TIMESTAMP not null comment '创建时间', updated_at datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', constraint uk_project_name unique (name) ) comment '接口自动化项目表' charset = utf8mb4; create table blog_api_connection ( id int auto_increment comment '连接ID(自增主键)' primary key, project_id int not null comment '所属项目ID(外键)', source_node_type enum ('interface', 'extractor') not null comment '源节点类型', source_node_id int not null comment '源节点ID', target_node_type enum ('interface', 'extractor') not null comment '目标节点类型', target_node_id int not null comment '目标节点ID', created_at datetime default CURRENT_TIMESTAMP not null, constraint uk_connection_relation unique (source_node_type, source_node_id, target_node_type, target_node_id), constraint fk_connection_project foreign key (project_id) references blog_api_project (id) on delete cascade ) comment '节点连接关系表' charset = utf8mb4; create index idx_connection_project on blog_api_connection (project_id); create table blog_api_execution ( id varchar(36) default (uuid()) not null comment '执行记录ID(UUID)' primary key, project_id int not null comment '所属项目ID(外键)', status enum ('running', 'success', 'failed') default 'running' not null comment '执行状态', trigger_type enum ('manual', 'schedule') default 'manual' not null comment '触发方式', triggered_by varchar(36) null comment '触发人ID', start_time datetime default CURRENT_TIMESTAMP not null comment '开始时间', end_time datetime null comment '结束时间', execution_time decimal(10, 2) null comment '执行耗时(秒)', total_nodes int default 0 not null comment '总节点数', success_nodes int default 0 not null comment '成功节点数', failed_nodes int default 0 not null comment '失败节点数', log text null comment '执行日志摘要', constraint fk_execution_project foreign key (project_id) references blog_api_project (id) on delete cascade ) comment '链路执行记录表' charset = utf8mb4; create index idx_execution_project on blog_api_execution (project_id); create index idx_execution_status on blog_api_execution (status); create table blog_api_executionresult ( id varchar(36) default (uuid()) not null comment '结果ID(UUID)' primary key, execution_id varchar(36) not null comment '所属执行记录ID(外键)', node_type enum ('interface', 'extractor') not null comment '节点类型', node_id int not null comment '节点ID', node_name varchar(100) null comment '节点名称', status varchar(50) default 'pending' not null comment '执行状态', request json null comment '实际发送的请求数据', response json null comment '接口响应(接口节点)', extracted_value text null comment '提取的值(提取器节点)', error_message text null comment '错误信息(失败时)', duration decimal(10, 2) null comment '执行耗时(秒)', execution_order int not null comment '执行顺序', start_time datetime default CURRENT_TIMESTAMP not null comment '节点开始时间', end_time datetime null comment '节点结束时间', project_id int not null comment '关联的项目ID', log text null comment '执行详细日志', total_nodes int null comment '执行的总节点数量', success_nodes int null comment '执行成功的节点数量', failed_nodes int null comment '执行失败的节点数量', execution_time datetime null comment '执行时间(记录执行开始的时间)', constraint fk_executionresult_project foreign key (project_id) references blog_api_project (id) on delete cascade, constraint fk_result_execution foreign key (execution_id) references blog_api_execution (id) on delete cascade ) comment '节点执行结果表' charset = utf8mb4; create index idx_result_execution on blog_api_executionresult (execution_id); create table blog_api_extractornode ( id int auto_increment comment '提取器节点ID(自增主键)' primary key, project_id int not null comment '所属项目ID(外键)', json_path varchar(255) not null comment 'JSON提取路径', variable_name varchar(50) not null comment '提取后变量名', default_value text null comment '提取失败时的默认值', required tinyint(1) default 0 not null comment '是否为必需项(1-是,0-否)', x int not null comment '画布X坐标', y int not null comment '画布Y坐标', created_at datetime default CURRENT_TIMESTAMP not null, updated_at datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP, constraint fk_extractor_project foreign key (project_id) references blog_api_project (id) on delete cascade ) comment '提取器节点表' charset = utf8mb4; create index idx_extractor_project on blog_api_extractornode (project_id); create table blog_api_interfacenode ( id int auto_increment comment '接口节点ID(自增主键)' primary key, project_id int not null comment '所属项目ID(外键)', name varchar(100) null comment '节点名称', url text not null comment '请求URL', method varchar(10) not null comment '请求方法(GET/POST等)', headers json null comment '请求头(JSON格式)', body json null comment '请求体(JSON格式)', timeout int default 30 not null comment '超时时间(秒)', retry_count int default 0 not null comment '失败重试次数', enabled tinyint(1) default 1 not null comment '是否启用(1-启用,0-禁用)', assertions json null comment '断言规则(JSON格式)', x int not null comment '画布X坐标', y int not null comment '画布Y坐标', created_at datetime default CURRENT_TIMESTAMP not null, updated_at datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP, constraint fk_interface_project foreign key (project_id) references blog_api_project (id) on delete cascade ) comment '接口节点表' charset = utf8mb4; create index idx_interface_project on blog_api_interfacenode (project_id); create table blog_api_user ( id bigint auto_increment comment '主键ID' primary key, password varchar(128) not null comment '加密后的密码', last_login datetime(6) null comment '最后登录时间', is_superuser tinyint(1) not null comment '是否为超级管理员', username varchar(150) not null comment '用户名(唯一)', first_name varchar(150) not null comment '名', last_name varchar(150) not null comment '姓', email varchar(254) not null comment '邮箱', is_staff tinyint(1) not null comment '是否为管理员(可登录后台)', is_active tinyint(1) not null comment '账号是否激活', date_joined datetime(6) not null comment '注册时间', avatar varchar(100) null comment '头像图片路径(可选)', bio longtext null comment '个人简介(可选)', constraint username unique (username) comment '用户名唯一索引' ) comment '自定义用户表' charset = utf8mb4; create table blog_api_article ( id bigint auto_increment primary key, title varchar(200) not null, content longtext not null, created_at datetime(6) default CURRENT_TIMESTAMP(6) not null, updated_at datetime(6) default CURRENT_TIMESTAMP(6) not null on update CURRENT_TIMESTAMP(6), cover_image varchar(100) null, author_id bigint not null, category_id int null comment '分类ID,关联blog_api_category表', constraint blog_api_article_author_id_12345678_fk_blog_api_user_id foreign key (author_id) references blog_api_user (id) on delete cascade, constraint fk_article_category foreign key (category_id) references blog_api_category (id) on delete set null ) charset = utf8mb4; create index blog_api_article_author_id_12345678 on blog_api_article (author_id); create table blog_api_comment ( id bigint auto_increment primary key, content text not null, created_at datetime(6) default CURRENT_TIMESTAMP(6) not null, updated_at datetime(6) default CURRENT_TIMESTAMP(6) not null on update CURRENT_TIMESTAMP(6), article_id bigint not null, user_id bigint not null, parent_comment_id bigint null, constraint blog_api_comment_article_id_12345678_fk_blog_api_article_id foreign key (article_id) references blog_api_article (id) on delete cascade, constraint blog_api_comment_user_id_12345678_fk_blog_api_user_id foreign key (user_id) references blog_api_user (id) on delete cascade, constraint fk_blog_api_comment_parent_comment_id foreign key (parent_comment_id) references blog_api_comment (id) on delete cascade ) charset = utf8mb4; create index blog_api_comment_article_id_12345678 on blog_api_comment (article_id); create index blog_api_comment_user_id_12345678 on blog_api_comment (user_id); create index idx_blog_api_comment_parent_comment_id on blog_api_comment (parent_comment_id); create table blog_api_image ( id bigint auto_increment primary key, image varchar(100) not null, caption varchar(200) null, created_at datetime(6) default CURRENT_TIMESTAMP(6) not null, article_id bigint null, user_id bigint null, constraint blog_api_image_article_id_12345678_fk_blog_api_article_id foreign key (article_id) references blog_api_article (id) on delete cascade, constraint blog_api_image_user_id_12345678_fk_blog_api_user_id foreign key (user_id) references blog_api_user (id) on delete cascade ) charset = utf8mb4; create index blog_api_image_article_id_12345678 on blog_api_image (article_id); create index blog_api_image_user_id_12345678 on blog_api_image (user_id); create table blog_api_like ( id bigint auto_increment primary key, created_at datetime(6) default CURRENT_TIMESTAMP(6) not null, article_id bigint not null, user_id bigint not null, constraint blog_api_like_article_id_user_id_12345678_uniq unique (article_id, user_id), constraint blog_api_like_article_id_12345678_fk_blog_api_article_id foreign key (article_id) references blog_api_article (id) on delete cascade, constraint blog_api_like_user_id_12345678_fk_blog_api_user_id foreign key (user_id) references blog_api_user (id) on delete cascade ) charset = utf8mb4; create index blog_api_like_user_id_12345678 on blog_api_like (user_id); create table django_session ( session_key varchar(40) not null primary key, session_data longtext not null, expire_date datetime(6) not null ) charset = utf8mb4; create index django_session_expire_date_a5c62663 on django_session (expire_date); 3.修改setting.py 的DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '库名', 'USER': '账号', 'PASSWORD': '密码', 'HOST': '服务器api', 'PORT': '端口', 'OPTIONS': { 'charset': 'utf8mb4', }, } } 3. 运行manage.py **一、系统简介** 二次元博客系统是一个专为动漫爱好者设计的内容分享平台,支持文章发布、评论互动、分类浏览等功能,用户可通过网页端参与社区交流,分享二次元相关的见解与创作。 **二、用户注册与登录** 1. 注册账号 进入系统首页后,点击导航栏的 "注册" 按钮(前端页面需补充该入口) 填写用户名、密码等必要信息(密码需包含大小写字母及数字,确保安全性) 提交后系统自动完成注册,跳转至登录页面 2. 登录系统 在登录页面输入注册的用户名和密码 点击 "登录" 按钮,验证通过后进入首页 登录状态下,导航栏将显示用户头像 / 用户名,可点击进入个人中心 3. 退出登录 点击导航栏的 "退出" 按钮,系统清除登录状态,返回首页 未登录状态下,部分功能(如发布文章、评论)将受限制 **三、内容浏览与搜索** 1. 首页浏览 首页展示最新发布的文章列表,按发布时间倒序排列 每篇文章卡片显示标题、作者、发布时间、分类及简介 点击文章标题可进入详情页阅读全文 2. 分类筛选 点击导航栏的 "专题合集",查看所有分类(如 "新番雷达"、"老宅档案" 等) 选择感兴趣的分类,系统将展示该分类下的所有文章 支持跨分类浏览,快速定位特定类型内容 3. 热门内容 点击导航栏的 "热门" 按钮,查看热度较高的文章(按点赞数 / 评论数排序) 热门页面定期更新,展示社区内讨论度较高的内容 4. 搜索功能 在首页或导航栏的搜索框输入关键词(如动画名称、角色名) 系统自动匹配标题包含关键词的文章,支持模糊搜索 搜索结果页支持按发布时间或热度二次排序 **四、内容创作与管理** 1. 发布文章 登录后,点击导航栏的 "发布" 按钮(前端页面需补充该入口) 填写文章信息: 标题:简洁明了,体现文章主题(如 "《某科学的超电磁炮》角色分析") 内容:支持富文本编辑(需前端配合实现),可插入换行、列表等格式 分类:从下拉菜单选择文章所属分类(如 "同人创作"、"吐槽大会") 封面图(可选):上传与文章相关的图片,增强视觉效果 点击 "发布" 按钮,系统校验内容合法性后发布,跳转至文章详情页 2. 上传图片 发布文章时,可通过 "上传图片" 按钮添加插图: 支持 JPG、PNG 格式图片,单张大小不超过 5MB 图片上传后自动关联当前文章,可在编辑器中调整位置 系统自动生成唯一文件名,避免重复 3. 编辑与删除文章 进入自己发布的文章详情页,点击右上角 "编辑" 按钮 修改内容后点击 "保存" 按钮更新文章;点击 "删除" 按钮可永久删除文章(删除前需二次确认) 仅文章作者有权限编辑或删除自己的内容 **五、社区互动功能** 1. 文章点赞 进入文章详情页,点击标题下方的 "点赞" 按钮(心形图标) 已点赞状态下再次点击,将取消点赞 文章卡片将显示当前点赞数,反映内容受欢迎程度 2. 评论互动 文章详情页底部设有评论区,登录用户可输入评论内容并提交 评论支持回复功能(需前端配合实现),可与其他用户针对内容展开讨论 评论内容需遵守社区规范,禁止违规言论 **六、个人中心管理** 1. 查看个人资料 点击导航栏的用户名 / 头像,进入个人中心 个人中心展示用户基本信息、发布的文章列表、收到的点赞 / 评论通知 2. 管理发布内容 在个人中心的 "我的文章" 板块,可查看自己发布的所有文章 支持按发布时间筛选,快速找到历史内容 可直接从列表进入文章编辑页,进行修改或删除 **七、常见问题** 忘记密码怎么办? 登录页面点击 "忘记密码",通过注册邮箱 / 手机验证后重置密码(需前端补充该功能)。 文章发布后不显示? 可能因内容违规被系统拦截,可联系管理员(需补充反馈入口)核查。 如何加入官方社群? 进入 "关于" 页面,扫描底部的官方二维码加入粉丝群,参与实时讨论。 图片上传失败? 检查图片格式(仅限 JPG/PNG)和大小(不超过 5MB),网络不稳定也可能导致失败,建议重试。 **八、社区规范** 禁止发布违法、暴力、色情等违规内容,违者将封禁账号 尊重他人观点,理性讨论,禁止人身攻击或引战言论 转载内容需注明出处,禁止侵权行为 违反规范的内容将被删除,情节严重者永久禁言