基于NodeJs+Express+MySQL 实现的个人博客完整项目

发布于:2022-11-16 ⋅ 阅读:(887) ⋅ 点赞:(0)

目录 

一、创建项目并初始化

项目结构

二、安装项目所需要的包

三、创建所需要的数据库表

表 user 用于存放账户密码

表 notepad 用于存放文章数据

表 leaving 用于存放留言板的数据

三、编写app.js文件

1、导入所有需要的包

2、创建web服务器

3、创建db文件夹,在文件夹里面创建mysql.js 注册连接数据库的路由

4、配置中间件和sssion认证

6、开始接口的配置

四、创建个人博客的页面

五、展示个人博客页面​​​​​​​

实现的功能: 多用户登录,注册,session认证,通过数据库展示文章列表、文章详情,动态生成文章页面,文章分页查询,留言板功能

一、创建项目并初始化

项目结构

​​​​​​​​​​​​​​

二、安装项目所需要的包

npm install msyql

npm install express

npm install ejs

三、创建所需要的数据库表

表 user 用于存放账户密码

CREATE TABLE user  (
  username varchar(100),
  password varchar(100)
) 

表 notepad 用于存放文章数据

CREATE TABLE notepad  (
  id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(100),
  title varchar(100),
  content varchar(9999),
  time varchar(99),
  PRIMARY KEY (`id`)
) 

表 leaving 用于存放留言板的数据

CREATE TABLE leaving  (
  username varchar(100),
  content varchar(9999),
  time varchar(100)
) 

三、编写app.js文件

1、导入所有需要的包

// 导入express
const express = require('express')
var bodyParser = require('body-parser');
// 导入数据库操作模块
const db = require('./db/mysql')
// 导入 session 中间件
var session = require('express-session')
const ejs=require("ejs");
const fs=require("fs");

2、创建web服务器

// 创建web服务器
const app = express()

// 调用app.listen(端口号, 启动成功后的回调函数)  启动服务器
app.listen(80, () => {
    console.log('127.0.0.1');
})

3、创建db文件夹,在文件夹里面创建mysql.js 注册连接数据库的路由

mysql.js

// 1. 导入 mysql 模块
const mysql = require('mysql')
// 2. 建立与 MySQL 数据库的连接关系
const db = mysql.createPool({
  host: 'localhost', // 数据库的 IP 地址
  user: 'root', // 登录数据库的账号
  password: 'root', // 登录数据库的密码
  database: 'movies', // 指定要操作哪个数据库
})

module.exports = db

4、配置中间件和sssion认证

app.use(session({
    secret: 'keyboard cat',  // secret 属性的值可以为任意字符串
    resave: false,           // 固定写法
    saveUninitialized: true  // 固定写法
}))
// 中间件定义post传递的格式
app.use(express.static('./pages'))
// app.use(express.static('./public'))
app.use(express.json())
app.use(bodyParser.urlencoded({extended:true}));//Context-Type 为application/x-www-form-urlencoded 时 返回的对象是一个键值对,当extended为false的时候,键值对中的值就为'String'或'Array'形式,为true的时候,则可为任何数据类型。
app.use(bodyParser.json());//用于解析json 会自动选择最为适宜的解析方式

6、开始接口的配置

登录接口

app.post('/api/getUsername', function(req, res) {
    // /配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");  

    const sqlStr = 'SELECT username,password FROM user;'
    db.query(sqlStr, (err, results) => {
    // 查询数据失败
    if (err) return console.log(err.message)

    console.log(results);
    // 查询数据成功
    // 注意:如果执行的是 select 查询语句,则执行的结果是数组
    let userData = results.map(item => item.username)
    let pwdData = results.map(item => item.password)

    if (userData.indexOf(req.body.username) == -1) {
        res.send({
            status: 400,
            message: '该用户不存在',
        })
    } else {
        // 用户存在,判断密码
        if (req.body.password == pwdData[userData.indexOf(req.body.username)]) {

            // 将用户的信息,存储到Session中
            req.session.user = req.body
            // 将用户的登陆状态,存储到Session中
            req.session.islogin = true

            res.send({
                status: 200,
                message: '登录成功',
            })

        } else {
            res.send({
                status: 401,
                message: '登录失败,密码不正确',
            })
        }

    }
    }) 
})

