Node.js学生管理系统(Express+MySQL)

这次的案例,数据持久化,用的MySQL

如果想看用其他数据持久化案例(如MongoDB数据库),可以点击  Node学生管理案例 


目录

一、完成功能:实现对“学生信息”的增删改查。并且实现了数据持久化。

数据库为MySQL。

二、使用到的技术:基于Express框架和art-template模板引擎,并且将路由模块分离出来,更利于开发和维护

三、编写代码

1.首先初始化项目(package.json)

2.安装要用到的包

3.编写核心模块app.js

4.路由模块router.js

5.封装MySQL对学生处理模块student.js

6.视图

1.index.html

2.new.html

四、页面展示:

1.首页  http://localhost:8888/students

2.搜索

3.编辑 

4.添加

五、源码下载


一、完成功能:实现对“学生信息”的增删改查。并且实现了数据持久化。

数据库为MySQL。

 

二、使用到的技术:基于Express框架和art-template模板引擎,并且将路由模块分离出来,更利于开发和维护

"art-template": "^4.12.2",

"body-parser": "^1.18.3",

"bootstrap": "^4.1.3",

"express": "^4.16.3",

"express-art-template": "^1.0.1",

"mysql": "^2.16.0"

三、编写代码

1.首先初始化项目(package.json)

npm init -y

2.安装要用到的包


# Express框架


npm i -S express



# 模板引擎


npm i -S art-template



# 模板引擎与Express的关联包


npm i -S express-art-template



# post请求解析工具


npm i -S body-parser


# mysql

npm i -S mysql

3.编写核心模块app.js

/**
 * app.js 入门模块
 * 职责:
 *   创建服务
 *   做一些服务相关配置
 *     模板引擎
 *     body-parser 解析表单 post 请求体
 *     提供静态资源服务
 *   挂载路由
 *   监听端口启动服务
 */

var express = require('express');
var router = require('./router');
var bodyParser = require('body-parser');

var app = express();

app.use('/node_modules/',express.static('./node_modules/'));
app.use('/public',express.static('./public/'));

// 配置模板引擎和 body-parser 一定要在 app.use(router) 挂载路由之前
// parse application/x-www-form-urlencoded
app.engine('html',require('express-art-template'));
app.use(bodyParser.urlencoded({extended:false}));
// parse application/json
app.use(bodyParser.json());

//挂载路由到app服务中
app.use(router);

app.listen(8888,function () {
    console.log('running  8888 ....')
})

4.路由模块router.js

/**
 * router.js 路由模块
 * 职责:
 *   处理路由
 *   根据不同的请求方法+请求路径设置具体的请求处理函数
 * 模块职责要单一,不要乱写
 * 我们划分模块的目的就是为了增强项目代码的可维护性
 * 提升开发效率
 */

var fs = require('fs');
var Student = require('./student');


// Express 提供了一种更好的方式
// 专门用来包装路由的

var express = require('express');

// 1、创建一个路由容器
var router = express.Router();

//2.把路由挂载到router路由中

/*
渲染学生列表界面
 */
router.get('/students', function (req, res) {
    if (req.query.name != null && req.query.name != undefined && req.query.name != '') {
        Student.findOneByName( req.query.name, function (err, students) {
            if (err) {
                return res.status(500).send('Server error');
            }
            console.log(students.toString())
            if (students.toString().length == 0) {
                res.render('index.html', {
                    count: 0,
                })
            } else {
                res.render('index.html', {
                    students: students
                })
            }
        })
    } else {
        Student.find(function (err, students) {
            if (err) {
                return res.status(500).send('Server error');
            }
            if (students.length >= 3) {
                var top = [
                    students[0],
                    students[1],
                    students[2],
                ]
            }
            res.render('index.html', {
                top: top,
                students: students
            })
        })
    }
})
/**
 * 渲染添加学生的页面
 */
router.get('/students/new', function (req, res) {
    res.render('new.html');
});

/*
 * 处理添加学生
 */
router.post('/students/new', function (req, res) {
    Student.add(req.body,function (err) {
        if (err) {
            return res.status(500).send('Server error');
        }
        res.redirect('/students')
    })
})
/*
 * 渲染编辑学生页面
 */
