第二次作业
一,前言
本次作业是基于第一次作业计算器界面设计功能上的功能拓展,通过使用nodejs连接mongdb数据库,并将计算器的历史记录进行记录。
二,概要设计
首先是对登录和注册界面的设计,登录界面需要用户名输入框和用户密码输入框并且需要两个登录注册按钮,注册界面需要用户名输入框和用户密码输入框并且需要一个登录按钮,在进入注册界面后,当注册界面关闭后会直接跳转到用户登陆界面。

功能设计图如下:

在用户输入账号和密码后,这些数据将会存储到数据库当中,用户类的E-R图如下:

在本次的项目设计在,开发工具选择Vscode,数据库使用mongdb,web服务器使用node-express框架创建。
三,前端界面设计
(一)登录注册界面设计

1 <body> 2 <div class="container"> 3 <div class="row"> 4 <div class="col-xs-12 col-md-8 col-md-offset-2 col-lg-4 col-lg-offset-4"> 5 <h2>登录</h2> 6 <hr /> 7 <form method="post" action="/login"> 8 <div class="form-group"> 9 <label for="item">用户名</label> 10 <input name="username" type="text" class="form-control" id="item" /> 11 </div> 12 <div class="form-group"> 13 <label for="time">密码</label> 14 <input name="password" type="password" class="form-control" id="time" /> 15 </div> 16 <hr> 17 <button type="submit" class="btn btn-primary btn-block">登录</button> 18 </form> 19 </div> 20 </div> 21 </div> 22 </body>