注册接口

app.post('/api/register', function(req, res) {
        // /配置请求的域名,*代表任意
        res.header("Access-Control-Allow-Origin", "*");   
        // 支持跨域请求类型
        res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
        //配置请求头信息,包含字符集等等 
        res.header("Content-Type", "application/json;charset=utf-8");  

        // 判断数据库里是否已经存在该用户名,如果没有则注册,如果有则提示重新注册
        const sqlStr = 'SELECT username FROM user;'
        db.query(sqlStr, (err, results) => {
        // 查询数据失败
        if (err) {
            return console.log(err.message)
        } else {
            let userData = results.map(item => item.username)
            // 判断注册的账号是否与数据库里的账号相同 -1 代表数据库里不存在此数据
            if (userData.indexOf(req.body.username) == -1) {
                const sqlStr = `INSERT into user (username, password) VALUES ( '${req.body.username}', '${req.body.password}' );`
                db.query(sqlStr, (err, results) => {
                // 查询数据失败
                if (err) {
                    return console.log(err.message)
                } else {
                    res.send({
                        status: 200,
                        message: '注册成功'
                    })
                }
            })
            } else {
                res.send({
                    status: 400,
                    message: '账号已存在,请重新注册'
                })
            }
        }
        })
})

获取用户姓名的接口

app.get('/api/username', (req, res) => {
    // /配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");
    // 判断用户是否登录
    if ( !req.session.islogin) {
        return res.send({
            status: 404,
            msg: 'fail'
        })
    }

    res.send({
        status: 200,
        msg: 'success',
        username: req.session.user.username
    })
})

退出登录的接口

app.post('/api/logout', (req, res) => {
    // /配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");
    // 清空当前客户端对应的 session 信息
    req.session.destroy()
    res.send({
        status: 200,
        msg: '退出登陆成功',
    })
})

获取文章列表

app.get('/api/getArticle', (req, res) => {
        // 配置请求的域名,*代表任意
        res.header("Access-Control-Allow-Origin", "*");   
        // 支持跨域请求类型
        res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
        //配置请求头信息,包含字符集等等 
        res.header("Content-Type", "application/json;charset=utf-8");

        const sqlStr = 'SELECT * FROM Notepad;'
        db.query(sqlStr, (err, results) => {
        // 查询数据失败
        if (err) {
            return console.log(err.message)
        } else {
            res.send({
                status: 200,
                message: '获取文章成功',
                data: results,
                username: req.session.user.username
            })
        }
    })
})

新增文章接口

app.post('/api/addArticle', (req, res) => {
    // 配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");

    let time = new Date()

    const sqlStr = `INSERT into Notepad VALUES (null, '${req.session.user.username}', '${req.body.title}', '${req.body.content}', '${time.toLocaleString()}');`
    db.query(sqlStr, (err, results) => {
    // 查询数据失败
    if (err) {
        return console.log(err.message)
    } else {
        res.send({
            status: 201,
            message: '添加文章成功',
            data: {}
        })
    }
})
})

查找文章接口

app.post('/api/search', (req, res) => {
        // 配置请求的域名,*代表任意
        res.header("Access-Control-Allow-Origin", "*");   
        // 支持跨域请求类型
        res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
        //配置请求头信息,包含字符集等等 
        res.header("Content-Type", "application/json;charset=utf-8");
    
        let time = new Date()
    
        const sqlStr = `SELECT * FROM notepad where id=${req.body.id};`
        db.query(sqlStr, (err, results) => {
        // 查询数据失败
        if (err) {
            return console.log(err.message)
        } else {
            res.send({
                status: 200,
                message: "查找成功",
                data: results 
            })
        }
        })
})

