简易的图书后台管理系统

3,612 阅读3分钟

写在前面

今天我们要实现的一个简易的图书管理页面不包含管理员的登陆页面,主要包含的功能有对图书列表的增删改查

准备工作:

  • 数据库:准备数据如下↓(包含id、书名name、书的作者author、书籍类型category、介绍info、是否完本isDone、排名ranking)

image.png

  • Vs-code:安装Express模块、初始化项目、安装mysql模块、封装好的Sql操作模块、ejs模块(所有的文件目录如下)

image.png

  • bootStrap的css样式(偷个懒自己就不一一写样式了)

先来完成几个简单的页面(列表页、新增页、修改页)

效果是这样的↓ 列表页 image.png

<!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>图书排行榜列表</title>
  <link href="/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="/css/book_list.css">
</head>
<body>
  <h1>图书排行榜列表</h1>
  <div class="container">
    <form class="form-inline" action="/book/list" method="get">
      <div class="form-group">
        <label for="searchBox">书名:</label>
        <input type="text" value="<%= bookName %>" class="form-control" id="searchBox" name="bookName">
      </div>
      <button type="submit" class="btn btn-default">查询</button>
    </form>
    <a href="/book/addPage" class="btn btn-success btn-add">新增</a>
    <table class="table table-hover table-bordered">
      <tbody>
        <tr>
          <th>排名</th>
          <th>书名</th>
          <th>作者</th>
          <th>分类</th>
          <th>状态</th>
          <th>简介</th>
          <th>操作</th>
        </tr>
        <% data.forEach((item,index) => { %>
        <tr>
          <td style="width: 60px;"><%= item.ranking %></td>
          <td class="book_table"><%= item.name %></td>
          <td class="book_table"><%= item.author %></td>
          <td class="book_table"><%= item.category %></td>
          <td class="book_table"><%= item.isDone?"完本":"连载" %></td>
          <td><%= item.info.length>100?item.info.slice(0,100)+"...":item.info %></td>
          <!-- 循环中,不能使用id -->
          <td>
            <button type="button" data-id="<%= item.id%>" class="btn btn-danger btn-del">删除</button>
            <button type="button" data-id="<%= item.id%>" class="btn btn-warning btn-edit">修改</button></td>
        </tr>
        <% }) %>
      </tbody>
    </table>
    <ul class="pagination">
      <!-- 上一页 -->
      <% if (page != 1) { %>
      <li><a href="/book/list?page=<%= page-1 %> ">&laquo;</a></li>
      <% } %>
      <!-- 动态生成页码 -->
      <% for( let i = 1; i <= totalPage; i++ ) { %>
        <% if (bookName) { %>
          <li><a href="/book/list?page=<%= i %>&bookName=<%= bookName %>"><%= i %> </a></li>
        <% }else{ %>
          <li><a href="/book/list?page=<%= i %>"><%= i %> </a></li>
          <% } %> 
      <% } %>
      <!-- 下一页 -->
      <% if (page<totalPage) { %>
      <li><a href="/book/list?page=<%= Number(page)+1 %>">&raquo;</a></li>
      <% } %>
    </ul>
  </div>
  <script>
    //获取所有的删除按钮,为它们添加点击事件
    let delBtns = document.querySelectorAll(".btn-del");
    for (let i = 0; i < delBtns.length; i++) {
      delBtns[i].onclick = function () {
        //弹出确认框
        if (confirm("确认删除吗?")) {
          //发起删除请求  修改url中的地址 
          //告诉服务器,要删除的数据是哪一个
          location.href = '/book/del?id=' + this.dataset.id;
        }
      }
    }
    //获取所有的修改按钮,为它们添加点击事件
    let editBtns = document.querySelectorAll(".btn-edit");
    for (let i = 0; i < editBtns.length; i++) {
       editBtns[i].onclick = function(){
        location.href = '/book/editPage?id=' + this.dataset.id;
       }
    }
  </script>
</body>
</html>

新增页 image.png

<!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>新增书籍</title>
  <link rel="stylesheet" href="/css/bootstrap.min.css">
  <link rel="stylesheet" href="/css/book_add.css">
</head>
<body>
  <div class="container">
    <h1>新增书籍</h1>
    <form method="post" action="/book/add">
      <div class="form-group">
        <label for="exampleInputEmail1">书名</label>
        <input type="text" class="form-control" name="name"  placeholder="请输入书名">
      </div>
      <div class="form-group">
        <label >作者</label>
        <input type="text" class="form-control" name="author" placeholder="请输入作者">
      </div>
      <div class="form-group">
        <label >类型</label>
        <select class="form-control" name="category">
          <!-- <option value="">---请选择---</option> -->
          <option value="玄幻">玄幻</option>
          <option value="都市">都市</option>
          <option value="历史">历史</option>
          <option value="科幻">科幻</option>
          <option value="仙侠">仙侠</option>
          <option value="轻小说">轻小说</option>
          <option value="悬疑">悬疑</option>
          <option value="游戏">游戏</option>
        </select>
      </div>
      <div class="form-group">
        <label for="">排名</label>
        <input type="number" name="ranking" class="form-control" placeholder="请输入排行">
      </div>
      <div class="checkbox">
        <label>
          <input type="checkbox" name="isDone"> 是否完本
        </label>
      </div>
      <div class="form-group">
        <label for="">简介</label>
        <textarea class="form-control" name="info" rows="6"></textarea>
      </div>
      <button type="submit" class="btn btn-default">提交</button>
    </form>
  </div>
