Nodejs+html+mysql实现轻量web应用

教育平台API设计与实现(Node.js + MySQL)

下面我将为您设计一个完整的教育平台API系统,包含用户认证、课程管理、文章管理等功能。

系统架构设计

技术栈

  • 后端: Node.js + Express.js

  • 数据库: MySQL

  • 身份验证: JWT (JSON Web Tokens)

  • 密码加密: bcryptjs

  • 其他: cors, dotenv, nodemon

数据库设计

首先创建数据库表结构:

sql

复制代码
CREATE DATABASE education_platform;
USE education_platform;

-- 用户表
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    role ENUM('student', 'teacher', 'admin') DEFAULT 'student',
    avatar_url VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 课程表
CREATE TABLE courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    instructor_id INT NOT NULL,
    price DECIMAL(10, 2) DEFAULT 0,
    thumbnail_url VARCHAR(255),
    category VARCHAR(100),
    level ENUM('beginner', 'intermediate', 'advanced') DEFAULT 'beginner',
    duration INT, -- 课程时长(小时)
    is_published BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (instructor_id) REFERENCES users(id)
);

-- 文章表
CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content LONGTEXT NOT NULL,
    author_id INT NOT NULL,
    course_id INT,
    is_public BOOLEAN DEFAULT TRUE,
    tags JSON,
    view_count INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (author_id) REFERENCES users(id),
    FOREIGN KEY (course_id) REFERENCES courses(id)
);

-- 用户课程关联表(报名记录)
CREATE TABLE user_courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    course_id INT NOT NULL,
    enrolled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    progress INT DEFAULT 0, -- 学习进度百分比
    completed BOOLEAN DEFAULT FALSE,
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (course_id) REFERENCES courses(id),
    UNIQUE KEY unique_enrollment (user_id, course_id)
);

-- API表
CREATE TABLE apis (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    endpoint VARCHAR(255) NOT NULL,
    method ENUM('GET', 'POST', 'PUT', 'DELETE', 'PATCH') DEFAULT 'GET',
    description TEXT,
    parameters JSON,
    response_example JSON,
    requires_auth BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

API实现代码

1. 项目初始化

创建项目并安装依赖:

bash

复制代码
mkdir education-platform-api
cd education-platform-api
npm init -y
npm install express mysql2 bcryptjs jsonwebtoken cors dotenv
npm install -D nodemon

2. 项目结构

text

复制代码
education-platform-api/
├── config/
│   └── database.js
├── controllers/
│   ├── authController.js
│   ├── userController.js
│   ├── courseController.js
│   ├── articleController.js
│   └── apiController.js
├── middleware/
│   ├── auth.js
│   └── validation.js
├── routes/
│   ├── auth.js
│   ├── users.js
│   ├── courses.js
│   ├── articles.js
│   └── apis.js
├── .env
├── app.js
└── package.json

3. 环境配置 (.env)

env

复制代码
PORT=3000
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=education_platform
JWT_SECRET=your_jwt_secret_key
JWT_EXPIRES_IN=7d

4. 数据库连接配置 (config/database.js)

javascript

复制代码
const mysql = require('mysql2');
require('dotenv').config();

const connection = mysql.createConnection({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
});

connection.connect((err) => {
  if (err) {
    console.error('数据库连接失败: ' + err.stack);
    return;
  }
  console.log('数据库连接成功,连接ID: ' + connection.threadId);
});

module.exports = connection;

5. 认证中间件 (middleware/auth.js)

javascript

复制代码
const jwt = require('jsonwebtoken');
require('dotenv').config();

const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ 
      success: false, 
      message: '访问令牌缺失' 
    });
  }

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ 
        success: false, 
        message: '访问令牌无效' 
      });
    }
    req.user = user;
    next();
  });
};

const authorize = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ 
        success: false, 
        message: '没有权限执行此操作' 
      });
    }
    next();
  };
};

module.exports = { authenticateToken, authorize };

6. 认证控制器 (controllers/authController.js)

javascript

复制代码
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const db = require('../config/database');
require('dotenv').config();

// 用户注册
const register = (req, res) => {
  const { username, email, password, role } = req.body;

  // 验证必填字段
  if (!username || !email || !password) {
    return res.status(400).json({
      success: false,
      message: '用户名、邮箱和密码是必填项'
    });
  }

  // 检查用户是否已存在
  db.query(
    'SELECT id FROM users WHERE email = ? OR username = ?',
    [email, username],
    async (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length > 0) {
        return res.status(409).json({
          success: false,
          message: '用户名或邮箱已存在'
        });
      }

      try {
        // 加密密码
        const saltRounds = 10;
        const hashedPassword = await bcrypt.hash(password, saltRounds);

        // 创建用户
        db.query(
          'INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, ?)',
          [username, email, hashedPassword, role || 'student'],
          (err, results) => {
            if (err) {
              return res.status(500).json({
                success: false,
                message: '用户创建失败'
              });
            }

            // 生成JWT令牌
            const token = jwt.sign(
              { 
                id: results.insertId, 
                username, 
                email, 
                role: role || 'student' 
              },
              process.env.JWT_SECRET,
              { expiresIn: process.env.JWT_EXPIRES_IN }
            );

            res.status(201).json({
              success: true,
              message: '用户注册成功',
              data: {
                token,
                user: {
                  id: results.insertId,
                  username,
                  email,
                  role: role || 'student'
                }
              }
            });
          }
        );
      } catch (error) {
        res.status(500).json({
          success: false,
          message: '服务器错误'
        });
      }
    }
  );
};

// 用户登录
const login = (req, res) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({
      success: false,
      message: '邮箱和密码是必填项'
    });
  }

  // 查找用户
  db.query(
    'SELECT * FROM users WHERE email = ?',
    [email],
    async (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(401).json({
          success: false,
          message: '邮箱或密码错误'
        });
      }

      const user = results[0];

      // 验证密码
      const isPasswordValid = await bcrypt.compare(password, user.password);
      if (!isPasswordValid) {
        return res.status(401).json({
          success: false,
          message: '邮箱或密码错误'
        });
      }

      // 生成JWT令牌
      const token = jwt.sign(
        { 
          id: user.id, 
          username: user.username, 
          email: user.email, 
          role: user.role 
        },
        process.env.JWT_SECRET,
        { expiresIn: process.env.JWT_EXPIRES_IN }
      );

      res.json({
        success: true,
        message: '登录成功',
        data: {
          token,
          user: {
            id: user.id,
            username: user.username,
            email: user.email,
            role: user.role,
            avatar_url: user.avatar_url
          }
        }
      });
    }
  );
};