动态获取接口用于渲染文章

app.get('/:_id', (req, res) => {

        var num = req.params._id
        num = num.replace('_id', '')
        num = parseInt(num)
        
        // 根据id查找相应的数据 
        const sqlStr = `SELECT * FROM Notepad where id=${num};`
        db.query(sqlStr, (err, results) => {
        // 查询数据失败
        if (err) {
            return console.log(err.message)
        } else {
            res.render("index.ejs",{
                username: results[0].username,
                title:results[0].title,
                content: results[0].content,
                time: results[0].time,
            })
        }})
})

获取留言接口 

// 获取评论
app.get('/api/getlist',(req,res)=>{
    // /配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");  
    const sqlStr = 'select * from leaving'
    db.query(sqlStr, (err, results) => {
    // 失败
    if (err) {
        return console.log(err.message)
    } 
    res.send({
        code: 200,
        msg: '获取评论列表成功',
        data: results,
        username: req.session.user.username
    })
})
}) 

新增留言接口

// 增加评论
app.post('/api/addlist', (req, res) => {
    // /配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");  

    let time = new Date()
    // 获取到客户端通过查询字符串,发送到服务器的数据
    // const sqlStr3 = `INSERT INTO leaving VALUES ('${body.text}');`
    const sqlStr = `INSERT INTO leaving VALUES ('${req.session.user.username}','${req.body.content}','${time.toLocaleString()}');`
    db.query(sqlStr, (err, results) => {
    // 失败
    if (err) {
        return console.log(err.message)
    } 
    res.send({
        status: 200,
        msg: '添加数据成功',
        data: results,
        username: req.session.user.username
    })
    })
})

分页查询接口 

app.post('/api/limit', (req, res) => {
    // /配置请求的域名,*代表任意
    res.header("Access-Control-Allow-Origin", "*");   
    // 支持跨域请求类型
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    //配置请求头信息,包含字符集等等 
    res.header("Content-Type", "application/json;charset=utf-8");  

    const sqlStr = `SELECT * FROM notepad LIMIT 10 OFFSET ${req.body.num};`
    db.query(sqlStr, (err, results) => {
    // 失败
    if (err) {
        return console.log(err.message)
    } 
    res.send({
        status: 200,
        msg: '分页查询成功',
        data: results,
    })
    })
})

四、创建个人博客的页面

登录页面   login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./jQuery.mini.js"></script>
    <script src="./axios.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            height: 100%;
        }
        body {
            height: 100%;
            background-image: url(../public/wallhaven-6k3lk6.jpg);
        }
        .container {
            height: 100%;
            background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);
        }
        .login-wrapper {
            background-color: #fff;
            width: 358px;
            height: 588px;
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 200px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }
        .login,.register {
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
            color: #fff;
        }
        .msg {
            text-align: center;
            line-height: 88px;
        }
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }

        .box {
            width: 5.333333333333333rem;
            height: 4.8rem;
            font-size: 1.173333333333333rem;
        }

        @media (width:375px) {
            html {
                font-size: 37.5px;
            }
        }

        /* 按钮当鼠标悬浮时的状态: */
        .btn:hover{
            transform: translateY(-3px);
            box-shadow: 0 10px 20px rgba(0,0,0,0.2);
        }

        .btn {
            transition: all .2s ;
            border-radius: 10px;
        }

        .tankuang_user{
            display: none;
            position: relative;
            background: #a6c1ee;
            z-index: 99;
            width: 250px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            border-radius: 5px;
            top: 40%;
            left: 50%;
            transform: translate(-50%, -50%);
        } 


        .tankuang{
            display: none;
            position: relative;
            background: #a6c1ee;
            z-index: 99;
            width: 250px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            border-radius: 5px;
            top: 40%;
            left: 50%;
            transform: translate(-50%, -50%);
        } 

        
    </style>
