使用Node.js构建收费公路管理系统

使用Node.js构建收费公路管理系统

在本文中,我们将使用Node.js构建一个简单的收费公路管理系统,其中数据将存储在本地MongoDB数据库中。

问题陈述: 在一个收费站,很难记录所有的交易并将它们存储在一个地方,如果需要的话,很难列出通过该收费站的车辆的数据。我们的目标是构建一个应用程序,允许收费管理员将收费收据添加到我们的数据库中,并且所有收据(通过收费站的车辆的详细信息)都应该对收费管理员可见。

因此,我们将使用以下方法构建我们的应用程序: 我们将使用简单的HTML(以及一些CSS)和Bootstrap构建前端,后端将使用Node.js,并且我们将使用本地MongoDB数据库。

我们的应用程序基本上包含以下两个页面,我们将在文章中进一步构建它们:

  1. 收费员可以从中添加通过收费的车辆的详细信息(车牌号码,日期,时间等)的简单页面。
  2. 我们将列出所有的交易或收费收据的详细信息的页面。

以下是我们的应用程序的外观示例:

使用Node.js构建收费公路管理系统

让我们开始构建我们的应用程序。

在我们的应用程序中安装所需的软件包: 首先,您必须对Node软件包(如“express”,“body-parser”,“ejs”和“mongoose”)有基本了解,并且在您的电脑上安装了MongoDB。如果您对这些软件包之一没有基本了解或尚未安装MongoDB,建议您参考提供的文章链接。当我们逐步了解代码时,将提供对所有软件包的简要描述。

所以,首先,导航到一个新的文件夹/目录,并通过在命令行中执行以下命令来在其中创建一个Server.js文件:

使用Node.js构建收费公路管理系统

现在我们已经创建了server.js文件,我们需要使用以下命令在我们的文件夹中初始化npm:

使用Node.js构建收费公路管理系统

一旦npm被初始化,我们就可以安装所需的包,包括express、ejs、body-parser和mongoose。执行以下命令来一次性安装所有这些包。

使用Node.js构建收费公路管理系统

到目前为止,项目的结构应该是这样的:

使用Node.js构建收费公路管理系统

现在,在Server.js文件中,我们将要求安装在上面的所有包,以便我们稍后可以在Server.js文件中使用它们。在server.js文件中,我们必须添加以下代码:

Server.js文件:

// Server.js 
  
// Adding require statement for express 
const express = require("express"); 
  
// Making app variable using express 
const app = express(); 
  
// Adding require statement for mongoose package 
const mongoose = require("mongoose"); 
  
// Adding require statement for ejs 
const ejs = require("ejs"); 
  
// Setting view engine to ejs 
app.set("view engine", "ejs"); 
  
// Adding require statement for body-parser 
const bodyParser = require("body-parser");

使用express处理/newReceipt路由: 现在,我们将使用express来处理应用程序的/newReceipt路由(这将允许收费管理员填写有关通过收费站的车辆的详细信息)。首先,我们将允许我们的应用程序在特定端口上侦听,然后我们必须创建不同的路由来处理不同的请求。这是我们将如何做到:

Server.js文件:

// Server.js continued 
  
// Handling get request on our home route. 
app.get("/newReceipt", function (req, res) { 
      res.send("got request on newReceipt route"); 
}); 
  
// Allowing our app to listen on port 8080 
app.listen(8080, function () { 
      console.log("Server listening on port 8080"); 
});

将应用程序连接到数据库:

现在我们需要使用上面安装的“mongoose”包来设置我们的Mongo数据库。首先,我们需要使用下面给出的代码将mongoose连接到我们的本地数据库:

Server.js:

// Server.js continued 
  
// Line below will connect our app to the local  
// database with the name "transactionDatabase" 
// which will store all of our toll transactions 
mongoose.connect("mongodb://127.0.0.1/transactionDatabase", { 
      useNewUrlParser: true, 
      useUnifiedTopology: true, 
});