// 获取当前用户信息
const getCurrentUser = (req, res) => {
  db.query(
    'SELECT id, username, email, role, avatar_url, created_at FROM users WHERE id = ?',
    [req.user.id],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '用户不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

module.exports = { register, login, getCurrentUser };

7. 用户控制器 (controllers/userController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有用户
const getAllUsers = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;

  // 获取用户总数
  db.query('SELECT COUNT(*) as total FROM users', (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页用户数据
    db.query(
      'SELECT id, username, email, role, avatar_url, created_at FROM users LIMIT ? OFFSET ?',
      [limit, offset],
      (err, results) => {
        if (err) {
          return res.status(500).json({
            success: false,
            message: '数据库查询错误'
          });
        }

        res.json({
          success: true,
          data: {
            users: results,
            pagination: {
              page,
              limit,
              total,
              totalPages
            }
          }
        });
      }
    );
  });
};

// 获取单个用户
const getUserById = (req, res) => {
  const userId = req.params.id;

  db.query(
    'SELECT id, username, email, role, avatar_url, created_at FROM users WHERE id = ?',
    [userId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '用户不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

// 更新用户信息
const updateUser = (req, res) => {
  const userId = req.params.id;
  const { username, avatar_url } = req.body;

  // 检查是否有权限更新(只能更新自己的信息或管理员)
  if (req.user.id != userId && req.user.role !== 'admin') {
    return res.status(403).json({
      success: false,
      message: '没有权限更新此用户信息'
    });
  }

  db.query(
    'UPDATE users SET username = ?, avatar_url = ? WHERE id = ?',
    [username, avatar_url, userId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库更新错误'
        });
      }

      if (results.affectedRows === 0) {
        return res.status(404).json({
          success: false,
          message: '用户不存在'
        });
      }

      res.json({
        success: true,
        message: '用户信息更新成功'
      });
    }
  );
};

// 删除用户
const deleteUser = (req, res) => {
  const userId = req.params.id;

  // 只有管理员可以删除用户
  if (req.user.role !== 'admin') {
    return res.status(403).json({
      success: false,
      message: '没有权限删除用户'
    });
  }

  db.query(
    'DELETE FROM users WHERE id = ?',
    [userId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库删除错误'
        });
      }

      if (results.affectedRows === 0) {
        return res.status(404).json({
          success: false,
          message: '用户不存在'
        });
      }

      res.json({
        success: true,
        message: '用户删除成功'
      });
    }
  );
};

module.exports = { getAllUsers, getUserById, updateUser, deleteUser };

8. 课程控制器 (controllers/courseController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有课程
const getAllCourses = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;
  const { category, level, is_published } = req.query;

  let query = `
    SELECT c.*, u.username as instructor_name 
    FROM courses c 
    JOIN users u ON c.instructor_id = u.id
  `;
  let countQuery = 'SELECT COUNT(*) as total FROM courses c';
  let queryParams = [];
  let countParams = [];
  let conditions = [];

  // 添加筛选条件
  if (category) {
    conditions.push('c.category = ?');
    queryParams.push(category);
    countParams.push(category);
  }

  if (level) {
    conditions.push('c.level = ?');
    queryParams.push(level);
    countParams.push(level);
  }

  if (is_published !== undefined) {
    conditions.push('c.is_published = ?');
    queryParams.push(is_published === 'true');
    countParams.push(is_published === 'true');
  }

  if (conditions.length > 0) {
    query += ' WHERE ' + conditions.join(' AND ');
    countQuery += ' WHERE ' + conditions.join(' AND ');
  }

  query += ' LIMIT ? OFFSET ?';
  queryParams.push(limit, offset);

  // 获取课程总数
  db.query(countQuery, countParams, (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页课程数据
    db.query(query, queryParams, (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      res.json({
        success: true,
        data: {
          courses: results,
          pagination: {
            page,
            limit,
            total,
            totalPages
          }
        }
      });
    });
  });
};

// 获取单个课程
const getCourseById = (req, res) => {
  const courseId = req.params.id;

  db.query(
    `SELECT c.*, u.username as instructor_name 
     FROM courses c 
     JOIN users u ON c.instructor_id = u.id 
     WHERE c.id = ?`,
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

// 创建课程
const createCourse = (req, res) => {
  const { title, description, price, thumbnail_url, category, level, duration } = req.body;
  const instructorId = req.user.id;

  if (!title || !description) {
    return res.status(400).json({
      success: false,
      message: '课程标题和描述是必填项'
    });
  }

  db.query(
    'INSERT INTO courses (title, description, instructor_id, price, thumbnail_url, category, level, duration) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
    [title, description, instructorId, price, thumbnail_url, category, level, duration],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '课程创建失败'
        });
      }

      res.status(201).json({
        success: true,
        message: '课程创建成功',
        data: {
          id: results.insertId
        }
      });
    }
  );
};

// 更新课程
const updateCourse = (req, res) => {
  const courseId = req.params.id;
  const { title, description, price, thumbnail_url, category, level, duration, is_published } = req.body;

  // 检查是否是课程创建者或管理员
  db.query(
    'SELECT instructor_id FROM courses WHERE id = ?',
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在'
        });
      }

      if (results[0].instructor_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限更新此课程'
        });
      }

      db.query(
        'UPDATE courses SET title = ?, description = ?, price = ?, thumbnail_url = ?, category = ?, level = ?, duration = ?, is_published = ? WHERE id = ?',
        [title, description, price, thumbnail_url, category, level, duration, is_published, courseId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '课程更新失败'
            });
          }

          res.json({
            success: true,
            message: '课程更新成功'
          });
        }
      );
    }
  );
};

// 删除课程
const deleteCourse = (req, res) => {
  const courseId = req.params.id;

  // 检查是否是课程创建者或管理员
  db.query(
    'SELECT instructor_id FROM courses WHERE id = ?',
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在'
        });
      }

      if (results[0].instructor_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限删除此课程'
        });
      }

      db.query(
        'DELETE FROM courses WHERE id = ?',
        [courseId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '课程删除失败'
            });
          }

          res.json({
            success: true,
            message: '课程删除成功'
          });
        }
      );
    }
  );
};

// 报名课程
const enrollCourse = (req, res) => {
  const courseId = req.params.id;
  const userId = req.user.id;

  // 检查课程是否存在
  db.query(
    'SELECT id FROM courses WHERE id = ? AND is_published = TRUE',
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在或未发布'
        });
      }

      // 检查是否已报名
      db.query(
        'SELECT id FROM user_courses WHERE user_id = ? AND course_id = ?',
        [userId, courseId],
        (err, enrollmentResults) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '数据库查询错误'
            });
          }

          if (enrollmentResults.length > 0) {
            return res.status(409).json({
              success: false,
              message: '您已经报名此课程'
            });
          }

          // 报名课程
          db.query(
            'INSERT INTO user_courses (user_id, course_id) VALUES (?, ?)',
            [userId, courseId],
            (err, results) => {
              if (err) {
                return res.status(500).json({
                  success: false,
                  message: '报名失败'
                });
              }

              res.status(201).json({
                success: true,
                message: '报名成功'
              });
            }
          );
        }
      );
    }
  );
};

module.exports = {
  getAllCourses,
  getCourseById,
  createCourse,
  updateCourse,
  deleteCourse,
  enrollCourse
};

9. 文章控制器 (controllers/articleController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有文章
const getAllArticles = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;
  const { course_id, is_public, author_id } = req.query;

  let query = `
    SELECT a.*, u.username as author_name, c.title as course_title
    FROM articles a 
    LEFT JOIN users u ON a.author_id = u.id
    LEFT JOIN courses c ON a.course_id = c.id
  `;
  let countQuery = 'SELECT COUNT(*) as total FROM articles a';
  let queryParams = [];
  let countParams = [];
  let conditions = [];

  // 添加筛选条件
  if (course_id) {
    conditions.push('a.course_id = ?');
    queryParams.push(course_id);
    countParams.push(course_id);
  }

  if (is_public !== undefined) {
    conditions.push('a.is_public = ?');
    queryParams.push(is_public === 'true');
    countParams.push(is_public === 'true');
  }

  if (author_id) {
    conditions.push('a.author_id = ?');
    queryParams.push(author_id);
    countParams.push(author_id);
  }

  // 非管理员只能查看公开文章或自己的文章
  if (req.user.role !== 'admin') {
    conditions.push('(a.is_public = TRUE OR a.author_id = ?)');
    queryParams.push(req.user.id);
    countParams.push(req.user.id);
  }

  if (conditions.length > 0) {
    query += ' WHERE ' + conditions.join(' AND ');
    countQuery += ' WHERE ' + conditions.join(' AND ');
  }

  query += ' ORDER BY a.created_at DESC LIMIT ? OFFSET ?';
  queryParams.push(limit, offset);

  // 获取文章总数
  db.query(countQuery, countParams, (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页文章数据
    db.query(query, queryParams, (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      res.json({
        success: true,
        data: {
          articles: results,
          pagination: {
            page,
            limit,
            total,
            totalPages
          }
        }
      });
    });
  });
};