</body>
</html>

修改页 image.png

<!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>修改书籍</title>
  <link rel="stylesheet" href="/css/bootstrap.min.css">
  <link rel="stylesheet" href="/css/book_add.css">
</head>
<body>
  <div class="container">
    <h1>修改书籍</h1>
    <form method="post" action="/book/edit">
      <input type="hidden" name="id" value="<%= id %>">
      <div class="form-group">
        <label for="exampleInputEmail1">书名</label>
        <input type="text" class="form-control" name="name" value="<%= name %>" placeholder="请输入书名">
      </div>
      <div class="form-group">
        <label>作者</label>
        <input type="text" class="form-control" name="author" value="<%= author %> " placeholder="请输入作者">
      </div>
      <div class="form-group">
        <label>类型</label>
        <select class="form-control" name="category">
          <!-- <option value="">---请选择---</option> -->
          <option value="玄幻" <% if (category == "玄幻") { %> selected <% } %>>玄幻</option>
          <option value="都市" <% if (category == "都市") { %> selected <% } %>>都市</option>
          <option value="历史" <% if (category == "历史") { %> selected <% } %>>历史</option>
          <option value="科幻" <% if (category == "科幻") { %> selected <% } %>>科幻</option>
          <option value="仙侠" <% if (category == "仙侠") { %> selected <% } %>>仙侠</option>
          <option value="轻小说" <% if (category == "轻小说") { %> selected <% } %>>轻小说</option>
          <option value="悬疑" <% if (category == "悬疑") { %> selected <% } %>>悬疑</option>
          <option value="游戏" <% if (category == "游戏") { %> selected <% } %>>游戏</option>
        </select>
      </div>
      <div class="form-group">
        <label for="">排名</label>
        <input type="text" name="ranking" class="form-control" value="<%= ranking %>" placeholder="请输入排行">
      </div>
      <div class="checkbox">
        <label>
          <input type="checkbox" name="isDone" <% if (isDone) { %>
           checked
          <% } %>> 是否完本
        </label>
      </div>
      <div class="form-group">
        <label for="">简介</label>
        <textarea class="form-control" style="resize: none;" name="info" rows="6"><%= info %> </textarea>
      </div>
      <button type="submit" class="btn btn-default">提交</button>
    </form>
  </div>
</body>

</html>

删除点击删除按钮,删除的时候对应有弹窗提示

rutes下的路由book.js文件

const express = require("express");
const db = require("../until/db")
const book = express.Router();
//进入列表页面
book.get("/list",async (req, res) => {
  //获取页码
  let {
    page,
    bookName
  } = req.query;
  if (!page) {
    page = 1;
  }
  //定义获取书籍数据的sql  只定义好了一部分。
  let sql = `select * from book`
  //定义查询所有书籍数量的SQL
  let countSql = `select count(*) as count from book`;
  if (bookName) {
    sql += ` where name like '%${bookName}%'`
    countSql += ` where name like '%${bookName}%'`
  }
  sql+= ` limit ${(page-1)*5},5`
  //完成拼接,去执行sql
  // let sql = `select * from book where name like '%${bookName}%' limit ${(page-1)*5},5`;
  let data = await db.query(sql);
  //获取书籍的总数
  // let countSql = `select count(*) as count from book where name like '%${bookName}%'`;
  let result = await db.query(countSql);
  let count = result[0].count;
  //根据总数计算总页数。
  let totalPage = Math.ceil(count / 5);
  //bookName 是为了分页时,点击分页标签不会出现查询错误。
  res.render("bookList",{data,totalPage,page,bookName});
})
//进入新增页面
book.get("/addPage",(req,res)=>{
  res.render("book_add")
})
//处理新增书籍的请求
book.post("/add",async(req,res)=>{
  let {isDone} = req.body;
  if (isDone) {
    isDone = 1;
  }else{
    isDone = 0;
  }
  //处理一下 isDone的值。 数据库中存的应该是0和1,而传过来的 是 空和on。
  req.body.isDone = isDone;
  let result = await db.insert("book",req.body);
  //判断受影响的行数如果大于0,说明新增成功,否则失败。
  if (result.affectedRows>0) {
    res.send("新增成功")
  } else {
    res.send("新增失败")
  }
})
//实现删除功能  location.href只能发送get请求
book.get("/del",async(req,res)=>{
  // 获取id
  let {id} = req.query;
  let result = await db.del("book",{id})
  if (result.affectedRows>0) {
    res.send("删除成功")
  } else {
    res.send("删除失败")
  }
})
//进入修改页面
book.get("/editPage",async(req,res)=>{
  //获取id
  let {id} = req.query;
  //查询这本书的信息  result是一个数组
  let result = await db.query(`select * from book where id = ${id}`);
  res.render("book_edit",result[0]);
})
//实现修改功能
book.post("/edit",async(req,res)=>{
  //获取传递过来的参数
  let editBook = req.body;
  //处理 完本 的值为空或on 修改为0或1
  if (editBook.isDone) {
    editBook.isDone = 1;
  } else {
    editBook.isDone = 0;
  }
  //实现修改功能
  let result = await db.update("book",editBook,{id:editBook.id});
  if (result.affectedRows>0) {
    res.send("修改成功")
  } else {
    res.send("修改失败")
  }
})
module.exports = book;

入口app.js文件加入的公共路由

app.use("/book",bookRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

我们在浏览器地址栏输入:本地3000/book/list即可访问,修改删出查看等等。