router.get('/students/edit', function (req, res) {
    // 1. 在客户端的列表页中处理链接问题(需要有 id 参数)
    // 2. 获取要编辑的学生 id
    //
    // 3. 渲染编辑页面
    //    根据 id 把学生信息查出来
    //    使用模板引擎渲染页面

    Student.findById(req.query.id, function (err, student) {
        if (err) {
            console.log(err)
            return res.status(500).send('Server error.');
        }
        res.render('edit.html', {
            student: student
        })
    })
})

/*
 * 处理编辑学生
 */
router.post('/students/edit', function (req, res) {
    // 1. 获取表单数据
    //    req.body
    // 2. 更新
    //    Student.updateById()
    // 3. 发送响应
    var id = req.body.id
    Student.findByIdAndUpdate(id, req.body, function (err) {
        if (err) {
            return res.status(500).send('Server error.')
        }
        res.redirect('/students')
    })
})

/*
 * 处理删除学生
 */
router.get('/students/delete', function (req, res) {
    // 1. 获取要删除的 id
    // 2. 根据 id 执行删除操作
    // 3. 根据操作结果发送响应数据
    var id = req.query.id
    Student.findByIdAndRemove(id, function (err) {
        if (err) {
            return res.status(500).send('Server error.')
        }
        res.redirect('/students')
    })
})

// 3. 把 router 导出
module.exports = router;

5.封装MySQL对学生处理模块student.js

var mysql = require('mysql');
var Student = new Object();
var connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '123456',
    database: 'nodetest'
});

connection.connect();


/**
 * 查询所有学生
 * @param callback
 */
Student.find = function (callback) {
    connection.query(
        `SELECT * 
            FROM student
        `
        , function (err, result) {
            if (err) {
                console.log('[SELECT ERROR] - ', err.message);
                return callback(err);
            }
            callback(null, result);
        });
}

/**
 * 根据姓名查询学生
 * @param name
 * @param callback
 */
Student.findOneByName = function (name, callback) {
    connection.query(
        `SELECT *
            FROM student
         WHERE 
            name like "%${name}%"
        `
        , function (err, result) {
            if (err) {
                console.log('[SELECT ERROR] - ', err.message);
                return callback(err);
            }
            callback(null, result);
        });
}

/**
 * 新增学生
 * @param callback
 */
var addSql = 'INSERT INTO student(Id,name,gender,age,hobbies) VALUES(NULL,?,?,?,?)';
Student.add = function (student, callback) {
    var addSqlParams = new Array();
    // 将学生中的属性添加到SQL值数组中
    for (var key in student) {
        addSqlParams.push(student[key]);
    }
    connection.query(addSql, addSqlParams, function (err, result) {
        if (err) {
            console.log('[SELECT ERROR] - ', err.message);
            return callback(err);
        }
        callback(null, result);
    });
}

/**
 * 根据Id查询学生
 * @param name
 * @param callback
 */
Student.findById = function (id, callback) {
    connection.query(
        `SELECT *
            FROM student
         WHERE 
            id = "${id}"
        `
        , function (err, result) {
            if (err) {
                console.log('[SELECT ERROR] - ', err.message);
                return callback(err);
            }
            callback(null, result[0]);
        });
}

var updateSql = 'UPDATE student SET ' +
    'name = ?, gender = ? , age = ? , hobbies = ? WHERE id = ?';
Student.findByIdAndUpdate = function (id, student, callback) {
    var addSqlParams = new Array();
    // 将学生中的属性添加到SQL值数组中
    for (var key in student) {
        addSqlParams.push(student[key]);
    }
    addSqlParams.shift()
    addSqlParams.push(id);
    console.log(addSqlParams)
    connection.query(updateSql, addSqlParams, function (err, result) {
        if (err) {
            console.log('[SELECT ERROR] - ', err.message);
            return callback(err);
        }
        callback(null, result.affectedRows);
    });
}

Student.findByIdAndRemove = function (id, callback) {
    var delSql = `DELETE FROM student where id= ${id}`;
    connection.query(delSql, function (err, result) {
        if (err) {
            return callback(err);
        }
        return callback(null, result.affectedRows);
    });
}

//导出模板构造函数
module.exports = Student;

6.视图

1.index.html

<!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">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">
    <title>学生管理系统</title>
    <!-- Bootstrap core CSS -->
    <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="/public/css/main.css" rel="stylesheet">