// 获取单个文章
const getArticleById = (req, res) => {
  const articleId = req.params.id;

  let query = `
    SELECT a.*, u.username as author_name, c.title as course_title
    FROM articles a 
    LEFT JOIN users u ON a.author_id = u.id
    LEFT JOIN courses c ON a.course_id = c.id
    WHERE a.id = ?
  `;
  let queryParams = [articleId];

  // 非管理员只能查看公开文章或自己的文章
  if (req.user.role !== 'admin') {
    query += ' AND (a.is_public = TRUE OR a.author_id = ?)';
    queryParams.push(req.user.id);
  }

  db.query(query, queryParams, (err, results) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    if (results.length === 0) {
      return res.status(404).json({
        success: false,
        message: '文章不存在或没有访问权限'
      });
    }

    // 增加浏览次数
    if (results[0].is_public || results[0].author_id === req.user.id) {
      db.query(
        'UPDATE articles SET view_count = view_count + 1 WHERE id = ?',
        [articleId]
      );
    }

    res.json({
      success: true,
      data: results[0]
    });
  });
};

// 创建文章
const createArticle = (req, res) => {
  const { title, content, course_id, is_public, tags } = req.body;
  const authorId = req.user.id;

  if (!title || !content) {
    return res.status(400).json({
      success: false,
      message: '文章标题和内容是必填项'
    });
  }

  db.query(
    'INSERT INTO articles (title, content, author_id, course_id, is_public, tags) VALUES (?, ?, ?, ?, ?, ?)',
    [title, content, authorId, course_id, is_public || true, JSON.stringify(tags)],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '文章创建失败'
        });
      }

      res.status(201).json({
        success: true,
        message: '文章创建成功',
        data: {
          id: results.insertId
        }
      });
    }
  );
};

// 更新文章
const updateArticle = (req, res) => {
  const articleId = req.params.id;
  const { title, content, course_id, is_public, tags } = req.body;

  // 检查是否是文章作者或管理员
  db.query(
    'SELECT author_id FROM articles WHERE id = ?',
    [articleId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '文章不存在'
        });
      }

      if (results[0].author_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限更新此文章'
        });
      }

      db.query(
        'UPDATE articles SET title = ?, content = ?, course_id = ?, is_public = ?, tags = ? WHERE id = ?',
        [title, content, course_id, is_public, JSON.stringify(tags), articleId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '文章更新失败'
            });
          }

          res.json({
            success: true,
            message: '文章更新成功'
          });
        }
      );
    }
  );
};

// 删除文章
const deleteArticle = (req, res) => {
  const articleId = req.params.id;

  // 检查是否是文章作者或管理员
  db.query(
    'SELECT author_id FROM articles WHERE id = ?',
    [articleId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '文章不存在'
        });
      }

      if (results[0].author_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限删除此文章'
        });
      }

      db.query(
        'DELETE FROM articles WHERE id = ?',
        [articleId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '文章删除失败'
            });
          }

          res.json({
            success: true,
            message: '文章删除成功'
          });
        }
      );
    }
  );
};

module.exports = {
  getAllArticles,
  getArticleById,
  createArticle,
  updateArticle,
  deleteArticle
};

10. API控制器 (controllers/apiController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有API
const getAllAPIs = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;

  // 获取API总数
  db.query('SELECT COUNT(*) as total FROM apis', (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页API数据
    db.query(
      'SELECT * FROM apis LIMIT ? OFFSET ?',
      [limit, offset],
      (err, results) => {
        if (err) {
          return res.status(500).json({
            success: false,
            message: '数据库查询错误'
          });
        }

        res.json({
          success: true,
          data: {
            apis: results,
            pagination: {
              page,
              limit,
              total,
              totalPages
            }
          }
        });
      }
    );
  });
};

// 获取单个API
const getAPIById = (req, res) => {
  const apiId = req.params.id;

  db.query(
    'SELECT * FROM apis WHERE id = ?',
    [apiId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: 'API不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

// 创建API
const createAPI = (req, res) => {
  const { name, endpoint, method, description, parameters, response_example, requires_auth } = req.body;

  if (!name || !endpoint) {
    return res.status(400).json({
      success: false,
      message: 'API名称和端点是必填项'
    });
  }

  db.query(
    'INSERT INTO apis (name, endpoint, method, description, parameters, response_example, requires_auth) VALUES (?, ?, ?, ?, ?, ?, ?)',
    [name, endpoint, method, description, JSON.stringify(parameters), JSON.stringify(response_example), requires_auth],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: 'API创建失败'
        });
      }

      res.status(201).json({
        success: true,
        message: 'API创建成功',
        data: {
          id: results.insertId
        }
      });
    }
  );
};

// 更新API
const updateAPI = (req, res) => {
  const apiId = req.params.id;
  const { name, endpoint, method, description, parameters, response_example, requires_auth } = req.body;

  db.query(
    'UPDATE apis SET name = ?, endpoint = ?, method = ?, description = ?, parameters = ?, response_example = ?, requires_auth = ? WHERE id = ?',
    [name, endpoint, method, description, JSON.stringify(parameters), JSON.stringify(response_example), requires_auth, apiId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: 'API更新失败'
        });
      }

      if (results.affectedRows === 0) {
        return res.status(404).json({
          success: false,
          message: 'API不存在'
        });
      }

      res.json({
        success: true,
        message: 'API更新成功'
      });
    }
  );
};

// 删除API
const deleteAPI = (req, res) => {
  const apiId = req.params.id;

  db.query(
    'DELETE FROM apis WHERE id = ?',
    [apiId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: 'API删除失败'
        });
      }

      if (results.affectedRows === 0) {
        return res.status(404).json({
          success: false,
          message: 'API不存在'
        });
      }

      res.json({
        success: true,
        message: 'API删除成功'
      });
    }
  );
};

module.exports = {
  getAllAPIs,
  getAPIById,
  createAPI,
  updateAPI,
  deleteAPI
};

11. 路由配置

创建各个模块的路由文件:

认证路由 (routes/auth.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { register, login, getCurrentUser } = require('../controllers/authController');
const { authenticateToken } = require('../middleware/auth');

router.post('/register', register);
router.post('/login', login);
router.get('/me', authenticateToken, getCurrentUser);

module.exports = router;
用户路由 (routes/users.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { getAllUsers, getUserById, updateUser, deleteUser } = require('../controllers/userController');
const { authenticateToken, authorize } = require('../middleware/auth');

router.get('/', authenticateToken, authorize('admin'), getAllUsers);
router.get('/:id', authenticateToken, getUserById);
router.put('/:id', authenticateToken, updateUser);
router.delete('/:id', authenticateToken, authorize('admin'), deleteUser);

module.exports = router;
课程路由 (routes/courses.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { 
  getAllCourses, 
  getCourseById, 
  createCourse, 
  updateCourse, 
  deleteCourse, 
  enrollCourse 
} = require('../controllers/courseController');
const { authenticateToken, authorize } = require('../middleware/auth');

router.get('/', getAllCourses);
router.get('/:id', getCourseById);
router.post('/', authenticateToken, authorize('teacher', 'admin'), createCourse);
router.put('/:id', authenticateToken, updateCourse);
router.delete('/:id', authenticateToken, deleteCourse);
router.post('/:id/enroll', authenticateToken, enrollCourse);

module.exports = router;
文章路由 (routes/articles.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { 
  getAllArticles, 
  getArticleById, 
  createArticle, 
  updateArticle, 
  deleteArticle 
} = require('../controllers/articleController');
const { authenticateToken } = require('../middleware/auth');

router.get('/', authenticateToken, getAllArticles);
router.get('/:id', authenticateToken, getArticleById);
router.post('/', authenticateToken, createArticle);
router.put('/:id', authenticateToken, updateArticle);
router.delete('/:id', authenticateToken, deleteArticle);

module.exports = router;
API路由 (routes/apis.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { 
  getAllAPIs, 
  getAPIById, 
  createAPI, 
  updateAPI, 
  deleteAPI 
} = require('../controllers/apiController');
const { authenticateToken, authorize } = require('../middleware/auth');

router.get('/', getAllAPIs);
router.get('/:id', getAPIById);
router.post('/', authenticateToken, authorize('admin'), createAPI);
router.put('/:id', authenticateToken, authorize('admin'), updateAPI);
router.delete('/:id', authenticateToken, authorize('admin'), deleteAPI);

module.exports = router;

12. 主应用文件 (app.js)

javascript

复制代码
const express = require('express');
const cors = require('cors');
require('dotenv').config();

const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/users');
const courseRoutes = require('./routes/courses');
const articleRoutes = require('./routes/articles');
const apiRoutes = require('./routes/apis');

const app = express();
const PORT = process.env.PORT || 3000;

// 中间件
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 路由
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/courses', courseRoutes);
app.use('/api/articles', articleRoutes);
app.use('/api/apis', apiRoutes);

// 健康检查端点
app.get('/health', (req, res) => {
  res.json({ 
    success: true, 
    message: '教育平台API运行正常',
    timestamp: new Date().toISOString()
  });
});

// 404处理
app.use('*', (req, res) => {
  res.status(404).json({
    success: false,
    message: 'API端点不存在'
  });
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    success: false,
    message: '服务器内部错误'
  });
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`教育平台API服务器运行在端口 ${PORT}`);
});

module.exports = app;

13. Package.json 脚本配置

json

复制代码
{
  "name": "education-platform-api",
  "version": "1.0.0",
  "description": "教育平台API服务",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "express": "^4.18.2",
    "mysql2": "^3.6.0",
    "bcryptjs": "^2.4.3",
    "jsonwebtoken": "^9.0.2",
    "cors": "^2.8.5",
    "dotenv": "^16.3.1"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  },
  "keywords": ["education", "api", "nodejs", "mysql"],
  "author": "Your Name",
  "license": "MIT"
}

API使用说明

1. 认证相关API

  • POST /api/auth/register - 用户注册

  • POST /api/auth/login - 用户登录

  • GET /api/auth/me - 获取当前用户信息

2. 用户管理API

  • GET /api/users - 获取所有用户(仅管理员)

  • GET /api/users/:id - 获取指定用户信息

  • PUT /api/users/:id - 更新用户信息

  • DELETE /api/users/:id - 删除用户(仅管理员)

3. 课程管理API

  • GET /api/courses - 获取所有课程

  • GET /api/courses/:id - 获取指定课程详情

  • POST /api/courses - 创建课程(教师和管理员)

  • PUT /api/courses/:id - 更新课程信息

  • DELETE /api/courses/:id - 删除课程

  • POST /api/courses/:id/enroll - 报名课程

4. 文章管理API

  • GET /api/articles - 获取所有文章

  • GET /api/articles/:id - 获取指定文章详情

  • POST /api/articles - 创建文章

  • PUT /api/articles/:id - 更新文章

  • DELETE /api/articles/:id - 删除文章

5. API文档管理

  • GET /api/apis - 获取所有API文档

  • GET /api/apis/:id - 获取指定API文档

  • POST /api/apis - 创建API文档(仅管理员)

  • PUT /api/apis/:id - 更新API文档(仅管理员)

  • DELETE /api/apis/:id - 删除API文档(仅管理员)

部署和运行

  1. 安装依赖:

bash

复制代码
npm install
  1. 创建MySQL数据库并导入SQL结构

  2. 配置环境变量(.env文件)

  3. 启动服务器:

bash

复制代码
# 开发模式
npm run dev

# 生产模式
npm start

安全注意事项

  1. 在生产环境中,确保使用强密码和安全的JWT密钥

  2. 考虑使用HTTPS加密通信

  3. 实施速率限制防止API滥用

  4. 定期更新依赖包以修复安全漏洞

  5. 对用户输入进行严格的验证和清理

这个API系统提供了教育平台的核心功能,您可以根据需要进一步扩展和优化。

使用nodejs链接mysql编写教育网站api,包含登录注册首页和其他页面api接口

我们正在设计一个教育网站的API,包括登录、注册、首页和其他页面的接口。我们将使用Node.js和MySQL。

根据要求,我们需要设计以下API端点:

  1. 用户认证

    • 注册

    • 登录

    • 获取当前用户信息(可能需要)

  2. 首页

    • 获取首页数据(可能包括轮播图、推荐课程、最新文章等)
  3. 课程相关

    • 获取课程列表

    • 获取课程详情

    • 获取课程分类

  4. 文章相关

    • 获取文章列表

    • 获取文章详情

  5. 笔记相关

    • 获取笔记列表(公开和私密)

    • 创建笔记

    • 更新笔记

    • 删除笔记

  6. 自学页面

    • 获取自学课程列表(免费和收费)
  7. 案例页面

    • 获取案例列表
  8. API页面

    • 获取API列表

考虑到时间,我们先设计主要接口,并实现其中一部分。

我们将使用Express框架,并使用mysql2库连接MySQL数据库。

步骤:

  1. 初始化项目

  2. 安装依赖:express, mysql2, bcryptjs, jsonwebtoken, cors, dotenv等

  3. 创建数据库连接

  4. 设计数据库表(如果尚未创建)

  5. 创建路由和控制器

  6. 实现中间件(如认证中间件)

由于代码量较大,我们将分步骤实现。

首先,我们设计数据库表(假设数据库名为education_platform):

用户表(users):

id, username, email, password, avatar, role, created_at, updated_at

课程表(courses):

id, title, description, price, category_id, teacher_id, cover_image, created_at, updated_at

课程分类表(categories):

id, name, description

文章表(articles):

id, title, content, author_id, cover_image, is_public, created_at, updated_at

笔记表(notes):

id, title, content, user_id, course_id, is_public, created_at, updated_at

案例表(cases):

id, title, description, image, link, created_at

API表(apis):

id, name, endpoint, method, description, parameters, example

由于时间关系,我们不会完全实现所有接口,但会给出一个框架,并实现部分核心功能。

我们先从用户注册和登录开始。

注意:密码需要加密存储,使用bcryptjs。

我们使用JWT进行身份验证。

接下来,我们开始编写代码。

教育网站API设计与实现 (Node.js + MySQL)

下面我将设计一个完整的教育网站API系统,包含用户认证、课程管理、文章管理等功能。

系统架构

技术栈

  • 后端: Node.js + Express.js

  • 数据库: MySQL

  • 身份验证: JWT (JSON Web Tokens)

  • 密码加密: bcryptjs

  • 其他: cors, dotenv, nodemon

数据库设计

首先创建数据库表结构:

sql

复制代码
CREATE DATABASE education_platform;
USE education_platform;

-- 用户表
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    role ENUM('student', 'teacher', 'admin') DEFAULT 'student',
    avatar_url VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 课程表
CREATE TABLE courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    instructor_id INT NOT NULL,
    price DECIMAL(10, 2) DEFAULT 0,
    thumbnail_url VARCHAR(255),
    category VARCHAR(100),
    level ENUM('beginner', 'intermediate', 'advanced') DEFAULT 'beginner',
    duration INT, -- 课程时长(小时)
    is_published BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (instructor_id) REFERENCES users(id)
);