在这里,数据库的名称被设定为 transactionDatabase (因为它将存储所有的交易)。上述代码将创建一个名为”transactionDatabase”的新数据库,并将其与Mongoose连接。

现在,我们需要为我们的交易创建模式,即以什么格式和哪些详细信息存储我们的过路费交易。因此,我们的记录中将有4个要素,即车辆号码、缴纳的过路费金额、记录的日期和时间。以下是我们将使用的模式的创建方式:

Server.js:

// Server.js continued 
  
// Transaction schema is the schema for our 
// records that we are going to store  
// It contains vehicleNumber in the form of 
// string, date as string, time as string 
// and the toll amount as number 
const transactionSchema = new mongoose.Schema({ 
      vehicleNumber: String, 
      date: String, 
      time: String, 
      tollAmount: Number, 
});

在变量transactionSchema里,我们有vehicleNumberdatetime这些是字符串类型; tollAmount是数字类型。所以,这就是我们要在数据库中存储的交易的模式。 既然我们已经创建了模式,我们还要为它创建一个模型,这样我们就可以创建该模式的实例了。 下面的代码将允许我们使用我们的模式创建模型,我们以后可以使用它来创建实例。

Server.js:

// Creating the schema below 
const Transaction = mongoose.model( 
    "Transaction", transactionSchema);

我们的模型将被命名为”Transaction”,它使用的模式是transactionSchema,我们在上面创建过。 现在我们准备使用我们的模型创建一个新的Transaction(其中包含车辆号码,过路费金额,日期和时间的详细信息),但是为此,我们需要与通过收费站的车辆相关的数据,这些数据将由收费员记录。为此,我们必须创建一个HTML页面,允许我们输入与车辆号码,过路费金额等相关的数据。 创建一个用于输入过路费交易信息的HTML文件: 我们在这里使用了Bootstrap,以使事情更加整洁和清晰,因此请确保在HTML文件中添加Bootstrap CDN。 创建一个名为newReceipt.html的文件,并将以下代码添加到其中。

NewReceipt.html

<!DOCTYPE html> 
<html lang="en" dir="ltr"> 
  
<head> 
    <meta charset="utf-8"> 
    <link href= 
"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" 
        rel="stylesheet"
        integrity= 
"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
        crossorigin="anonymous"> 
    <title>New Record</title> 
</head> 
  
<body style="padding:1%;"> 
    <div class=""> 
        <h1>New Transaction</h1> 
    </div> 
    <form class="" action="/newReceipt" method="post"> 
        <label for="">Vehicle Number</label> 
        <input type="text" name="vehicleNumber" 
            value="" style="margin-bottom:1%;"> 
        <br> 
  
        <label for="">Amount</label> 
        <input type="number" name="amount" 
            value="" style="margin-bottom:1%;"> 
        <br> 
          
        <button type="submit" name="button"> 
            Add Transaction 
        </button> 
    </form> 
</body> 
  
</html>

以下是上述代码的解释:

  • 首先,在head标签中添加了bootstrap CDN,以使网页看起来更整洁。
  • 在body中,我们有一个包含标题和表单元素的div,用于收集来自收费员的数据。
  • 在表单元素内部,我们有两个输入框,一个是车辆编号,其name属性为”vehicleNumber”,另一个属性是收费金额,其name属性为”amount”。
  • 然后我们有一个按钮,类型为submit,即当点击时提交所有表单数据。
  • 表单元素具有一个action属性,它的值设置为”/newReceipt”,也就是说,当表单被提交时,我们将到达”/newReceipt”路由,并且method属性指定了我们将要发送的请求类型,这里是”post”请求。

现在我们已经创建了一个名为newReceipt.html的简单HTML页面,我们必须确保当app.get(“/newReceipt”)被调用时,我们可以将此页面作为响应提供。为了更好地理解,请参考下面的代码: 在home(“/”)路由上提供NewReceipt.html文件:

Server.js:

// Server.js 
  
// Handling the new receipt route 
// passing the newReceipt.html file on this route 
app.get("/newReceipt", function (req, res) { 
      res.sendFile(__dirname + "/newReceipt.html"); 
});

这段代码需要添加到Server.js文件中,当我们进入/newReceipt路由时,它将作为响应提供给我们创建的newReceipt.html页面。

因此,让我们通过启动服务器并转到/newReceipt路由来检查一切是否正常工作。首先使用下面显示的命令启动服务器:

使用Node.js构建收费公路管理系统

到目前为止,如果一切正常,我们可以进一步创建一个新的交易并将其存储在transactionDatabase中。为此,我们将从在“newReceipt.html”中创建的表单元素中获取数据。

从在“NewReceipt.html”文件中创建的表单中获取数据并将数据添加到我们的数据库中: 为了读取表单数据,我们将使用一个称为“body-parser”的包,该包已在上面安装。为了使用它,我们首先要告诉我们的应用程序使用bodyParser,这可以通过在Server.js文件的require package行下面添加一行来完成:

Server.js:

// Server.js 
  
const bodyParser = require("body-parser"); 
  
// Allowing our app to use bodyParser 
app.use( 
      bodyParser.urlencoded({ 
        extended: true, 
      }) 
);

在“newReceipt.html”中的表单元素,在提交时会生成一个POST请求到/newReceipt路由,我们需要在Server.js文件中处理,代码如下所示:

// Server.js 
  
// Handling post request on the /newReceipt route 
app.post("/newReceipt", function (req, res) { 
  
    // Getting the vehicle Number from the request, 
    // which was entered in the newReceipt.html 
    // page 
    let vNo = req.body.vehicleNumber; 
  
    // Getting the amount from the request. 
    let amt = req.body.amount; 
  
    // Creating a new transaction which we 
    // are going to save in database. 
    var t = new Transaction({ 
        vehicleNumber: vNo, 
        date: getDate(), 
        time: getTime(), 
        tollAmount: amt, 
    }); 
  
    // Saving the transaction in the database. 
    t.save(); 
  
    // Sending response that we have saved the data 
    res.send("Saved the data"); 
}); 
  
// Function to get the current date 
function getDate() { 
  
    // Creating new date object 
    var date = new Date(); 
  
    // Converting date to string 
    date = date.toString(); 
  
    // Returning the date 
    return date.substring(0, 10); 
} 
  
// Function to get the current time 
function getTime() { 
    var today = new Date(); 
    return today.getHours() + ":" 
        + today.getMinutes()  
        + ":" + today.getSeconds(); 
}

以下是代码的解释:

  • req.body.vehicleNumber和req.body.amount用于获取newReceipt.html中的表单元素中的输入。
  • 使用4个参数创建了一个新的交易:vehicleNumber(从请求中获取),date(从一个名为getDate()的函数获取),time(从一个名为getTime()的简单函数获取)和tollAmount(从请求中获取)。
  • “t.save()”函数将名为t的交易保存在我们的transactionDatabase中。
  • getDate()是一个简单的函数,用于使用Javascript Date()获取当前日期。
  • getTime()是一个类似getDate()的简单函数,用于获取当前时间。
  • res.send()函数用于通过发送响应来结束请求,指示数据已保存。

现在,一旦我们通过单击表单中的按钮提交表单数据,我们将在我们的transaction database中保存一个新的transaction实例。

让我们检查到目前为止的进展。我们将再次启动服务器,使用下面显示的命令:

使用Node.js构建收费公路管理系统

一旦服务器启动,我们可以继续访问/newReceipt路由,以获取“newReceipt.html”作为响应。一旦我们输入vehicleNumber和amount,并点击按钮,我们将看到一个响应“已保存”,说明数据已保存。以下是示例演示:

使用Node.js构建收费公路管理系统