</head>

<body>
<div class="container-fluid">
    <div class="navbar-header">
        <a class="navbar-brand" href="#">学生管理系统</a>
    </div>
    <div class="row">
    </div>
    <div class="col-sm-9 col-sm-offset-3 col-md-12 col-md-offset-2 main">
        <h1 class="page-header">Top3</h1>
        <div class="row placeholders">
            {{ each top }}
            <div class="col-xs-6 col-sm-4 placeholder">
                <img src="/public/img/head.jpg"
                     width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail">
                <h4>{{ $value.name }}</h4>
                <span class="text-muted">{{ $value.hobbies }}</span>
            </div>
            {{ /each }}
        </div>
        <h2 class="sub-header">学生列表</h2>
        <form class="form-inline" action="/students">
            <div class="form-group">
                <label for="id" style="margin:5px">搜索:</label>
                <input type="text" style="margin:5px ;width: 400px" class="form-control" name="name" id="id"
                       placeholder="请输入姓名">
            </div>
            <div class="form-inline">
                <button type="submit" class="btn btn-default" style="width: 100px ;margin:5px">搜索</button>
                <a class="btn btn-success" href="/students/new">添加学生</a>
            </div>
        </form>
        <div class="table-responsive" style="margin-top: 50px">
            <table class="table table-striped">
                <thead>
                <tr>
                    <th>#</th>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>年龄</th>
                    <th>爱好</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {{if count == 0}}
                    <tr>
                    </tr>
                    <td>
                        未找到该姓名,请重新查询!
                    </td>
                    </tbody>
                {{else}}
                    {{each students}}
                    <tr>
                        <td>{{ $index +1 }}</td>
                        <td>{{ $value.name }}</td>
                        {{if $value.gender==0 }}
                        <td>男</td>
                        {{else}}
                        <td>女</td>
                        {{/if}}
                        <td> {{ $value.age }}</td>
                        <td>{{ $value.hobbies }}</td>
                        <td>
                            <a href="/students/edit?id={{ $value.id }}">编辑</a>
                            <a href="javascript:if(confirm('确实要删除?'))location='/students/delete?id={{ $value.id }}'">删除</a>
                        </td>
                    </tr>
                    {{ /each }}
                {{/if}}


                </tbody>
            </table>
        </div>
    </div>
</div>
</div>
</body>

</html>

2.new.html

<!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">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">
    <title>添加学生</title>
    <!-- Bootstrap core CSS -->
    <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="/public/css/main.css" rel="stylesheet">
</head>

<body>
<div class="container-fluid">
    <div class="navbar-header">
        <a class="navbar-brand" href="/students">学生管理系统</a>
    </div>
</div>
<div class="container-fluid">
    <div class="row">
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
            <h2 class="sub-header">添加学生</h2>
            <form action="/students/new" method="post">
                <div class="form-group">
                    <label for="">姓名</label>
                    <input type="text" class="form-control" id="" name="name" required minlength="2" maxlength="10">
                </div>
                <div class="form-group">
                    <label for="">性别</label>
                    <div>
                        <label class="radio-inline">
                            <input type="radio" name="gender" id="" value="0" checked> 男
                        </label>
                        <label class="radio-inline">
                            <input type="radio" name="gender" id="" value="1"> 女
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <label for="">年龄</label>
                    <input class="form-control" type="number" id="" name="age" required min="1" max="150">
                </div>
                <div class="form-group">
                    <label for="">爱好</label>
                    <input class="form-control" type="text" id="" name="hobbies">
                </div>
                <div class="row">
                    <div class="col-md-5">
                        <button type="submit" class="btn btn-default">提交</button>
                    </div>
                    <div class="col-md-2" style="height: 20px">
                    </div>
                    <div class="col-md-5">

                        <a href="/students">
                            <button type="button" class="btn btn-default">取消</button>
                        </a>
                    </div>
                </div>
            </form>

        </div>
    </div>
</div>
</body>

</html>

四、页面展示:

1.首页  http://localhost:8888/students

2.搜索

3.编辑 

4.添加

五、源码下载

https://download.csdn.net/download/litongzero/10598800

关注我 + 回复 邮箱,免费发源码

猜你喜欢

转载自blog.csdn.net/LitongZero/article/details/81606395