-- 文章表
CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content LONGTEXT NOT NULL,
    author_id INT NOT NULL,
    course_id INT,
    is_public BOOLEAN DEFAULT TRUE,
    tags JSON,
    view_count INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (author_id) REFERENCES users(id),
    FOREIGN KEY (course_id) REFERENCES courses(id)
);

-- 用户课程关联表(报名记录)
CREATE TABLE user_courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    course_id INT NOT NULL,
    enrolled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    progress INT DEFAULT 0, -- 学习进度百分比
    completed BOOLEAN DEFAULT FALSE,
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (course_id) REFERENCES courses(id),
    UNIQUE KEY unique_enrollment (user_id, course_id)
);

-- API表
CREATE TABLE apis (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    endpoint VARCHAR(255) NOT NULL,
    method ENUM('GET', 'POST', 'PUT', 'DELETE', 'PATCH') DEFAULT 'GET',
    description TEXT,
    parameters JSON,
    response_example JSON,
    requires_auth BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

API实现代码

1. 项目初始化

创建项目并安装依赖:

bash

复制代码
mkdir education-platform-api
cd education-platform-api
npm init -y
npm install express mysql2 bcryptjs jsonwebtoken cors dotenv
npm install -D nodemon

2. 项目结构

text

复制代码
education-platform-api/
├── config/
│   └── database.js
├── controllers/
│   ├── authController.js
│   ├── userController.js
│   ├── courseController.js
│   ├── articleController.js
│   └── apiController.js
├── middleware/
│   ├── auth.js
│   └── validation.js
├── routes/
│   ├── auth.js
│   ├── users.js
│   ├── courses.js
│   ├── articles.js
│   └── apis.js
├── .env
├── app.js
└── package.json

3. 环境配置 (.env)

env

复制代码
PORT=3000
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=education_platform
JWT_SECRET=your_jwt_secret_key
JWT_EXPIRES_IN=7d

4. 数据库连接配置 (config/database.js)

javascript

复制代码
const mysql = require('mysql2');
require('dotenv').config();

const connection = mysql.createConnection({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
});

connection.connect((err) => {
  if (err) {
    console.error('数据库连接失败: ' + err.stack);
    return;
  }
  console.log('数据库连接成功,连接ID: ' + connection.threadId);
});

module.exports = connection;

5. 认证中间件 (middleware/auth.js)

javascript

复制代码
const jwt = require('jsonwebtoken');
require('dotenv').config();

const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ 
      success: false, 
      message: '访问令牌缺失' 
    });
  }

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ 
        success: false, 
        message: '访问令牌无效' 
      });
    }
    req.user = user;
    next();
  });
};

const authorize = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ 
        success: false, 
        message: '没有权限执行此操作' 
      });
    }
    next();
  };
};

module.exports = { authenticateToken, authorize };

6. 认证控制器 (controllers/authController.js)

javascript

复制代码
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const db = require('../config/database');
require('dotenv').config();

// 用户注册
const register = (req, res) => {
  const { username, email, password, role } = req.body;

  // 验证必填字段
  if (!username || !email || !password) {
    return res.status(400).json({
      success: false,
      message: '用户名、邮箱和密码是必填项'
    });
  }

  // 检查用户是否已存在
  db.query(
    'SELECT id FROM users WHERE email = ? OR username = ?',
    [email, username],
    async (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length > 0) {
        return res.status(409).json({
          success: false,
          message: '用户名或邮箱已存在'
        });
      }

      try {
        // 加密密码
        const saltRounds = 10;
        const hashedPassword = await bcrypt.hash(password, saltRounds);

        // 创建用户
        db.query(
          'INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, ?)',
          [username, email, hashedPassword, role || 'student'],
          (err, results) => {
            if (err) {
              return res.status(500).json({
                success: false,
                message: '用户创建失败'
              });
            }

            // 生成JWT令牌
            const token = jwt.sign(
              { 
                id: results.insertId, 
                username, 
                email, 
                role: role || 'student' 
              },
              process.env.JWT_SECRET,
              { expiresIn: process.env.JWT_EXPIRES_IN }
            );

            res.status(201).json({
              success: true,
              message: '用户注册成功',
              data: {
                token,
                user: {
                  id: results.insertId,
                  username,
                  email,
                  role: role || 'student'
                }
              }
            });
          }
        );
      } catch (error) {
        res.status(500).json({
          success: false,
          message: '服务器错误'
        });
      }
    }
  );
};

// 用户登录
const login = (req, res) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({
      success: false,
      message: '邮箱和密码是必填项'
    });
  }

  // 查找用户
  db.query(
    'SELECT * FROM users WHERE email = ?',
    [email],
    async (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(401).json({
          success: false,
          message: '邮箱或密码错误'
        });
      }

      const user = results[0];

      // 验证密码
      const isPasswordValid = await bcrypt.compare(password, user.password);
      if (!isPasswordValid) {
        return res.status(401).json({
          success: false,
          message: '邮箱或密码错误'
        });
      }

      // 生成JWT令牌
      const token = jwt.sign(
        { 
          id: user.id, 
          username: user.username, 
          email: user.email, 
          role: user.role 
        },
        process.env.JWT_SECRET,
        { expiresIn: process.env.JWT_EXPIRES_IN }
      );

      res.json({
        success: true,
        message: '登录成功',
        data: {
          token,
          user: {
            id: user.id,
            username: user.username,
            email: user.email,
            role: user.role,
            avatar_url: user.avatar_url
          }
        }
      });
    }
  );
};

