文件结构如下:
|----heroManage
|----node_modules --> 这是用命令自动生成的 npm i express body-parser multer
|----uploads --> 这是用代码自动生成的 var upload = multer({ dest: “uploads/” });
|----utils --> 这是复制的工具包
|----www --> 这是主要的前端代码包
|----app.js --> 这是主要的后端代码文件
|----package.json --> 这是用命令自动生成的 npm init -y
|----package-lock.json --> 这是和上面的node_modules文件夹一起生成的
再附带一张小图片
这是后端主要逻辑代码:
// 导包 const express = require("express"); const bodyParser = require("body-parser"); const path = require("path"); const multer = require("multer"); // 用包,帮我们创建一个uploads文件夹 var upload = multer({ dest: "uploads/" }); // 导入我们自己写的模块,需要拼接一个绝对路径 const db = require(path.join(__dirname, "utils", "db.js")); // 创建服务器 const app = express(); // 例如,通过如下代码就可以将 www 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了: app.use(express.static("www")); // 如果要使用多个静态资源目录,请多次调用 express.static 中间件函数: app.use(express.static("uploads")); // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })); // 写接口(注册路由) // 1. 用户登录 app.post("/login", (req, res) => { // 1.1 接收用户传递过来的用户名和密码 let { username, password } = req.body; // 对象解构语法 // 1.2 判断账号和密码是否正确 // 实际开放的时候判断流程:把账号和密码发到数据库中去验证 if (username == "admin" && password == "123456") { res.send({ code: 200, msg: "登录成功!", }); } else { res.send({ code: 400, msg: "账号或者密码不正确!", }); } }); // 2. 获取所有英雄 app.get("/getAllHero", (req, res) => { // 调用我们自己写的db.js模块,调用它里面的方法获取所有的英雄 let list = db.getHeros(); res.send({ code: 200, data: list, }); }); // 3. 新增英雄 app.post("/add", upload.single("icon"), (req, res) => { // req.file is the `avatar` file // 传过来的文件,参数名用icon // req.body will hold the text fields, if there were any // 一起传过来的文本保存在req.body中 console.log(req.file); // 文件的参数就在这里 { filename: 'ee7c4b63db36fd8acd85f24eaf55eb6d', } console.log(req.body); // 文本参数就在这里 { name: '千里', skill: '飘起来' } // 用变量保存一下 let { name, skill } = req.body; let icon = req.file.filename; // 把这个新增的英雄的数据,用我们自己写的插件db.js 存起来 let result = db.addHero({ name, skill, icon: "http://127.0.0.1:4399/" + icon, }); // 判断 if (result == true) { res.send({ code: 200, msg: "新增成功", }); } else { res.send({ code: 400, msg: "新增失败", }); } }); // 4. 删除英雄 app.get("/delete", (req, res) => { // 接收前端传递过来的要删除的英雄的id let { id } = req.query; // console.log(id); // 用我们自己写的db.js这个文件去删除 英雄 let result = db.deleteHeroById(id); // 判断 if (result == true) { res.send({ code: 200, msg: "删除成功!", }); } else { res.send({ code: 400, msg: "删除失败!", }); } }); // 5. 根据id获取英雄(编辑的第一步) app.get("/getHeroById", (req, res) => { // 获取前端传递过来需要编辑的这个英雄的id let { id } = req.query; // 解构赋值 // 用db.js来获取id下的英雄信息 let result = db.getHeroById(id); if (result != false) { res.send({ code: 200, mag: "获取成功", data: result, }); } else { res.send({ code: 400, mag: "获取失败", }); } res.send("根据id获取英雄"); }); // 6. 编辑英雄 app.post("/edit", upload.single("icon"), (req, res) => { // 用模块multer来接收用户编辑之后的(英雄名,英雄技能,,英雄头像) // 文件(英雄头像)req.file.filename; // 非文件参数 req.body // console.log(req.file.filename); // 387d6f59e71fd30002b039dd05f6062c // console.log(req.body); // { id: '3', name: '千里里', skill: '飘起来了' } // 存进变量里 let icon = req.file.filename; let { id, name, skill } = req.body; // 用db.js来处理 let result = db.editHero({ id, name, skill, icon: "http://127.0.0.1:4399/" + icon, }); if (result == true) { res.send({ code: 200, msg: "修改成功!", }); } else { res.send({ code: 400, msg: "修改失败!", }); } res.send("编辑英雄"); }); // 开启服务器 app.listen(4399, () => { console.log("服务器开启了..."); });这是前端登录页代码:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Bootstrap 101 Template</title> <!-- Bootstrap --> <link href="./lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> <style> .login-panel { margin-top: 100px; } .vCode { height: 36px; cursor: pointer; } .wrap { position: fixed; left: 0; top: 0; width: 100%; height: 100%; background: url("images/bg03.jpg") center bottom no-repeat; overflow: auto; } .navbar-brand { padding: 10px 15px; } .form-horizontal { margin-top: 10px; } .form-horizontal .form-group { margin-bottom: 20px; } </style> </head> <body> <div class="wrap"> <nav class="navbar navbar-inverse navbar-static-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#mymenu" > <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#"><img src="images/logo.png" /></a> </div> </div> </nav> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <div class="panel panel-default login-panel"> <div class="panel-heading"> <h3 class="panel-title"><b>用户登录</b></h3> </div> <div class="panel-body"> <form action="#" method="post" class="form-horizontal"> <div class="form-group"> <label for="userName" class="col-sm-2 control-label" >用户名</label > <div class="col-sm-10"> <input type="text" name="username" value="叶良辰" class="form-control" id="username" placeholder="请输入用户名" /> </div> </div> <div class="form-group"> <label for="userPass" class="col-sm-2 control-label" >密码</label > <div class="col-sm-10"> <input type="password" name="password" value="1234" class="form-control" id="password" placeholder="请输入密码" /> </div> </div> <!-- <div class="form-group"> <label for="vCode" class="col-sm-2 control-label">验证码</label> <div class="col-sm-6"> <input type="text" name="vcode" class="form-control" id="vcode" placeholder="请输入验证码" /> </div> <div class="col-sm-4"> <img class="vCode" src="/captcha" alt="" /> </div> </div> --> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-success login"> 登陆 </button> <a href="./register.html" class="btn btn-default">注册</a> </div> </div> </form> </div> </div> </div> </div> </div> </div> </body> </html> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="./lib/bootstrap/js/jquery-1.12.4.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="./lib/bootstrap/js/bootstrap.min.js"></script> <script> // 入口函数 $(function () { // 一:登录功能 // 1. 给登录按钮设置一个点击事件 $(".login").on("click", function (e) { // 去掉默认的提交行为 e.preventDefault(); // 2. 获取用户输入的账号和密码 let username = $("#username").val().trim(); let password = $("#password").val().trim(); // 3. 发送ajax请求,获取返回的数据 $.ajax({ type: "post", url: "http://127.0.0.1:4399/login", // 对象解构语法 data: { username, password, }, success: function (backData) { // backData: 接收到的后端返回的json数据 // console.log(backData); if (backData.code == 200) { // 如果成功,就跳转到首页 alert("登录成功"); window.location.href = "index.html"; } else { alert(backData.msg); } }, }); }); }); </script>这是前端的主页代码:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Bootstrap 101 Template</title> <!-- Bootstrap --> <link href="./lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> <style> .wrap { position: fixed; left: 0; top: 0; width: 100%; height: 100%; background: url("images/bg03.jpg") center bottom no-repeat; overflow: auto; } .navbar-brand { padding: 10px 15px; } .logout { font-weight: 900; font-size: 20px; color: #ff0000; text-decoration: none; } .logout:hover { text-decoration: none; color: yellowgreen; } #my-table th { text-align: center; } #my-table td { text-align: center; line-height: 80px; padding: 0; padding: 10px; } td img { width: 80px; height: 80px; } .username { font-weight: 900; color: hotpink; background-color: yellowgreen; } .pagination { margin: 0px; padding: 0px; font-size: 0; line-height: 1; } .pagination li { display: inline-block; font-size: 14px; } .mp15 { margin-top: 15px; } .table { margin-bottom: 0; } .table-bordered > thead > tr > td, .table-bordered > thead > tr > th { border-bottom-width: 1px; } .page-title { font-size: 16px; font-weight: bold; } </style> </head> <body> <div class="wrap"> <nav class="navbar navbar-inverse navbar-static-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#mymenu" > <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#"><img src="images/logo.png" /></a> </div> </div> </nav> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="panel panel-default"> <div class="panel-heading clearfix"> <div class="row"> <div class="col-md-6 page-title">英雄列表</div> <div class="col-md-6 text-right">当前位置:首页</div> </div> </div> <div class="panel-body"> <!-- action 不写 就是当前页面 method 不写 就是 get --> <div class="row"> <div class="col-md-9"> <!--<form class="form-inline"> <div class="form-group"> <label class="sr-only" for="exampleInputAmount" >Amount (in dollars)</label > <div class="input-group"> <div class="input-group-addon">英雄姓名</div> <input type="text" value="" class="form-control" name="search" placeholder="请输入查询内容" /> </div> </div> <button type="submit" class="btn btn-default">查找</button> </form>--> </div> <div class="col-md-3"> <a href="./add.html" class="btn btn-success pull-right" >新增</a > </div> </div> <table id="my-table" class="table table-bordered mp15"> <thead> <tr> <th width="25%">头像</th> <th width="25%">姓名</th> <th width="25%">技能</th> <th width="25%">操作</th> </tr> </thead> <tbody> <tr> <td><img src="./lib/img/盖伦.png" alt="" /></td> <td>盖伦</td> <td>躲草丛</td> <td> <button onclick="location.href='./edit.html'" class="btn btn-primary" > 编辑 </button> <button onclick="alert('你真狠')" class="btn btn-danger" > 删除 </button> </td> </tr> <tr> <td><img src="./lib/img/盖伦.png" alt="" /></td> <td>盖伦</td> <td>躲草丛</td> <td> <button onclick="location.href='./edit.html'" class="btn btn-primary" > 编辑 </button> <button onclick="alert('你真狠')" class="btn btn-danger" > 删除 </button> </td> </tr> </tbody> </table> </div> </div> </div> </div> </div> </div> </body> </html> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="./lib/bootstrap/js/jquery-1.12.4.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="./lib/bootstrap/js/bootstrap.min.js"></script> <!-- 引入模板引擎js文件 --> <script src="./lib/js/template-web.js"></script> <!-- 准备一个模板 --> <script type="text/html" id="cq"> {{each data v}} <tr> <td><img src="{{v.icon}}"></td> <td>{{v.name}}</td> <td>{{v.skill}}</td> <td> <button onclick="location.href='./edit.html?id={{v.id}}'" class="btn btn-primary">编辑</button> <button data-id='{{v.id}}' class="btn btn-danger delete">删除</button> </td> </tr> {{/each}} </script> <script> // 入口函数 $(function () { // 一:一进到首页,就要发送ajax请求,获取所有的英雄数据 $.ajax({ type: "get", url: "http://127.0.0.1:4399/getAllHero", success: function (res) { console.log(res); // var temp = template('cq', res); // $('tbody').html(temp) if (res.code == 200) { // 通过模板引擎渲染 var resHtml = template("cq", res); console.log(resHtml); $("tbody").html(resHtml); } }, }); }); // 删除数据 $("tbody").on("click", ".delete", function () { var that = this; // console.log(this) var id = $(this).attr("data-id").trim(); if (confirm("你要删除吗??")) { $.ajax({ type: "get", url: "http://127.0.0.1:4399/delete", data: { id: id, }, success: function (res) { // console.log(res) if (res.code == 200) { $(that).parent().parent().remove(); } }, }); } }); </script>