现在我们已经将事务保存在数据库中,我们还需要显示这些事务。为此,我们将在主页路由中创建一个获取请求,以表格格式显示所有记录。为此,我们需要在Server.js文件中添加以下代码:

从Server.js文件向主页路由发送从数据库中获取的数据:

Server.js:

// Server.js 
  
// Handling request on home route 
app.get("/", function (req, res) { 
      res.send("got a request on home route"); 
});

为了从我们的transactionDatabase中获取数据,我们需要使用Mongoose软件包,并且我们要使用的函数是find(),它会接受两个参数,一个是条件(在这种情况下没有条件,因为我们要获取所有记录),根据该条件从数据库中获取数据,第二个是回调函数。下面的代码示例了这一点:

Server.js:

// Server.js 
  
// Handling the home route 
app.get("/", function (req, res) { 
    
      // Fetching all the transaction data from  
    // the database 
      Transaction.find({}, function (err, docs) { 
      
        // Sending the transactions found as 
        // a response to this route 
        res.send(docs); 
      }); 
});

在上面的代码中,有几点需要注意: 第一个参数在find()函数中保持空白,因为我们想要获取所有记录而不带任何条件。 回调函数中的“docs”参数包含了我们从数据库中提取的所有数据。 res.send()方法以JSON格式将所有提取的数据作为响应发送。 所以,让我们再次测试一下。重新启动服务器,使用命令“node server.js”(如下面的GIF图像所示),然后进入主页路径,你将看到一个像这样的响应:

使用Node.js构建收费公路管理系统

到目前为止,我们已经从主页路由获取了transactionDatabase的数据,但数据以原始的JSON格式呈现。

以系统化的方式展示数据: 现在,我们的最后任务是以表格形式以系统化的方式展示这些数据。为此,我们将使用一个名为“ejs”的软件包,它是我们之前已经安装的软件包,它基本上允许我们在HTML中使用Server.js文件的变量。首先,我们需要在目录中创建一个“views”文件夹,然后在该文件夹中创建一个新的“index.ejs”文件。注意,我们也可以在ejs文件中编写简单的HTML代码。因此,让我们从将简单的HTML内容添加到我们的index.ejs页面开始。

index.ejs文件的起始代码如下(基本的HTML代码):

<!-- index.ejs file -->
<!DOCTYPE html> 
<html lang="en" dir="ltr"> 
  
<head> 
    <meta charset="utf-8"> 
    <title>All Transactions</title> 
</head> 
  
<body> 
    <h1>List of All Transactions</h1> 
</body> 
  
</html>

现在,在处理主页路由的get请求时,我们必须传递index.ejs文件,以及我们从transactionDatabase获取到的数据。为此,在处理主页路由的get请求时,我们必须对主页路由进行以下更改:

不再使用res.send()方法,而是使用res.render()方法,其中我们将传递两个参数,第一个是我们要作为响应发送的ejs文件,第二个是我们要发送到ejs文件的数据。

具体代码如下:

Server.js:

// Server.js 
  
app.get("/", function (req, res) { 
  
    // Finding all the transactions 
    Transaction.find({}, function (err, docs) { 
          
        // We are not going to use res.send() function 
        // res.send(docs); 
  
        // Using res.render() method instead of  
        // res.send() method 
        // Using res.render() method, we can 
        // pass data to the front-end 
        res.render("index", { 
            docs: docs, 
        }); 
    }); 
});

以下是与上述代码相关的注意事项:

  • 在res.render()方法中,第一个参数是’index’,用于指定我们将’index.ejs’文件作为响应发送。
  • res.render()方法中的第二个参数是docs,它是从transactionDatabase中获取的数据(所有收费记录),我们将docs变量发送到我们的”index.ejs”文件中,在那里可以以表格的形式显示这些数据。

现在,在index.ejs文件中,我们需要创建表格并使用ejs来正确排列从Server.js文件获取的数据。

为此,首先我们需要创建表格元素,然后使用以下代码添加表格标题:

Index.ejs:

<!DOCTYPE html> 
<html lang="en" dir="ltr"> 
  
<head> 
    <meta charset="utf-8"> 
    <link href= 
"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity= 
"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" 
        crossorigin="anonymous"> 
</head> 
  
<body style="padding:2%;"> 
    <div class=""> 
        <h1>List of all Transactions</h1> 
    </div> 
    <div class="transactions-table" 
        style="border:2px solid black;"> 
        <table class="table"> 
            <thead> 
                <tr> 
                    <th scope="col">Sr. No.</th> 
                    <th scope="col">Vehicle Number</th> 
                    <th scope="col">Date</th> 
                    <th scope="col">Time</th> 
                    <th scope="col">Amount</th> 
                </tr> 
            </thead> 
            <tbody> 
            </tbody> 
        </table> 
    </div> 
</body> 
  
</html>

在上面给出的代码中,有几个重要的要点需要注意:

  • 我们添加了Bootstrap CDN,以使表格看起来更清晰,整洁,并且还添加了一些简单的内联CSS,使事情看起来更有条理。
  • 到目前为止,我们只添加了表格的标题,接下来的几个步骤中,我们将把从Server.js文件中获取到的数据添加到我们的表格正文中。

在继续下一步之前,您必须对Nodejs的ejs软件包有足够的了解。

向Index.ejs文件添加Javascript代码: 现在,我们将在HTML代码中或index.ejs文件中使用Javascript,这是ejs允许我们做的事情。

这是我们将要做的事情:

  • 我们将在index.ejs文件中创建一个简单的for循环,该循环将运行与我们的docs变量中记录数一样多的次数,而docs变量则是我们从Server.js文件获取到的数据。
  • 对于每条记录,我们将创建一个新的<tr>表格行)标签,并在每个“tr”标签内部添加5个<td>(表格数据)标签。
  • 这5个<td>标签将根据记录中的数据依次包含Sr. No.、Vehicle Number、Date、Time和Amount。

这是我们将要这样做的方式(下面仅提供了表格正文标签的代码,即<tbody>):

Index.ejs:

<!-- index.ejs file -->
  
<tbody> 
    <% for(var i=0; i< docs.length; i++) { %> 
    <tr> 
        <td> 
            <%= i %> 
        </td> 
        <td> 
            <tbody> 
                <% for(var i=0; i< docs.length; i++) { %> 
                    <tr> 
                        <td> 
                            <%= i %> 
                        </td> 
                        <td> 
                            <%= docs[i].vehicleNumber %> 
                        </td> 
                        <td> 
                            <%= docs[i].date %> 
                        </td> 
                        <td> 
                            <%= docs[i].time %> 
                        </td> 
                        <td> 
                            <%= docs[i].tollAmount %> 
                        </td> 
                    </tr> 
                    <% } %> 
            </tbody> 
            <%= docs[i].vehicleNumber %> 
        </td> 
        <td> 
            <%= docs[i].date %> 
        </td> 
        <td> 
            <%= docs[i].time %> 
        </td> 
        <td> 
            <%= docs[i].tollAmount %> 
        </td> 
    </tr> 
    <% } %> 
</tbody>

上面的HTML代码看起来有点奇怪,因为我们在其中使用了Javascript,用于创建for循环并使用Javascript变量。这是对上面代码的解释:

  • <% %>”是用于在扩展名为ejs的文件中写入一行Javascript代码的括号。所以,在这里,我们在“<% %>”标签中写入了for循环。
  • “docs.length”表示我们数据库中的交易记录数量,上面创建的for循环将运行这么多次。
  • docs[i]表示我们数据库中的第i条记录,docs[i].vehicleNumber表示第i条记录中的vehicleNumber变量。(同样,docs[i].date代表第i条记录中的date变量,以此类推)。
  • 每次运行for循环时,我们将创建一行(<tr>标签),并在一行中使用5个<td>标签设置5个数据变量。