// 获取当前用户信息
const getCurrentUser = (req, res) => {
  db.query(
    'SELECT id, username, email, role, avatar_url, created_at FROM users WHERE id = ?',
    [req.user.id],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '用户不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

module.exports = { register, login, getCurrentUser };

7. 用户控制器 (controllers/userController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有用户
const getAllUsers = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;

  // 获取用户总数
  db.query('SELECT COUNT(*) as total FROM users', (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页用户数据
    db.query(
      'SELECT id, username, email, role, avatar_url, created_at FROM users LIMIT ? OFFSET ?',
      [limit, offset],
      (err, results) => {
        if (err) {
          return res.status(500).json({
            success: false,
            message: '数据库查询错误'
            });
          }

          res.json({
            success: true,
            data: {
              users: results,
              pagination: {
                page,
                limit,
                total,
                totalPages
              }
            }
          });
        }
      );
    });
  };

  // 获取单个用户
  const getUserById = (req, res) => {
    const userId = req.params.id;

    db.query(
      'SELECT id, username, email, role, avatar_url, created_at FROM users WHERE id = ?',
      [userId],
      (err, results) => {
        if (err) {
          return res.status(500).json({
            success: false,
            message: '数据库查询错误'
          });
        }

        if (results.length === 0) {
          return res.status(404).json({
            success: false,
            message: '用户不存在'
          });
        }

        res.json({
          success: true,
          data: results[0]
        });
      }
    );
  };

  // 更新用户信息
  const updateUser = (req, res) => {
    const userId = req.params.id;
    const { username, avatar_url } = req.body;

    // 检查是否有权限更新(只能更新自己的信息或管理员)
    if (req.user.id != userId && req.user.role !== 'admin') {
      return res.status(403).json({
        success: false,
        message: '没有权限更新此用户信息'
      });
    }

    db.query(
      'UPDATE users SET username = ?, avatar_url = ? WHERE id = ?',
      [username, avatar_url, userId],
      (err, results) => {
        if (err) {
          return res.status(500).json({
            success: false,
            message: '数据库更新错误'
          });
        }

        if (results.affectedRows === 0) {
          return res.status(404).json({
            success: false,
            message: '用户不存在'
          });
        }

        res.json({
          success: true,
          message: '用户信息更新成功'
        });
      }
    );
  };

  // 删除用户
  const deleteUser = (req, res) => {
    const userId = req.params.id;

    // 只有管理员可以删除用户
    if (req.user.role !== 'admin') {
      return res.status(403).json({
        success: false,
        message: '没有权限删除用户'
      });
    }

    db.query(
      'DELETE FROM users WHERE id = ?',
      [userId],
      (err, results) => {
        if (err) {
          return res.status(500).json({
            success: false,
            message: '数据库删除错误'
          });
        }

        if (results.affectedRows === 0) {
          return res.status(404).json({
            success: false,
            message: '用户不存在'
          });
        }

        res.json({
          success: true,
          message: '用户删除成功'
        });
      }
    );
  };

  module.exports = { getAllUsers, getUserById, updateUser, deleteUser };

8. 课程控制器 (controllers/courseController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有课程
const getAllCourses = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;
  const { category, level, is_published } = req.query;

  let query = `
    SELECT c.*, u.username as instructor_name 
    FROM courses c 
    JOIN users u ON c.instructor_id = u.id
  `;
  let countQuery = 'SELECT COUNT(*) as total FROM courses c';
  let queryParams = [];
  let countParams = [];
  let conditions = [];

  // 添加筛选条件
  if (category) {
    conditions.push('c.category = ?');
    queryParams.push(category);
    countParams.push(category);
  }

  if (level) {
    conditions.push('c.level = ?');
    queryParams.push(level);
    countParams.push(level);
  }

  if (is_published !== undefined) {
    conditions.push('c.is_published = ?');
    queryParams.push(is_published === 'true');
    countParams.push(is_published === 'true');
  }

  if (conditions.length > 0) {
    query += ' WHERE ' + conditions.join(' AND ');
    countQuery += ' WHERE ' + conditions.join(' AND ');
  }

  query += ' LIMIT ? OFFSET ?';
  queryParams.push(limit, offset);

  // 获取课程总数
  db.query(countQuery, countParams, (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页课程数据
    db.query(query, queryParams, (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      res.json({
        success: true,
        data: {
          courses: results,
          pagination: {
            page,
            limit,
            total,
            totalPages
          }
        }
      });
    });
  });
};

// 获取单个课程
const getCourseById = (req, res) => {
  const courseId = req.params.id;

  db.query(
    `SELECT c.*, u.username as instructor_name 
     FROM courses c 
     JOIN users u ON c.instructor_id = u.id 
     WHERE c.id = ?`,
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

// 创建课程
const createCourse = (req, res) => {
  const { title, description, price, thumbnail_url, category, level, duration } = req.body;
  const instructorId = req.user.id;

  if (!title || !description) {
    return res.status(400).json({
      success: false,
      message: '课程标题和描述是必填项'
    });
  }

  db.query(
    'INSERT INTO courses (title, description, instructor_id, price, thumbnail_url, category, level, duration) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
    [title, description, instructorId, price, thumbnail_url, category, level, duration],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '课程创建失败'
        });
      }

      res.status(201).json({
        success: true,
        message: '课程创建成功',
        data: {
          id: results.insertId
        }
      });
    }
  );
};

// 更新课程
const updateCourse = (req, res) => {
  const courseId = req.params.id;
  const { title, description, price, thumbnail_url, category, level, duration, is_published } = req.body;

  // 检查是否是课程创建者或管理员
  db.query(
    'SELECT instructor_id FROM courses WHERE id = ?',
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在'
        });
      }

      if (results[0].instructor_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限更新此课程'
        });
      }

      db.query(
        'UPDATE courses SET title = ?, description = ?, price = ?, thumbnail_url = ?, category = ?, level = ?, duration = ?, is_published = ? WHERE id = ?',
        [title, description, price, thumbnail_url, category, level, duration, is_published, courseId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '课程更新失败'
            });
          }

          res.json({
            success: true,
            message: '课程更新成功'
          });
        }
      );
    }
  );
};

// 删除课程
const deleteCourse = (req, res) => {
  const courseId = req.params.id;

  // 检查是否是课程创建者或管理员
  db.query(
    'SELECT instructor_id FROM courses WHERE id = ?',
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在'
        });
      }

      if (results[0].instructor_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限删除此课程'
        });
      }

      db.query(
        'DELETE FROM courses WHERE id = ?',
        [courseId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '课程删除失败'
            });
          }

          res.json({
            success: true,
            message: '课程删除成功'
          });
        }
      );
    }
  );
};

// 报名课程
const enrollCourse = (req, res) => {
  const courseId = req.params.id;
  const userId = req.user.id;

  // 检查课程是否存在
  db.query(
    'SELECT id FROM courses WHERE id = ? AND is_published = TRUE',
    [courseId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '课程不存在或未发布'
        });
      }

      // 检查是否已报名
      db.query(
        'SELECT id FROM user_courses WHERE user_id = ? AND course_id = ?',
        [userId, courseId],
        (err, enrollmentResults) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '数据库查询错误'
            });
          }

          if (enrollmentResults.length > 0) {
            return res.status(409).json({
              success: false,
              message: '您已经报名此课程'
            });
          }

          // 报名课程
          db.query(
            'INSERT INTO user_courses (user_id, course_id) VALUES (?, ?)',
            [userId, courseId],
            (err, results) => {
              if (err) {
                return res.status(500).json({
                  success: false,
                  message: '报名失败'
                });
              }

              res.status(201).json({
                success: true,
                message: '报名成功'
              });
            }
          );
        }
      );
    }
  );
};

module.exports = {
  getAllCourses,
  getCourseById,
  createCourse,
  updateCourse,
  deleteCourse,
  enrollCourse
};