</head>
<body>

    <div class="tankuang">
        <div id="header">
          <span style="color:#ffffff; font-size:20px;margin: auto;line-height: 50px;" id="layer_msg">帐号不存在,请先注册</span>
        </div>
    </div>

    <div class="container">
        <div class="login-wrapper">
            <div class="header">HELLO HANG</div>
            <div class="form-wrapper">
                <form action="" id="form_login">
                    <input type="text" name="username" placeholder="账号" class="input-item" id="user">
                    <input type="password" name="password" placeholder="密码" class="input-item" id="pwd">
                    <div class="login btn">登录</div>
                    <div class="register btn">注册</div>
                </form>
            </div>
            <div class="msg">
                有问题?
                <a href="http://wpa.qq.com/msgrd?v=3&uin=26198573&site=qq&menu=13017388854">请联系站长</a>
            </div>
        </div>
    </div>

    <script>
        $(function() {
            $('.login').click(function(e){
                e.preventDefault()
                var data = $('#form_login').serialize()
                $.post(
                    'http://127.0.0.1/api/getUsername',
                    data,
                    function(res) {
                        if (res.status == 400){
                            document.querySelector('.tankuang').style.display = 'block',
                            document.querySelector('.container').style.marginTop = '-100px'
                            $('#layer_msg').text('账号不存在,请先注册')
                            setTimeout(function(){
                                document.querySelector('.tankuang').style.display = 'none',
                                document.querySelector('.container').style.marginTop = '0px'
                            },1000)
                        } else if (res.status == 401) {
                            document.querySelector('.tankuang').style.display = 'block',
                            document.querySelector('.container').style.marginTop = '-100px'
                            $('#layer_msg').text('密码错误,请重新登录')
                            setTimeout(function(){
                                document.querySelector('.tankuang').style.display = 'none',
                                document.querySelector('.container').style.marginTop = '0px'
                            },1000)
                        } else {
                            location.href = './index.html'
                        }
                    }
                )
            })

            $(document).keyup(function(e){
                e.preventDefault()
                if (e.keyCode == '13') {
                    var data = $('#form_login').serialize()
                    $.post(
                        'http://127.0.0.1/api/getUsername',
                        data,
                        function(res) {
                            if (res.status == 400){
                                document.querySelector('.tankuang').style.display = 'block',
                                document.querySelector('.container').style.marginTop = '-100px'
                                $('#layer_msg').text('账号不存在,请先注册')
                                setTimeout(function(){
                                    document.querySelector('.tankuang').style.display = 'none',
                                    document.querySelector('.container').style.marginTop = '0px'
                                },1000)
                            } else if (res.status == 401) {
                                document.querySelector('.tankuang').style.display = 'block',
                                document.querySelector('.container').style.marginTop = '-100px'
                                $('#layer_msg').text('密码错误,请重新登录')
                                setTimeout(function(){
                                    document.querySelector('.tankuang').style.display = 'none',
                                    document.querySelector('.container').style.marginTop = '0px'
                                },1000)
                            } else {
                                location.href = './index.html'
                            }
                        }
                    )
                }
 
            })

            $('.register').click(function(e){
                e.preventDefault()
                var data = $('#form_login').serialize()
                $.post(
                    'http://127.0.0.1/api/register',
                    data,
                    function(res) {
                        console.log(res);
                        if(res.status == 200) {
                            document.querySelector('.tankuang').style.display = 'block',
                            document.querySelector('.container').style.marginTop = '-100px'
                            $('#layer_msg').text('注册成功')
                            setTimeout(function(){
                                document.querySelector('.tankuang').style.display = 'none',
                                document.querySelector('.container').style.marginTop = '0px'
                            },1000)
                        } else {
                            document.querySelector('.tankuang').style.display = 'block',
                            document.querySelector('.container').style.marginTop = '-100px'
                            $('#layer_msg').text('账号已存在,请重新注册')
                            setTimeout(function(){
                                document.querySelector('.tankuang').style.display = 'none',
                                document.querySelector('.container').style.marginTop = '0px'
                            },1000)
                        }
                    }
                )
            })
        })
    </script>
