- 技术栈
- 原生HTML+CSS+JS
- php8.0
- Mysql5.7
- 界面设计
- 站点主页无需登录,就可以进行内容的浏览
- 点击登录,出现登录页面,管理员登录后进入后台管理,普通用户继续浏览主页
- 用户管理
- 需要支持用户登录,用户分为管理员和普通用户
- 管理员支持对笔记、分类、评论、用户有完整的权限
- 普通用户只有查看笔记、分类、评论和发表评论的权限
- 分类管理
- 笔记管理
- 评论管理
---
## 数据库设计
### 数据库信息
- 数据库名: `site03`
- 字符集: `utf8mb4`
- 排序规则: `utf8mb4_unicode_ci`
```sql
CREATE DATABASE IF NOT EXISTS `site03`
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE `site03`;
```
---
### 表结构
#### 1. users — 用户表
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ---------------- | ---- | --------------------------------- |
| id | INT UNSIGNED | 是 | 主键,自增 |
| username | VARCHAR(50) | 是 | 用户名,唯一 |
| password | VARCHAR(255) | 是 | 密码哈希(password_hash) |
| role | ENUM('admin','user') | 是 | 角色:管理员 / 普通用户,默认 user |
| email | VARCHAR(100) | 否 | 邮箱 |
| avatar | VARCHAR(255) | 否 | 头像路径 |
| status | TINYINT(1) | 是 | 状态:0=禁用, 1=启用,默认 1 |
| created_at | DATETIME | 是 | 创建时间 |
| updated_at | DATETIME | 是 | 更新时间 |
```sql
CREATE TABLE `users` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`role` ENUM('admin','user') NOT NULL DEFAULT 'user',
`email` VARCHAR(100) DEFAULT NULL,
`avatar` VARCHAR(255) DEFAULT NULL,
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '0=禁用 1=启用',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
---
#### 2. categories — 分类表
| 字段 | 类型 | 必填 | 说明 |
| ----------- | ---------------- | ---- | ---------------------------- |
| id | INT UNSIGNED | 是 | 主键,自增 |
| name | VARCHAR(50) | 是 | 分类名称,唯一 |
| slug | VARCHAR(50) | 是 | URL 别名,唯一 |
| description | TEXT | 否 | 分类描述 |
| sort_order | INT UNSIGNED | 是 | 排序权重,默认 0 |
| created_at | DATETIME | 是 | 创建时间 |
| updated_at | DATETIME | 是 | 更新时间 |
```sql
CREATE TABLE `categories` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`slug` VARCHAR(50) NOT NULL,
`description` TEXT DEFAULT NULL,
`sort_order` INT UNSIGNED NOT NULL DEFAULT 0,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`),
UNIQUE KEY `uk_slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
---
#### 3. notes — 笔记表
| 字段 | 类型 | 必填 | 说明 |
| ----------- | --------------------- | ---- | ----------------------------------- |
| id | INT UNSIGNED | 是 | 主键,自增 |
| title | VARCHAR(255) | 是 | 笔记标题 |
| content | LONGTEXT | 是 | 笔记正文 |
| summary | VARCHAR(500) | 否 | 摘要 |
| category_id | INT UNSIGNED | 是 | 所属分类,外键 |
| user_id | INT UNSIGNED | 是 | 作者,外键 |
| status | ENUM('draft','published') | 是 | 状态:草稿 / 已发布,默认 draft |
| view_count | INT UNSIGNED | 是 | 浏览次数,默认 0 |
| created_at | DATETIME | 是 | 创建时间 |
| updated_at | DATETIME | 是 | 更新时间 |
```sql
CREATE TABLE `notes` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`content` LONGTEXT NOT NULL,
`summary` VARCHAR(500) DEFAULT NULL,
`category_id` INT UNSIGNED NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
`status` ENUM('draft','published') NOT NULL DEFAULT 'draft',
`view_count` INT UNSIGNED NOT NULL DEFAULT 0,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_category_id` (`category_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`),
CONSTRAINT `fk_notes_category` FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE RESTRICT,
CONSTRAINT `fk_notes_user` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
---
#### 4. comments — 评论表
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ----------------------------------- | ---- | --------------------------------- |
| id | INT UNSIGNED | 是 | 主键,自增 |
| note_id | INT UNSIGNED | 是 | 所属笔记,外键 |
| user_id | INT UNSIGNED | 是 | 评论人,外键 |
| parent_id | INT UNSIGNED | 否 | 父评论 ID(支持回复),外键 |
| content | TEXT | 是 | 评论内容 |
| status | ENUM('pending','approved','rejected') | 是 | 审核状态,默认 pending |
| created_at | DATETIME | 是 | 创建时间 |
| updated_at | DATETIME | 是 | 更新时间 |
```sql
CREATE TABLE `comments` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`note_id` INT UNSIGNED NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
`parent_id` INT UNSIGNED DEFAULT NULL,
`content` TEXT NOT NULL,
`status` ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_note_id` (`note_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_parent_id` (`parent_id`),
CONSTRAINT `fk_comments_note` FOREIGN KEY (`note_id`) REFERENCES `notes`(`id`) ON DELETE CASCADE,
CONSTRAINT `fk_comments_user` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT,
CONSTRAINT `fk_comments_parent` FOREIGN KEY (`parent_id`) REFERENCES `comments`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
---
### 索引说明
| 表 | 索引名 | 字段 | 类型 | 用途 |
| ---------- | ------------------- | ----------- | ------ | -------------------------- |
| users | PRIMARY | id | 主键 | 用户唯一标识 |
| users | uk_username | username | 唯一 | 用户名唯一约束 |
| categories | PRIMARY | id | 主键 | 分类唯一标识 |
| categories | uk_name | name | 唯一 | 分类名唯一约束 |
| categories | uk_slug | slug | 唯一 | URL 别名唯一约束 |
| notes | PRIMARY | id | 主键 | 笔记唯一标识 |
| notes | idx_category_id | category_id | 普通 | 按分类查询笔记 |
| notes | idx_user_id | user_id | 普通 | 按作者查询笔记 |
| notes | idx_status | status | 普通 | 按发布状态筛选 |
| comments | PRIMARY | id | 主键 | 评论唯一标识 |
| comments | idx_note_id | note_id | 普通 | 按笔记查询评论 |
| comments | idx_user_id | user_id | 普通 | 按用户查询评论 |
| comments | idx_parent_id | parent_id | 普通 | 查询回复链 |
---
### 外键约束说明
- `notes.category_id` → `categories.id`: RESTRICT,存在笔记时不可删除分类
- `notes.user_id` → `users.id`: RESTRICT,存在笔记时不可删除用户
- `comments.note_id` → `notes.id`: CASCADE,删除笔记时级联删除评论
- `comments.user_id` → `users.id`: RESTRICT,存在评论时不可删除用户
- `comments.parent_id` → `comments.id`: CASCADE,删除父评论时级联删除子回复
---
### 种子数据
```sql
-- 默认管理员: admin / admin123
INSERT INTO `users` (`username`, `password`, `role`) VALUES
('admin', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'admin');
-- 示例分类
INSERT INTO `categories` (`name`, `slug`, `description`, `sort_order`) VALUES
('技术笔记', 'tech', '编程与技术相关笔记', 1),
('生活随笔', 'life', '日常生活与感悟', 2),
('读书笔记', 'reading', '书籍阅读与书评', 3);
```
> 密码 `admin123` 使用 PHP `password_hash('admin123', PASSWORD_DEFAULT)` 生成,实际部署时请更换。
> 详细搭建说明参见 [spec.md](#) 附录。