9. 文章控制器 (controllers/articleController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有文章
const getAllArticles = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;
  const { course_id, is_public, author_id } = req.query;

  let query = `
    SELECT a.*, u.username as author_name, c.title as course_title
    FROM articles a 
    LEFT JOIN users u ON a.author_id = u.id
    LEFT JOIN courses c ON a.course_id = c.id
  `;
  let countQuery = 'SELECT COUNT(*) as total FROM articles a';
  let queryParams = [];
  let countParams = [];
  let conditions = [];

  // 添加筛选条件
  if (course_id) {
    conditions.push('a.course_id = ?');
    queryParams.push(course_id);
    countParams.push(course_id);
  }

  if (is_public !== undefined) {
    conditions.push('a.is_public = ?');
    queryParams.push(is_public === 'true');
    countParams.push(is_public === 'true');
  }

  if (author_id) {
    conditions.push('a.author_id = ?');
    queryParams.push(author_id);
    countParams.push(author_id);
  }

  // 非管理员只能查看公开文章或自己的文章
  if (req.user.role !== 'admin') {
    conditions.push('(a.is_public = TRUE OR a.author_id = ?)');
    queryParams.push(req.user.id);
    countParams.push(req.user.id);
  }

  if (conditions.length > 0) {
    query += ' WHERE ' + conditions.join(' AND ');
    countQuery += ' WHERE ' + conditions.join(' AND ');
  }

  query += ' ORDER BY a.created_at DESC LIMIT ? OFFSET ?';
  queryParams.push(limit, offset);

  // 获取文章总数
  db.query(countQuery, countParams, (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

    // 获取分页文章数据
    db.query(query, queryParams, (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      res.json({
        success: true,
        data: {
          articles: results,
          pagination: {
            page,
            limit,
            total,
            totalPages
          }
        }
      });
    });
  );
};

// 获取单个文章
const getArticleById = (req, res) => {
  const articleId = req.params.id;

  let query = `
    SELECT a.*, u.username as author_name, c.title as course_title
    FROM articles a 
    LEFT JOIN users u ON a.author_id = u.id
    LEFT JOIN courses c ON a.course_id = c.id
    WHERE a.id = ?
  `;
  let queryParams = [articleId];

  // 非管理员只能查看公开文章或自己的文章
  if (req.user.role !== 'admin') {
    query += ' AND (a.is_public = TRUE OR a.author_id = ?)';
    queryParams.push(req.user.id);
  }

  db.query(query, queryParams, (err, results) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    if (results.length === 0) {
      return res.status(404).json({
        success: false,
        message: '文章不存在或没有访问权限'
      });
    }

    // 增加浏览次数
    if (results[0].is_public || results[0].author_id === req.user.id) {
      db.query(
        'UPDATE articles SET view_count = view_count + 1 WHERE id = ?',
        [articleId]
      );
    }

    res.json({
      success: true,
      data: results[0]
    });
  });
};

// 创建文章
const createArticle = (req, res) => {
  const { title, content, course_id, is_public, tags } = req.body;
  const authorId = req.user.id;

  if (!title || !content) {
    return res.status(400).json({
      success: false,
      message: '文章标题和内容是必填项'
    });
  }

  db.query(
    'INSERT INTO articles (title, content, author_id, course_id, is_public, tags) VALUES (?, ?, ?, ?, ?, ?)',
    [title, content, authorId, course_id, is_public || true, JSON.stringify(tags)],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '文章创建失败'
        });
      }

      res.status(201).json({
        success: true,
        message: '文章创建成功',
        data: {
          id: results.insertId
        }
      });
    }
  );
};

// 更新文章
const updateArticle = (req, res) => {
  const articleId = req.params.id;
  const { title, content, course_id, is_public, tags } = req.body;

  // 检查是否是文章作者或管理员
  db.query(
    'SELECT author_id FROM articles WHERE id = ?',
    [articleId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '文章不存在'
        });
      }

      if (results[0].author_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限更新此文章'
        });
      }

      db.query(
        'UPDATE articles SET title = ?, content = ?, course_id = ?, is_public = ?, tags = ? WHERE id = ?',
        [title, content, course_id, is_public, JSON.stringify(tags), articleId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '文章更新失败'
            });
          }

          res.json({
            success: true,
            message: '文章更新成功'
          });
        }
      );
    }
  );
};

// 删除文章
const deleteArticle = (req, res) => {
  const articleId = req.params.id;

  // 检查是否是文章作者或管理员
  db.query(
    'SELECT author_id FROM articles WHERE id = ?',
    [articleId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: '文章不存在'
        });
      }

      if (results[0].author_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({
          success: false,
          message: '没有权限删除此文章'
        });
      }

      db.query(
        'DELETE FROM articles WHERE id = ?',
        [articleId],
        (err, results) => {
          if (err) {
            return res.status(500).json({
              success: false,
              message: '文章删除失败'
            });
            }

            res.json({
              success: true,
              message: '文章删除成功'
            });
          }
        );
      }
    );
  };

  module.exports = {
    getAllArticles,
    getArticleById,
    createArticle,
    updateArticle,
    deleteArticle
  };

10. API控制器 (controllers/apiController.js)

javascript

复制代码
const db = require('../config/database');

// 获取所有API
const getAllAPIs = (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;

  // 获取API总数
  db.query('SELECT COUNT(*) as total FROM apis', (err, countResults) => {
    if (err) {
      return res.status(500).json({
        success: false,
        message: '数据库查询错误'
      });
    }

    const total = countResults[0].total;
    const totalPages = Math.ceil(total / limit);

  // 获取分页API数据
  db.query(
    'SELECT * FROM apis LIMIT ? OFFSET ?',
    [limit, offset],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      res.json({
        success: true,
        data: {
          apis: results,
          pagination: {
            page,
            limit,
            total,
            totalPages
          }
        }
      });
    }
  );
});
};

// 获取单个API
const getAPIById = (req, res) => {
  const apiId = req.params.id;

  db.query(
    'SELECT * FROM apis WHERE id = ?',
    [apiId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: '数据库查询错误'
        });
      }

      if (results.length === 0) {
        return res.status(404).json({
          success: false,
          message: 'API不存在'
        });
      }

      res.json({
        success: true,
        data: results[0]
      });
    }
  );
};

// 创建API
const createAPI = (req, res) => {
  const { name, endpoint, method, description, parameters, response_example, requires_auth } = req.body;

  if (!name || !endpoint) {
    return res.status(400).json({
      success: false,
      message: 'API名称和端点是必填项'
    });
  }

  db.query(
    'INSERT INTO apis (name, endpoint, method, description, parameters, response_example, requires_auth) VALUES (?, ?, ?, ?, ?, ?, ?)',
    [name, endpoint, method, description, JSON.stringify(parameters), JSON.stringify(response_example), requires_auth],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: 'API创建失败'
        });
      }

      res.status(201).json({
        success: true,
        message: 'API创建成功',
        data: {
          id: results.insertId
        }
      });
    }
  );
};

// 更新API
const updateAPI = (req, res) => {
  const apiId = req.params.id;
  const { name, endpoint, method, description, parameters, response_example, requires_auth } = req.body;

  db.query(
    'UPDATE apis SET name = ?, endpoint = ?, method = ?, description = ?, parameters = ?, response_example = ?, requires_auth = ? WHERE id = ?',
    [name, endpoint, method, description, JSON.stringify(parameters), JSON.stringify(response_example), requires_auth, apiId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: 'API更新失败'
        });
      }

      if (results.affectedRows === 0) {
        return res.status(404).json({
          success: false,
          message: 'API不存在'
        });
      }

      res.json({
        success: true,
        message: 'API更新成功'
      });
    }
  );
};

// 删除API
const deleteAPI = (req, res) => {
  const apiId = req.params.id;

  db.query(
    'DELETE FROM apis WHERE id = ?',
    [apiId],
    (err, results) => {
      if (err) {
        return res.status(500).json({
          success: false,
          message: 'API删除失败'
        });
      }

      if (results.affectedRows === 0) {
        return res.status(404).json({
          success: false,
          message: 'API不存在'
        });
      }

      res.json({
        success: true,
        message: 'API删除成功'
      });
    }
  );
};