</body>
</html>

博客主页 index.html  可进行分页查询

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./jQuery.mini.js"></script>
  <link rel="stylesheet" href="./bootstrap.css">
  <script src="./axios.js"></script>
  <style>

    body {
			background-repeat: no-repeat;
			background-size: cover;
    }

    .navbar {
      z-index: 99;
    }

    .name {
      display: flex;
      justify-content: space-between;
      float: right;
      width: 26rem;
      height: 100%;
      font-size: .875rem;
      color: #696767;
      /* background-color: aqua; */
    }

    .collapse {
      width: 250px;
      display: flex;
      justify-content: space-around;
    }

    .container {
        width: 100%;
        height: 100%;
    }

    .listbig {
      font-size: 18px;
    }

    .list_a {
      font-size: 16px;
    }

    .limit {
      text-align: center;
    }

    .list-group {
      height: 550px;
    }

  </style>
</head>
<body>

    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <div class="navbar-header">
          <a class="navbar-brand" href="#">文章列表</a>
        </div>
        <ul class="nav navbar-nav">
          <li><a href="./addarticle.html">添加文章 </a></li>
          <li><a href="./leaving.html">留言板 </a></li>
        </ul>
        <div class="collapse  navbar-right" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav ">
            <li><a href="#" class="user"></a></li>
          </ul>
          <ul class="nav navbar-nav ">
            <li><a href="#" id="btnLogout">退出登录</a></li>
          </ul>
        </div>
      </div>
    </nav>
    <div class="list-group">
      <a href="#" class="list-group-item active listbig">
        文章列表
      </a>
    </div>

    <nav aria-label="Page navigation" class="limit">
      <ul class="pagination">
        <li><a href="#" id="1">1</a></li>
        <li><a href="#" id="2">2</a></li>
        <li><a href="#" id="3">3</a></li>
        <li><a href="#" id="4">4</a></li>
        <li><a href="#" id="5">5</a></li>
      </ul>
    </nav>

  <script>
    $(function () { 
      // 点击文章列表切换页面
      $('.list-group').on('click', 'a', function(e){
        // 获取点击文字的id值
        var list_id = e.target.id 
        // 获取文章列表进行文章筛选
        axios({
          method: 'GET',
          url: 'http://127.0.0.1/api/getArticle',
        }).then(function(res) {
            // console.log(list_id);
            var data = {id: list_id}
              // 筛选文章
              axios({
                method: 'POST',
                data,
                url: 'http://127.0.0.1/api/search',
              }).then(function(res) {
                if (res.data.status == 200) {
                  console.log(res.data);
                  console.log(res.data.data.content);
                } else {
                  alert('文章不存在!')
                }
              })
              
          })
      })

      // 获取用户名判断是否登录
      $.get(
        'http://127.0.0.1/api/username',
        function(res) {
          // console.log(res);
          if (res.status == 200) {  
            let username = res.username
            $('.user').text(username)
            let data = {num: 0}
                  // 获取文章列表
                  axios({
                    method: 'POST',
                    data,
                    url: 'http://127.0.0.1/api/limit',
                  }).then(function(res) {
                    // 将获取到的文章渲染到页面 作为初始页面
                    res.data.data.map(item => {
                      let a = `<a href="${item.id}_id" target="_blank" class="list-group-item  list_a" id="${item.id}">${item.title} <div class="name"> <span class="username">用户 ${item.username}</span> <span class="time">发布于 ${item.time}</span></div> </a>`
                      $('.list-group').append(a)
                    })
                  })
          } else {
            alert('请先完成登录')
            location.href = './login.html'
          }
        }
      )

      // 退出登录
      $('#btnLogout').click(function() {
        $.post(
          'http://127.0.0.1/api/register',
          function(res) {
            if (res.status == 200) {
              // 如果 status 为 200,则表示退出成功,重新跳转到登录页面
              location.href = './login.html'
            }
          }
        )
      })

      // 分页查询
      $('.limit').on('click', 'li', function(e){
        let data = {num: parseInt((e.target.id-1) * 10)}
        axios({
            method: 'POST',
            data,
            url: 'http://127.0.0.1/api/limit',
        }).then(function(res) {
            if (res.data.status == 200) {
                  $('.list-group').empty('')
                  $('.list-group').append('<a href="#" class="list-group-item active listbig">文章列表</a>')
                  res.data.data.map(item => {
                  let a = `<a href="${item.id}_id" target="_blank" class="list-group-item  list_a" id="${item.id}">${item.title} <div class="name"> <span class="username">用户 ${item.username}</span> <span class="time">发布于 ${item.time}</span></div> </a>`
                  $('.list-group').append(a)
                  })
            } else {
              alert('查询失败!')
            }
        })
      })

    })
  </script>