1 <body> 2 <div class="container"> 3 <div class="row"> 4 <div class="col-xs-12 col-md-8 col-md-offset-2 col-lg-4 col-lg-offset-4"> 5 <h2>注册</h2> 6 <hr /> 7 <form method="post" action="/reg"> 8 <div class="form-group"> 9 <label for="item">用户名</label> 10 <input name="username" type="text" class="form-control" id="item" /> 11 </div> 12 <div class="form-group"> 13 <label for="time">密码</label> 14 <input name="password" type="password" class="form-control" id="time" /> 15 </div> 16 <hr> 17 <button type="submit" class="btn btn-primary btn-block">注册</button> 18 </form> 19 </div> 20 </div> 21 </div> 22 </body>
计算器界面代码继续延用第一次作业的计算器的界面设计,当用户从登陆界面登录成功后会直接跳转到计算器界面。
四,数据库用户表设计
对于数据库的设计,我们需要设计用户表来存储用户的信息,包含了用户名(Uname)和密码(Password),在nodejs中我们使用shortid组件使数据库可以自动在数据库中为每一组用户数据创建唯一的ID索引。这样方便了用户的登录,可以让用户通过用户名并且确保不会登录到其他人的账号。创建用户表的基本结构如下:
1 // 定义bookSchema模式 2 const mongoose = require('mongoose'); 3 4 const bookSchema = new mongoose.Schema({ 5 name: String, 6 7 Password: Number 8 }); 9 10 // 定义Book模型 11 const Book = mongoose.model('Book', bookSchema); 12
13 //暴露book模型 14 module.exports = Book;
这时我们已经创建了一个名为books的用户表,在这个用户表中包含了三列,包含了用户的信息和唯一ID索引,现在通过插入数据来查看是否成功连接到数据库:
1 const db = require('./db/db'); 2 const Book = require('./models/Book'); 3 4 const mongoose = require('mongoose'); 5 6 db(() => { 7 // 创建记录 8 const createBook = async () => { 9 try { 10 const newBook = new Book({ 11 name: '安三', 12 13 Password: '342432' 14 }); 15 await newBook.save(); 16 console.log('Create book successfully'); 17 } catch (err) { 18 console.error(err); 19 } 20 }; 21 22 // 创建用户记录 23 createBook(); 24 25 }, () => { 26 // 连接关闭后执行的回调函数 27 mongoose.disconnect(); 28 }, () => { 29 console.log('连接失败'); 30 });
测试所得的数据库情况如下所示:

五,代码设计
使用Express框架创建Web应用程序的示例。引入了各种模块,设置了应用程序的视图引擎和静态文件目录。然后,定义了不同的路由文件,并将它们应用于相应的路径。最后,定义了404和错误处理程序。

1 var createError = require('http-errors'); 2 var express = require('express'); 3 var path = require('path'); 4 var cookieParser = require('cookie-parser'); 5 var logger = require('morgan'); 6 7 var indexRouter = require('./routes/index'); 8 const authRouter = require('./routes/auth'); 9 var usersRouter = require('./routes/users'); 10 11 var app = express(); 12 13 // view engine setup 14 app.set('views', path.join(__dirname, 'views')); 15 app.set('view engine', 'ejs'); 16 17 app.use(logger('dev')); 18 app.use(express.json()); 19 app.use(express.urlencoded({ extended: false })); 20 app.use(cookieParser()); 21 app.use(express.static(path.join(__dirname, 'public'))); 22 23 app.use('/', indexRouter); 24 app.use('/', authRouter); 25 app.use('/users', usersRouter); 26 27 // catch 404 and forward to error handler 28 app.use(function(req, res, next) { 29 next(createError(404)); 30 }); 31 32 // error handler 33 app.use(function(err, req, res, next) { 34 // set locals, only providing error in development 35 res.locals.message = err.message; 36 res.locals.error = req.app.get('env') === 'development' ? err : {}; 37 38 // render the error page 39 res.status(err.status || 500); 40 res.render('error'); 41 }); 42 43 module.exports = app
使用Express框架创建的路由模块。它引入了Express、lowdb、FileSync、shortid模块,并创建了一个Express Router对象。该路由模块定义了一个GET方法,当访问'/account'时,从数据库中获取computer数组,并渲染list模板,将computer数组传递给模板进行渲染。
// 引入express模块和router模块 var express = require('express'); var router = express.Router(); // 引入lowdb模块和FileSync模块 const low = require('lowdb') const FileSync = require('lowdb/adapters/FileSync'); // 创建一个FileSync适配器对象 const adapter = new FileSync(__dirname + '/../data/db.json') // 使用适配器对象创建一个lowdb对象 const db = low(adapter) // 引入shortid模块 const shortid = require('shortid'); router.get('/account', function(req, res, next) { let computer = db.get('computer').value(); res.render('list', {computer:computer}); });
使用第一次的计算器代码,并对其中的部分代码进行参数回调,时用户在进行计算时,使历史记录可以传回到数据库中,以便对于历史记录的查看。

<!DOCTYPE html>
<html lang="ch-ZN">
<head>
<meta charset="UTF-8">
<title>计算器</title>
<style>
* {
margin: 0;
padding: 0;
}
.button {
width: 50px;
height: 50px;
font-size: 25px;
margin: 2px;
cursor: pointer;
background: #607d8b;
border: none;
color: white;
}
.button1 {
width: 221px;
height: 50px;
font-size: 25px;
margin: 2px;
cursor: pointer;
background: #607d8b;
border: none;
color: white;
}
.textView {
width: 200px;
margin: 5px;
font-size: 23px;
padding: 5px;
border: thick double #32a1ce;;
}
.main {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
html {
background: linear-gradient(to right, #00f7ff, #d0cd77);
height: 100%;
}
</style>
<script>
let a="1343.43245";
let b=a.indexOf(".");
console.log(b);
let c=a.substring(0,b+3);
console.log(c);
function insert(num) {
// TODO 插入
document.form.textView.value = document.form.textView.value + num;
}
function equal() {
// TODO 计算结果,并且结果保留两位小数
let exp = document.form.textView.value;
if (exp) {
let eval1 = eval(document.form.textView.value);
// eval() 执行括号内的语句 , 记录结果
let number = eval1.toString().indexOf(".");
if (number!==-1){
// 如果是小数,保留两位小数
eval1=eval1.toString().substring(0,number+3);
// 截取
document.form.textView.value=eval1;
}else {
// 如果不是小数,直接赋值
document.form.textView.value=eval1;
}
}
}
function Mclean() {
// TODO 清理输入框的文字
document.form.textView.value = null;
}
function back() {
// TODO 删除文本框的一个字符
let exp = document.form.textView.value;
document.form.textView.value = exp.substring(0, exp.length - 1);
// 截取字符串
}
function sqrt() {
let num = parseFloat(document.form.textView.value);
if (num < 0) {
document.form.textView.value='false';
return;
}
var guess = num / 2; // 初始猜测值为 num / 2
var epsilon = 0.00001; // 定义精度值
var previousGuess; // 用于存储上一次的猜测值
do {
previousGuess = guess; // 保存当前猜测值以便下一次迭代使用
guess = (guess + num / guess) / 2; // 牛顿迭代法更新猜测值
} while (Math.abs(guess - previousGuess) > epsilon); // 当两次猜测值之差小于精度值时停止迭代
document.form.textView.value=guess;
}
</script>
</head>
<body>
<div class="main">
<form name="form" method="post" action="/account">
<input class="textView" name="textView" >
</form>
<table>
<tr>
<td><input type="button" class="button" value="C" onclick="Mclean()"></td>
<td><input type="button" class="button" value="<" onclick="back()"></td>
<td><input type="button" class="button" value="/" onclick="insert('/')"></td>
<td><input type="button" class="button" value="x" onclick="insert('*')"></td>
</tr>
<tr>
<td><input type="button" class="button" value="7" onclick="insert(7)"></td>
<td><input type="button" class="button" value="8" onclick="insert(8)"></td>
<td><input type="button" class="button" value="9" onclick="insert(9)"></td>
<td><input type="button" class="button" value="-" onclick="insert('-')"></td>
</tr>
<tr>
<td><input type="button" class="button" value="4" onclick="insert(4)"></td>
<td><input type="button" class="button" value="5" onclick="insert(5)"></td>
<td><input type="button" class="button" value="6" onclick="insert(6)"></td>
<td><input type="button" class="button" value="+" onclick="insert('+')"></td>
</tr>
<tr>
<td><input type="button" class="button" value="1" onclick="insert(1)"></td>
<td><input type="button" class="button" value="2" onclick="insert(2)"></td>
<td><input type="button" class="button" value="3" onclick="insert(3)"></td>
<td rowspan="2"><input style="height: 107px" type="button" class="button" value="=" onclick="equal()"></td>
</tr>
<tr>
<td colspan="2"><input style="width: 107px" type="button" class="button" value="0" onclick="insert(0)"></td>
<td><input type="button" class="button" value="." onclick="insert('.')"></td>
</tr>
</table>
<tr>
<td><input class="button1" value=" 开方计算" onclick="sqrt()"></td>
</tr>
</div>
</body>
</html>
下面这段代码是一个Node.js服务器,使用了Express框架和HTTP模块。
1 var app = require('../app'); 2 var debug = require('debug')('computer:server'); 3 var http = require('http'); 4 5 /** 6 * Get port from environment and store in Express. 7 */ 8 9 var port = normalizePort(process.env.PORT || '3000'); 10 app.set('port', port); 11 12 /** 13 * Create HTTP server. 14 */ 15 16 var server = http.createServer(app); 17 18 /** 19 * Listen on provided port, on all network interfaces. 20 */ 21 22 server.listen(port); 23 server.on('error', onError); 24 server.on('listening', onListening); 25 26 /** 27 * Normalize a port into a number, string, or false. 28 */ 29 30 function normalizePort(val) { 31 var port = parseInt(val, 10); 32 33 if (isNaN(port)) { 34 // named pipe 35 return val; 36 } 37 38 if (port >= 0) { 39 // port number 40 return port; 41 } 42 43 return false; 44 } 45 46 /** 47 * Event listener for HTTP server "error" event. 48 */ 49 50 function onError(error) { 51 if (error.syscall !== 'listen') { 52 throw error; 53 } 54 55 var bind = typeof port === 'string' 56 ? 'Pipe ' + port 57 : 'Port ' + port; 58 59 // handle specific listen errors with friendly messages 60 switch (error.code) { 61 case 'EACCES': 62 console.error(bind + ' requires elevated privileges'); 63 process.exit(1); 64 break; 65 case 'EADDRINUSE': 66 console.error(bind + ' is already in use'); 67 process.exit(1); 68 break; 69 default: 70 throw error; 71 } 72 } 73 74 /** 75 * Event listener for HTTP server "listening" event. 76 */ 77 78 function onListening() { 79 var addr = server.address(); 80 var bind = typeof addr === 'string' 81 ? 'pipe ' + addr 82 : 'port ' + addr.port; 83 debug('Listening on ' + bind); 84 }
这个JavaScript函数是一个模块导出函数。它使用了mongoose
库来连接到本地的一个MongoDB数据库。如果连接成功,会调用
success函数;如果连接失败,会调用error函数。在连接关闭
时,打印一条日志信息。
db.js
1 module.exports = function(success,error) { 2 const mongoose =require('mongoose'); 3 mongoose.connect('mongodb://127.0.0.1:27017/datacd'); 4 5 mongoose.connection.once('open',() => { 6 success(); 7 }); 8 9 mongoose.connection.on('error',() => { 10 error(); 11 }); 12 13 mongoose.connection.on('close',() => { 14 console.log('连接关闭'); 15 }); 16 }
浙公网安备 33010602011771号