在这里还有最后一件事要做的是,在我们的主页或交易页面上添加一个“添加交易”按钮,点击该按钮,我们可以生成一个新的交易。我们的index.ejs文件中只需要一个简单的表单元素。代码如下所示:

Index.ejs:

<form class="" action="/newReceipt" method="get"> 
      <button type="submit" name="button" 
        style="margin-top:1%;"> 
          Add Transaction 
      </button> 
</form>

现在我们已经完成了index.ejs文件,我们已经完成了我们的应用程序,现在我们将进行最后一次测试。因此,请使用如下所示的“node server.js”命令重新启动服务器:

使用Node.js构建收费公路管理系统

我们应用的结果如下所示:

使用Node.js构建收费公路管理系统

完整代码: 下面给出了Server.js文件和NewReceipt.html文件的完整代码:

// Server.js 
  
const express = require("express"); 
const app = express(); 
const mongoose = require("mongoose"); 
const ejs = require("ejs"); 
app.set("view engine", "ejs"); 
  
const bodyParser = require("body-parser"); 
  
app.use( 
    bodyParser.urlencoded({ 
        extended: true, 
    }) 
); 
app.set("view engine", "ejs"); 
  
mongoose.connect( 
"mongodb://127.0.0.1/transactionDatabase", { 
    useNewUrlParser: true, 
    useUnifiedTopology: true, 
}); 
  
const transactionSchema = new mongoose.Schema({ 
    vehicleNumber: String, 
    date: String, 
    time: String, 
    tollAmount: Number, 
}); 
  
const Transaction = mongoose.model( 
    "Transaction", transactionSchema); 
  
app.get("/", function (req, res) { 
    Transaction.find({}, function (err, docs) { 
        // res.send(docs); 
        res.render("index", { 
            docs: docs, 
        }); 
    }); 
}); 
  
app.get("/newReceipt", function (req, res) { 
    res.sendFile(__dirname + "/newReceipt.html"); 
}); 
  
app.post("/newReceipt", function (req, res) { 
    var t = new Transaction({ 
        vehicleNumber: req.body.vehicleNumber, 
        date: getDate(), 
        time: getTime(), 
        tollAmount: req.body.amount, 
    }); 
    t.save(); 
    res.send("saved"); 
}); 
  
function getDate() { 
    var date = new Date(); 
    date = date.toString(); 
    console.log(date.substring(0, 10)); 
    return date.substring(0, 10); 
} 
  
function getTime() { 
    var today = new Date(); 
    return today.getHours() + ":" 
        + today.getMinutes() + ":" 
        + today.getSeconds(); 
} 
  
app.listen(8080, function () { 
    console.log("Server listening on port 8080"); 
});

HTML代码

<!-- Newreceipt.html -->
  
<!DOCTYPE html> 
<html lang="en" dir="ltr"> 
  
<head> 
    <meta charset="utf-8"> 
    <link href= 
"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" 
        rel="stylesheet"
        integrity= 
"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" 
        crossorigin="anonymous"> 
</head> 
  
<body style="padding:1%;"> 
    <div class=""> 
        <h1>New Transaction</h1> 
    </div> 
    <form class="" action="/newReceipt" method="post"> 
        <label for="">Vehicle Number</label> 
        <input type="text" name="vehicleNumber" 
            value="" style="margin-bottom:1%;"> 
        <br> 
        <label for="">Amount</label> 
        <input type="number" name="amount" 
            value="" style="margin-bottom:1%;"> 
        <br> 
        <button type="submit" name="button"> 
            Add Transaction 
        </button> 
    </form> 
</body> 
  
</html>

结论: 现在我们可以使用这个应用记录过路车辆的交易,包括车牌号、日期、时间和过路费金额。除此之外,所有的过路费交易将会在我们的主页上统一列出。建立一个收费公路管理系统可以极大地提高收费、交通管理和整体道路安全的效率和效果。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程