</body>

</html>

添加文章的页面 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./jQuery.mini.js"></script>
    <link rel="stylesheet" href="./bootstrap.css">
    <script src="./axios.js"></script>

    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            height: 1200px;
        }
        body {
            height: 1200px;
        }
        .container {
            width: 100%;
            height: 100%;
            /* background-image: linear-gradient(to right, #26453d, #0b1013); */
            /* background-image: linear-gradient(to right, #a7a8bd, #2e317c); */
            background-image: linear-gradient(to bottom, #a7a8bd, #2e317c);

        }
        .login-wrapper {
            background-color: #fff;
            width: 700px;
            height: 900px;
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            text-align: center;
            margin: 0 auto;
            /* left: 50%;
            top: 50%;
            transform: translate(-50%, -50%); */
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 80px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }

        /* .navbar {
          margin-top: -100px;
        } */

        .btn {
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
        }
        .msg {
            text-align: center;
            line-height: 200px;
        }
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }

        /* 按钮当鼠标悬浮时的状态: */
        .btn:hover{
            transform: translateY(-3px);
            box-shadow: 0 10px 20px rgba(0,0,0,0.2);
        }

        .btn {
            transition: all .2s ;
            border-radius: 10px;
        }

      .tankuang{
        display: none;
        position: relative;
        background: #305a56;
        z-index: 99;
        width: 200px;
        height: 100px;
        text-align: center;
        line-height: 100px;
        border-radius: 5px;
        top: 30%;
        left: 50%;
        transform: translate(-50%, -50%);
      } 
    </style>