module.exports = {
  getAllAPIs,
  getAPIById,
  createAPI,
  updateAPI,
  deleteAPI
};

11. 路由配置

创建各个模块的路由文件:

认证路由 (routes/auth.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { register, login, getCurrentUser } = require('../controllers/authController');
const { authenticateToken } = require('../middleware/auth');

router.post('/register', register);
router.post('/login', login);
router.get('/me', authenticateToken, getCurrentUser);

module.exports = router;
用户路由 (routes/users.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { getAllUsers, getUserById, updateUser, deleteUser } = require('../controllers/userController');
const { authenticateToken, authorize } = require('../middleware/auth');

router.get('/', authenticateToken, authorize('admin'), getAllUsers);
router.get('/:id', authenticateToken, getUserById);
router.put('/:id', authenticateToken, updateUser);
router.delete('/:id', authenticateToken, authorize('admin'), deleteUser);

module.exports = router;
课程路由 (routes/courses.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { 
  getAllCourses, 
  getCourseById, 
  createCourse, 
  updateCourse, 
  deleteCourse, 
  enrollCourse 
} = require('../controllers/courseController');
const { authenticateToken, authorize } = require('../middleware/auth');

router.get('/', getAllCourses);
router.get('/:id', getCourseById);
router.post('/', authenticateToken, authorize('teacher', 'admin'), createCourse);
router.put('/:id', authenticateToken, updateCourse);
router.delete('/:id', authenticateToken, deleteCourse);
router.post('/:id/enroll', authenticateToken, enrollCourse);

module.exports = router;
文章路由 (routes/articles.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { 
  getAllArticles, 
  getArticleById, 
  createArticle, 
  updateArticle, 
  deleteArticle 
} = require('../controllers/articleController');
const { authenticateToken } = require('../middleware/auth');

router.get('/', authenticateToken, getAllArticles);
router.get('/:id', authenticateToken, getArticleById);
router.post('/', authenticateToken, createArticle);
router.put('/:id', authenticateToken, updateArticle);
router.delete('/:id', authenticateToken, deleteArticle);

module.exports = router;
API路由 (routes/apis.js)

javascript

复制代码
const express = require('express');
const router = express.Router();
const { 
  getAllAPIs, 
  getAPIById, 
  createAPI, 
  updateAPI, 
  deleteAPI 
} = require('../controllers/apiController');
const { authenticateToken, authorize } = require('../middleware/auth');

router.get('/', getAllAPIs);
router.get('/:id', getAPIById);
router.post('/', authenticateToken, authorize('admin'), createAPI);
router.put('/:id', authenticateToken, authorize('admin'), updateAPI);
router.delete('/:id', authenticateToken, authorize('admin'), deleteAPI);

module.exports = router;

12. 主应用文件 (app.js)

javascript

复制代码
const express = require('express');
const cors = require('cors');
require('dotenv').config();

const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/users');
const courseRoutes = require('./routes/courses');
const articleRoutes = require('./routes/articles');
const apiRoutes = require('./routes/apis');

const app = express();
const PORT = process.env.PORT || 3000;

// 中间件
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 路由
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/courses', courseRoutes);
app.use('/api/articles', articleRoutes);
app.use('/api/apis', apiRoutes);

// 健康检查端点
app.get('/health', (req, res) => {
  res.json({ 
    success: true, 
    message: '教育平台API运行正常',
    timestamp: new Date().toISOString()
  });
});

// 404处理
app.use('*', (req, res) => {
  res.status(404).json({
    success: false,
    message: 'API端点不存在'
  });
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    success: false,
    message: '服务器内部错误'
  });
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`教育平台API服务器运行在端口 ${PORT}`);
});

module.exports = app;

13. Package.json 脚本配置

json

复制代码
{
  "name": "education-platform-api",
  "version": "1.0.0",
  "description": "教育平台API服务",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "express": "^4.18.2",
    "mysql2": "^3.6.0",
    "bcryptjs": "^2.4.3",
    "jsonwebtoken": "^9.0.2",
    "cors": "^2.8.5",
    "dotenv": "^16.3.1"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  },
  "keywords": ["education", "api", "nodejs", "mysql"],
  "author": "Your Name",
  "license": "MIT"
}

API使用说明

1. 认证相关API

  • POST /api/auth/register - 用户注册

  • POST /api/auth/login - 用户登录

  • GET /api/auth/me - 获取当前用户信息

2. 用户管理API

  • GET /api/users - 获取所有用户(仅管理员)

  • GET /api/users/:id - 获取指定用户信息

  • PUT /api/users/:id - 更新用户信息

  • DELETE /api/users/:id - 删除用户(仅管理员)

3. 课程管理API

  • GET /api/courses - 获取所有课程

  • GET /api/courses/:id - 获取指定课程详情

  • POST /api/courses - 创建课程(教师和管理员)

  • PUT /api/courses/:id - 更新课程信息

  • DELETE /api/courses/:id - 删除课程

  • POST /api/courses/:id/enroll - 报名课程

4. 文章管理API

  • GET /api/articles - 获取所有文章

  • GET /api/articles/:id - 获取指定文章详情

  • POST /api/articles - 创建文章

  • PUT /api/articles/:id - 更新文章

  • DELETE /api/articles/:id - 删除文章

5. API文档管理

  • GET /api/apis - 获取所有API文档

  • GET /api/apis/:id - 获取指定API文档

  • POST /api/apis - 创建API文档(仅管理员)

  • PUT /api/apis/:id - 更新API文档(仅管理员)

  • DELETE /api/apis/:id - 删除API文档(仅管理员)

部署和运行

  1. 安装依赖:

bash

复制代码
npm install
  1. 创建MySQL数据库并导入SQL结构

  2. 配置环境变量(.env文件)

  3. 启动服务器:

bash

复制代码
# 开发模式
npm run dev

# 生产模式
npm start

安全注意事项

  1. 在生产环境中,确保使用强密码和安全的JWT密钥

  2. 考虑使用HTTPS加密通信

  3. 实施速率限制防止API滥用

  4. 定期更新依赖包以修复安全漏洞

  5. 对用户输入进行严格的验证和清理

这个API系统提供了教育平台的核心功能,您可以根据需要进一步扩展和优化。

相关推荐
05Nuyoah2 小时前
Day 02 HTML的基础
前端·javascript·css·html·firefox·jquery·html5
不宕机的小马达2 小时前
【Web前端|第一篇】HTML、CSS与JavaScript
前端·css·html
小红帽6152 小时前
HTML,CSS,JS三者的功能及联系
javascript·css·html
路光.2 小时前
统一配置管理根据不同域名展现不同信息或相近信息 Vue3类单例模式封装
前端·单例模式·typescript·vue3
一点一木3 小时前
⚡ GitHub 热榜速报 | 2025 年 09 月 第 3 周
前端·人工智能·github
^辞安3 小时前
什么是Mvcc
java·数据库·mysql
GISer_Jing3 小时前
携程HR面(准备)
前端·javascript·面试
Larry_Yanan3 小时前
QML学习笔记(五)QML新手入门其三:使用Row和Colunm进行简单布局
前端·笔记·qt·学习·ui
Nicholas683 小时前
flutter视频播放器video_player_avfoundation之FVPVideoPlayerPlugin(一)
前端