zoukankan      html  css  js  c++  java
  • 用express脚手架做后台管理系统(思路+代码展示)

    所用技术:
    1.采用前后端分离:
    前后端分离和前后端不分离的区别:
    前后端不分离:前端页面看到的效果都是由后端控制和渲染的,前后端耦合度高;
    前后端分离:前端根据自己的需求渲染页面效果,前后端耦合度低。
     
    2.ajax
    通过ajax请求数据,处理后返回结果
     
    3.jquery
    主要是使用iquery中的$.ajax
     
    4.数据库:
    mongoose
     
    5.bootstrap
    主要是用于静态布局
     
    思路:
    一,登录注册:
    1.在public文件夹新建index.html 文件,书写静态布局,利用模块化将html代码进行封装---->
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="./css/common/reset.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="./css/index/index.css">
    </head>
    
    <body>
    <div class="login_container"></div>
    </body>
    
    </html>
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    <script src="./js/js/common/register.js"></script>
    <script src="./js/js/common/login.js"></script>
    <script src="./js/js/common/page.js"></script>
    2.在public文件夹下新建js文件夹,在js文件夹下新建common文件夹,存放index要封装的模块化JS文件---->
    3.在common文件夹下新建page.js文件:创建一个Page对象(该Page对象就是index文件中的登录注册的静态布局)---->>给Page对象一个container实例属性,init以及createContent的原型方法---->
    function Page() {
        //实例属性:
        this.container = $(".login_container");    //登录注册最外层div的class名
        this.flag = true;        //设置开关,在注册和登录之间实现跳转
        this.init();
       
    }
    
    //原型方法:
    Page.prototype = {
        init:function(){
            this.createContent();
        },
        //渲染到页面的方法:需要在Register和Login之后调用:
        createContent:function(params=this.flag){     //判断有参数则直接登录,没有参数则注册传参
            this.container.html('')
            if(params){
               //new一个login对象(login.js)
                this.login =  new Login(this.container);
            }else{
               //new一个register对象(register.js)
                this.register = new Register(this.container);
            }
        }
    }
    
    new Page();

    4.在common文件夹下新建login.js和register.js文件---->主要是创建登录,注册模板

    //创建一个Register对象:
    function Register(container){
        this.container = container;
        this.init();
    }
    
    //Resgiter模板
    Register.template = `
    <div class="login">
                <div class="logo">
                    <img src="https://cas.1000phone.net/cas/images/login/logo.png">
                </div>
                <form class="form">
                    <div class="form-group">
                        <label for="register_username">用户名</label>
                        <input type="email" class="form-control" id="register_username" placeholder="Email">
                    </div>
                    <div class="form-group">
                        <label for="register_password">密码</label>
                        <input type="password" class="form-control" id="register_password" placeholder="Password">
                    </div>
                    <div class="form-group">
                        <div class="alert alert-danger" role="alert">忘记密码?</div>
                        <div class="alert alert-info" role="alert" id="js_login">去登陆</div>
                    </div>
                    <button type="button" class="btn btn-info login_btn" id="login_btn">注册</button>
                </form>
            </div> 
    `
    
    Register.prototype = {
        init:function(){
            this.createDom();
            this.handlePush();
            this.handleRegister();
        },
        //创建div,将Register.prototype追加到div中,再将div追加到页面中
        createDom:function(){
            this.el = $("<div class='content'></div>");
            this.el.append(Register.template);
            this.container.append(this.el);
        },
        //点击去登录,切换到登录页面
        handlePush(){
            this.el.find("#js_login").on("click",$.proxy(this.handleLogin,this))  
        },
        handleLogin(){
             new Page().createContent(true);
        },
         //点击去注册,切换到注册页面
        handleRegister(){
            this.el.find("#login_btn").on("click",$.proxy(this.handleRegisterBtn,this))
        },
    
        //给注册按钮添加点击事件:通过$.ajax向服务器发送请求,并将服务器处理的结果返回给客户端
        handleRegisterBtn(){
            //获取客户信息(用户名和密码)
           var username = this.el.find("#register_username").val();
           var password = this.el.find("#register_password").val();
    
           //var一个userInfo对象,存放用户名和密码:因为key和value一样,所以只写一个就可以了
        //    var userInfo = {
        //        username:username,
        //        password:password
        //    }
           var userInfo = {
               username,
               password
           }
          //向服务端发送请求:将客户传递的参数传递给服务端,服务端进行处理,判断用户名是否存在 
            $.ajax({
                type:"post",
                url:"/api/register",    //接口是由后端提供的,通过路由建立前后端之间的连接
                data:userInfo,    
                dataType:"json",
                success:$.proxy(this.handleRegisterSuccess,this)    //获取数据成功返回handleRegisterSuccess方法
            })
        },
        handleRegisterSuccess(data){
            if(data.status){
                alert("注册成功");    
                //注册成功跳转到登录页面
                new Page().createContent(true);    
            }
        }
    }
    //创建Login对象:
    function Login(container){
        //实例属性:
        this.container = container;
        this.init();
    }
    
    //登录模板
    Login.template = `
    <div class="login">
                <div class="logo">
                    <img src="https://cas.1000phone.net/cas/images/login/logo.png">
                </div>
                <form class="form">
                    <div class="form-group">
                        <label for="login_username">用户名</label>
                        <input type="email" class="form-control" id="login_username" placeholder="Email">
                    </div>
                    <div class="form-group">
                        <label for="login_password">密码</label>
                        <input type="password" class="form-control" id="login_password" placeholder="Password">
                    </div>
                    <div class="form-group">
                        <div class="alert alert-danger" role="alert">忘记密码?</div>
                        <div class="alert alert-info" role="alert" id="js_register">去注册</div>
                    </div>
                    <button type="button" class="btn btn-info login_btn" id="login_btn">登陆</button>
                </form>
            </div> 
    `
    //原型方法
    Login.prototype = {
        init(){
            this.createDom();
            this.handlePush();
            this.loginBtn();
        },
        createDom:function(){
            this.el = $("<div class='content'></div>");
            this.el.append(Login.template);
            this.container.append(this.el);
        },
        //点击去注册切换到注册页面
        handlePush(){
           this.el.find("#js_register").on("click",$.proxy(this.handleRegister,this))  
        },
        handleRegister(){
            new Page().createContent(false);
        },
        //给登录按钮添加点击事件:
        loginBtn(){
            this.el.find("#login_btn").on("click",$.proxy(this.handleLoginCallBack,this))
        },
        handleLoginCallBack(){
            //var一个userInfo对象
            var userInfo = {
                username:this.el.find("#login_username").val(),
                password:this.el.find("#login_password").val()
            }
           //通过ajax将客户端的请求发送给服务端:并接受服务端返回的数据:
            $.ajax({
                type:"post",
                url:"/api/login",
                data:userInfo,
                success:$.proxy(this.handleLoginSucc,this)
            })
        },
        //登录成功则跳转到详情页
        handleLoginSucc(data){
            if(data.status){
                location.href="http://localhost:3000/html/detail.html"
            }
        }
    }

    以上前端代码书写完毕:从代码中不难看出:前端主要是做了静态布局,以及向后端发送请求,并将返回结果回馈给客户端,进行渲染页面

    接下来理一下后端代码:

    在客户端向服务端发送请求后,服务端接收到请求后,是要对请求数据做处理的,即对数据的增删改查,主要是放在model层的:

    我们先来处理一下注册数据:处理数据之前我们先来连接一下数据库:

    新建util文件夹,并新建database.js文件:

    //引入mongoose模块:
    var mongoose = require("mongoose");
    //设置路径,连接数据库
    let url = "mongodb://127.0.0.1:27017/bk1824"
    mongoose.connect(url);
    //导出数据库模块
    module.exports = {
        mongoose
    }

    有了数据库我们再来model文件夹下处理数据:

    我们将注册登录的数据放在user.js文件中:

    //连接数据库
    const mongoose = require("../util/database").mongoose;
    //在做数据的增删改查时需要先创建表:在数据库中,会默认在表明后加“s”,当表名结尾字母是y时,变y为i再加es
    const User = mongoose.model("user",{
        //设置表的字段:(mongodb和mongoose的区别之一:mongoose可以设置字段)
        username:String,
        password:String
    })
    
    //
    //在处理注册登录数据时,都需要先在数据库中查出对应数据,再进行判断
    const userFind = (userInfo,cb)=>{
        User.findOne(userInfo).then((res)=>{
            cb(res)
        })
    }
    
    //
    //判断注册数据中用户名没被占用,则调用该方法将数据增加到数据库中:
    const userAdd = (userInfo,cb)=>{
        let user = new User(userInfo);
        user.save().then((res)=>{
            cb(res);
        })
    }
    
    //导出查,增模块:在controller层引入跑业务逻辑
    module.exports = {
        userFind,
        userAdd
    }

    有了操作数据库的方法,接下来我们跑一下业务逻辑,业务逻辑主要在controller文件夹下,注册登录的业务逻辑主要放在user.js文件下:

    //引入model/user.js文件,使用增,查方法:
    const userModel = require("../model/user");
    //引入加密模块  1.     主要用来给密码加密,增加安全性,提高用户体验
    const crypto = require('crypto');
    //引入token:   判断用户是否已经登录      需要在前端中验证
    const jwt = require("jsonwebtoken");
      
    //注册的业务逻辑:先获取用户输入的数据,再从数据库中查找对应的数据,判断用户输入的数据在数据库中能否查到,如果有,则用户名已存在,
    //注册失败,查不到,添加到数据库中,注册成功
    const register = (req,res)=>{
        //解构赋值:因为是POST请求数据的,所以用req.body获取数据:此处获取的是用户传递的参数
        let {username,password} = req.body;
    //调用查的方法,从数据库查数据:
        userModel.userFind({username},function(data){
            //如果数据不存在,则添加进数据库:
            if(!data){
                //
                //创建sha256算法  2.    给数据加密:md5和sha256的区别:md5可以解密,sha256不能解密,所以相对安全
                const hash = crypto.createHash('sha256');
                //需要加密的字符 3.
                hash.update(password);
               
                //对密码进行加密 4.
                //将加密的数据添加到数据库中:
                userModel.userAdd({
                    username:username,
                    password:hash.digest('hex')   //加盐
                },function(){
                    //处理完数据返回结果:
                   res.json({
                    status:true,
                    Info:"注册成功"
                   })
                })
            }else{
                res.json({
                    status:false,
                    Info:"用户名已存在"
                })
            }
        })
    }
    
    
    const login = (req,res)=>{
        //获取用户名和密码
        let {username,password} = req.body;
        //查看当前用户名是否存在 如果不存在告诉用户用户名不存在  如果存在则进行密码判断
        userModel.userFind({username},function(data){
            if(data){
                //创建sha256算法
                const hash = crypto.createHash('sha256');
                //进行加密
                hash.update(password);
                //因为数据库中的密码是加密的  所以我们进行对比的时候也需要进行加密在对比
                if(data.password == hash.digest('hex')){
    
                    //设置token
                    let token = jwt.sign({username},"bk1824",{'expiresIn':'1h'})
                    //种cookie
                    res.cookie("token",token)
                    res.cookie("userInfo",username)
    
                    //成功
                    res.json({
                        status:true,
                        info:"登陆成功",
                    })
                }else{
                    //失败
                    res.json({
                        status:false,
                        info:"密码错误"
                    })
                }
    
            }else{
                //用户名不存在
                res.json({
                    status:false,
                    info:"用户名不存在"
                })
            }
        })
    }
    //导出模块:
    module.exports = {
        register,
        login
    }
    
    
    /*
        md5加密  解密
    
        sha256加密
    
    
        123456 + bk1824 + 秘钥 = 随机字符串
    
    
    
        token
    
    
        1、安装
            cnpm install jsonwebtoken -S
    
        2、引入
            const jwt = require("jsonwebtoken");
    
        3、设置token
            jwt.sign(payload,秘钥,过期时间)
            payload:相关信息
            秘钥:随机字符
            过期时间 token什么时候过期
    */

    万事俱备,只欠东风,最最重要的路由文件:

    var express = require('express');
    var router = express.Router();
    var userController = require("../controller/user");
    /* /api/register */
    router.post('/register',userController.register);
    //登陆 /api/login
    router.post('/login',userController.login);
    
    
    
    
    
    module.exports = router;
    
    
    /*
        MVC模式
            架构思想
            M:model层  数据的增删改查
            V:view层   视图的展示
            C:controller层   负责业务逻辑
    
        MVP
    
        MVVM
    
    */

    注册登录效果到这儿就告一段落了,接下来再做一下职位的增删改查:

    还是先来码一码前端代码:

    我们的前端文件还是统一放在public中,至于为啥要放在public中,主要是因为因为我们使用了express框架,既然使用了人家,就得遵循人家的规则嘛,在express中,会优先渲染public中的文件:

    我们还是利用bootstrap来做静态布局,用JS模板渲染页面:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <link rel="stylesheet" href="../css/common/reset.css">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" />
        <link rel="stylesheet" href="../css/detail/detail.css">
    </head>
    
    <body>
        <div class="header">
            <div class="logo">
                <img src="http://jx.1000phone.net/Public/assets/css/images/logo.png?1552286991" />
            </div>
            <div class="info">
                <p id="js_userName"></p>
                <p id="js_logout" class="logout">退出</p>
            </div>
        </div>
        <!-- tabBar -->
        <div class="container_detail">
            <div class="tabbar">
                <ul>
                    <li class="active">系统首页</li>
                    <li>职位列表</li>
                    <li>职位管理</li>
                </ul>
            </div>
            <div class="content">
                <!-- <div class="list">
                    <div class="list_job">
                       <div class="job_des">
                            <div class="job_name">前端开发工程师</div>
                            <div class="job_price">8000</div>
                            <div class="job_ex">经验3-5年 本科</div>
                       </div>
                       <div class="com_des">
                           <div class="company_logo">
                               <img src="https://www.lgstatic.com/thumbnail_100x100/i/image3/M00/28/02/Cgq2xlqa2jWAGAnMAAArW2y3MsY901.jpg"/>
                           </div>
                           <div class="company_name">北京阿里科技有限公司</div>
                       </div>
                       <div class="operation">
                           <button class="btn btn-danger">删除</button>
                           <button class="btn btn-info">修改</button>
                       </div>
                    </div>
                </div> -->
            </div>
            <!-- 模块框 -->
            <div class="modal fade" tabindex="-1" role="dialog" id="jobModel">
                <div class="modal-dialog" role="document">
                    <div class="modal-content">
                        <div class="modal-header">
                            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                                    aria-hidden="true">&times;</span></button>
                            <h4 class="modal-title">请修改内容</h4>
                        </div>
                        <div class="modal-body">
                            <form>
                                <div class="form-group">
                                    <label for="job_modify_name">职位名称</label>
                                    <input type="text" class="form-control" id="job_modify_name" placeholder="请输入职位名称">
                                </div>
                                <div class="form-group">
                                    <label for="job_modify_price">薪资</label>
                                    <input type="text" class="form-control" id="job_modify_price" placeholder="薪资范围">
                                </div>
                                <div class="form-group">
                                    <label for="job_modify_ask">要求</label>
                                    <input type="text" class="form-control" id="job_modify_ask" placeholder="招聘要求">
                                </div>
                                <div class="form-group">
                                    <label for="company_modify_name">公司名称</label>
                                    <input type="text" class="form-control" id="company_modify_name" placeholder="请输入公司名称">
                                </div>
                                <div class="form-group">
                                    <label for="logo_modify">上传公司logo</label>
                                    <input type="file" id="logo_modify" multiple>
                                </div>
                            </form>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-primary" id="modify_btn" data-dismiss="modal">修改</button>
                        </div>
                    </div>
                </div>
            </div>
    
        </div>
    </body>
    
    </html>
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    <script src="https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js"></script>
    <script src="../js/js/common/auth.js"></script>
    <script src="../js/js/detail/logout.js"></script>
    <script src="../js/js/detail/joblist.js"></script>
    <script src="../js/js/detail/tabbar.js"></script>
    <script src="../js/js/detail/job.js"></script>
    <script src="../js/js/detail/modify.js"></script>

    静态布局就不详细说了,毕竟审美不同,可以随意调的,这个随意,主要是理一下JS代码:

    public文件夹---detail---js-----job.js

    function Job() {
        this.content = $(".content");
        this.init()
    }
    
    Job.template = `
    <form>
                        <div class="form-group">
                            <label for="job_name">职位名称</label>
                            <input type="text" class="form-control" id="job_name" placeholder="请输入职位名称">
                        </div>
                        <div class="form-group">
                            <label for="job_price">薪资</label>
                            <input type="text" class="form-control" id="job_price" placeholder="薪资范围">
                        </div>
                        <div class="form-group">
                            <label for="job_ask">要求</label>
                            <input type="text" class="form-control" id="job_ask" placeholder="招聘要求">
                        </div>
                        <div class="form-group">
                            <label for="company_name">公司名称</label>
                            <input type="text" class="form-control" id="company_name" placeholder="请输入公司名称">
                        </div>
                        <div class="form-group">
                            <label for="logo">上传公司logo</label>
                            <input type="file" id="logo" multiple>
                        </div>
                        <button type="button" class="btn btn-default" id="js_jobBtn">提交</button>
                    </form>
    `
    
    //原型对象
    Job.prototype = {
        init(){
            this.createDom();
            this.JobClick();
        },
        //动态渲染到页面中:
        createDom(){
            this.el = $("<div class='from'></div>");
            this.el.append(Job.template);
            this.content.html(this.el)
        },
        //点击提交,上传数据:
        JobClick(){
            this.el.find("#js_jobBtn").on("click",$.proxy(this.handleJobCB,this))
        },
        handleJobCB(){
            //创建formData 模拟表单提交数据  兼容性问题    此处用模拟表单提交数据主要是因为要上传图片
            //获取要上传的数据:
            var formData = new FormData();
            var jobName = this.el.find("#job_name");
            var jobPrice = this.el.find("#job_price");
            var jobAsk = this.el.find("#job_ask");
            var companyName = this.el.find("#company_name");
            var logo = this.el.find("#logo");
            
          
            
            //append key val  key是服务端接收的key值
            formData.append("jobname",jobName.val());
            formData.append("jobprice",jobPrice.val());
            formData.append("jobask",jobAsk.val());
            formData.append("companyname",companyName.val());
            formData.append("companylogo",logo[0].files[0]);
           
           
    //通过ajax将请求的数据发送给服务器:
            $.ajax({
                type:"post",
                url:"/job/addjob",
                data:formData,
                cache:false,    //不读取缓存中的结果 true的话会读缓存  其实post本身就不会读取缓存中的结果
                contentType:false,  //数据编码格式不使用jquery的方式 为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。
                processData:false,//默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会处理转化成
                //一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM 树信息或其它不希望转换的
                //信息,请设置为 false。
                success:$.proxy(this.handleSuccess,this)
            })
        },
        handleSuccess(data){
           if(data.status){
               alert("添加成功");
               new JobList();
           }
        }
    }
  • 相关阅读:
    jdbc框架 commons-dbutils的使用
    SpringBoot整合Quartz和H2的例子
    Microsoft VS 2008 过期解决方法
    数据库事务的隔离级别
    angularJS中ng-if的用法
    angularJS中ng-change的用法
    Hello,Akka
    Yum常用命令及Yum中文手册
    最大堆的插入/删除/调整/排序操作(图解+程序)(JAVA)
    别人要访问我的电脑上部署的tomcat,必须关闭防火墙吗?
  • 原文地址:https://www.cnblogs.com/kinoko-1009/p/10527006.html
Copyright © 2011-2022 走看看