</head>
<body>

  <div class="tankuang">
    <div id="header">
      <span style="color:#ffffff; font-size:20px;margin: auto;line-height: 50px;" id="layer_msg">提交成功...</span>
    </div>
  </div>

  <nav class="navbar navbar-default">
    <div class="container-fluid">
      <div class="navbar-header">
        <a class="navbar-brand" href="./index.html">返回主页</a>
      </div>
      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
        <ul class="nav navbar-nav navbar-right">
          <li><a href="#" id="btnLogout">退出登录</a></li>
        </ul>
      </div>
    </div>
  </nav>

    <div class="container">
        <div class="login-wrapper">
            <div class="header">写文章</div>
                <form id="form_add">
                  <div class="form-wrapper">
                    <div class="input-group">
                      <span class="input-group-addon" id="basic-addon3" >文章标题</span>
                      <input type="text" class="form-control" id="basic-url" name="title" aria-describedby="basic-addon3">
                    </div>
                    <h3>文章内容</h3>
                    <textarea class="form-control" rows="18" name="content" style="font-size: 16px;"></textarea>
                    <div class="btn">发布文章</div>
                </div>
                </form>
            <div class="msg">
              有问题?
              <a href="http://wpa.qq.com/msgrd?v=3&uin=26198573&site=qq&menu=13017388854">请联系站长</a>
          </div>
        </div>
    </div>

    <script>
        $(function(){
        // 发布文章
          $('.btn').click(function(e){
              e.preventDefault()
              var data = $('#form_add').serialize()
              axios({
                method: 'POST',
                url: 'http://127.0.0.1/api/addArticle',
                data
              }).then(function(res){
                if (res.data.status == 201) {
                  document.querySelector('.tankuang').style.display = 'block',
                  document.querySelector('.navbar').style.marginTop = '-100px'
                  setTimeout(function(){
                    location.href = './index.html'
                  },800)
                } else {
                  alert('文章发布失败')
                }
              })
          })

          // 获取用户名判断是否登录
          $.get(
            'http://127.0.0.1/api/username',
            function(res) {
              console.log(res);
              if (res.status == 200) {
                // alert('登陆成功!欢迎'+res.username)
              } else {
                alert('请先完成登录')
                location.href = './login.html'
              }
            }
          )

          // 退出登录
          $('#btnLogout').click(function() {
            $.post(
              'http://127.0.0.1/api/register',
              function(res) {
                if (res.status == 200) {
                  // 如果 status 为 200,则表示退出成功,重新跳转到登录页面
                  location.href = './login.html'
                }
              }
            )
          })
        })
    </script>
</body>
</html>

 渲染文章的页面,使用的ejs     index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./jQuery.mini.js"></script>
    <script src="./axios.js"></script>
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            height: 1400px;
        }
        body {
            height: 1400px;
        }
        .container {
            height: 100%;
            /* background-image: linear-gradient(to right, #999999, #330867); */
            /* background-image: linear-gradient(to right, #b5caa0, #1b813e); */
            background-image: linear-gradient(to bottom, #91b493, #096148);
        }
        .login-wrapper {
            background-color: #fff;
            width: 800px;
            /* height: 1200px; */
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            text-align: center;
            margin: 0 auto;
            /* left: 50%;
            top: 50%;
            transform: translate(-50%,-50%); */

            /* table-layout:fixed;  */
            /* word-break:break-all;  */
            /* overflow:hidden; */
            /* word-break: break-all;word-wrap: break-word; */

        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 100px;
        }

        .other {
            font-size: 14px;
            line-height: 30px;
            color: #696767;;
        }

        /* div{ word-wrap: break-word; word-break: normal;} */

        .content {
            overflow: hidden;
            text-indent: 2rem;
            text-align: left;
            margin: 30px auto;
            width: 700px;
            /* height: 900px; */
            line-height: 1rem;
            /* background-color: #abc1ee; */
            word-break: break-all;
            word-wrap: break-word;
            table-layout:fixed;
        }


        .msg {
            text-align: center;
            line-height: 200px;
        }
        
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="login-wrapper">
            <div class="header"><%- title %></div>
            <div class="other">
                <div class="name">用户: <%- username %></div>
                <div class="time"><%- time %></div>
            </div>
            <div class="content">
                
                |<pre><%- content %></pre>
            </div>
            <div class="msg">
                有问题?
                <a href="http://wpa.qq.com/msgrd?v=3&uin=26198573&site=qq&menu=13017388854">请联系站长</a>
            </div>
        </div>
    </div>

    <script>
            // 获取用户名判断是否登录
            $.get(
                'http://127.0.0.1/api/username',
                function(res) {
                console.log(res);
                if (res.status == 200) {
                    // alert('登陆成功!欢迎'+res.username)
                } else {
                    alert('请先完成登录')
                    location.href = './login.html'
                }
                }
            )

    </script>

</body>
</html>

留言板,用于展示留言,添加留言

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./jQuery.mini.js"></script>
    <link rel="stylesheet" href="./bootstrap.css">
    <script src="./axios.js"></script>

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .container {
            width: 100%;
            height: 100%;
            background-image: linear-gradient(to bottom, #f9f4dc, #ecb88a);

        }
        .login-wrapper {
            background-color: #fff;
            width: 700px;
            /* height: 900px; */
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            text-align: center;
            margin: 0 auto;
            /* left: 50%;
            top: 50%;
            transform: translate(-50%, -50%); */
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 80px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }

        .btn {
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
        }
        .msg {
            text-align: center;
            line-height: 200px;
        }
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }

        /* 按钮当鼠标悬浮时的状态: */
        .btn:hover{
            transform: translateY(-3px);
            box-shadow: 0 10px 20px rgba(0,0,0,0.2);
        }

        .btn {
            transition: all .2s ;
            border-radius: 10px;
        }

    </style>
</head>
<body>

    <div class="tankuang">
        <div id="header">
          <span style="color:#ffffff; font-size:20px;margin: auto;line-height: 50px;" id="layer_msg"></span>
        </div>
    </div>

    <nav class="navbar navbar-default">
        <div class="container-fluid">
          <div class="navbar-header">
            <a class="navbar-brand" href="./index.html">返回主页</a>
          </div>
          <div class="collapse navbar-right" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav ">
                <li><a href="#" class="user">123123</a></li>
            </ul>
            <ul class="nav navbar-nav">
              <li><a href="#" id="btnLogout">退出登录</a></li>
            </ul>
          </div>
        </div>
      </nav>
    
        <div class="container">
            <div class="login-wrapper">
                <div class="header">留言板</div>
                    <form id="form_add">
                      <div class="form-wrapper">
                        <ul class="list-group">
                            <!-- 留言内容 -->
                        </ul>
                        <!-- <h3>文章内容</h3> -->
                        <textarea class="form-control" rows="10" name="content" style="font-size: 16px;"></textarea>
                        <div class="btn">发布留言</div>
                    </div>
                    </form>
                <div class="msg">
                  有问题?
                  <a href="http://wpa.qq.com/msgrd?v=3&uin=26198573&site=qq&menu=13017388854">请联系站长</a>
              </div>
            </div>
        </div>
    
    <script>
        $(function(){
        // 发布留言
            $('.btn').click(function(e){
                e.preventDefault()
                var data = $('#form_add').serialize()
                axios({
                method: 'POST',
                url: 'http://127.0.0.1/api/addlist',
                data
                }).then(function(res){
                if (res.data.status == 200) {
                        // 刷新页面
                        location.reload();
                } else {
                    alert("评论发布失败")
                }
                })
            })

            // 获取用户名判断是否登录
            $.get(
                'http://127.0.0.1/api/username',
                function(res) {
                // console.log(res);
                if (res.status == 200) {  
                    let username = res.username
                        // 获取文章列表
                        axios({
                            method: 'GET',
                            url: 'http://127.0.0.1/api/getlist',
                        }).then(function(res) {
                            // 将获取到的文章渲染到页面
                            res.data.data.map(item => {
                            $('.user').text(username)
                            let li = `
                            <li class="list-group-item">
                                <span>${item.content}</span>
                                <span class="badge">${item.username}</span>
                            </li>`
                            $('.list-group').append(li)
                            })
                        })
                } else {
                    alert('请先完成登录')
                    location.href = './login.html'
                }
                }
            )

            // 退出登录
            $('#btnLogout').click(function() {
            $.post(
                'http://127.0.0.1/api/register',
                function(res) {
                if (res.status == 200) {
                    // 如果 status 为 200,则表示退出成功,重新跳转到登录页面
                    location.href = './login.html'
                }
                }
            )
            })
        })
    </script>
</body>
</html>

五、展示个人博客页面

登陆页面

博客主页 

  添加文章页面

文章详细页面

留言板 

至此,我的个人博客大致完成,后续将会继续改进

本文含有隐藏内容,请 开通VIP 后查看