web作业(二)用node.js在树莓派上开发一个便携式教育工具
树莓派部分
系统烧录
具体步骤参考:https://mc.dfrobot.com.cn/thread-306405-1-1.html
可视化界面如下:
热点
要求
由于我的树莓派出了一点小问题,所以这个暂未实现,等我实现好了,再来补充
教育工具部分
学生端
1.注册、登录功能实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学生登录</title>
<link rel="stylesheet" href="stylesheets/style.css">
</head>
<body>
<div class="container">
<form action="/stulogin" method="post">
<div class="title">学生登录</div>
<div class="row">
<input type="text" name="username" placeholder="请输入用户名" required>
</div>
<div class="row">
<input type="password" name="password" placeholder="请输入密码" required>
</div>
<button type="button" id="loginBtn">登录</button>
<a href="sturegister.html">还没有账号?去注册一个</a>
</form>
</div>
</body>
</html>
后端
var studentLogin = function (username, password, req, callback) {
var sqlstr = "SELECT username, password FROM student WHERE username=?";
var params = [username];
var promise = new Promise(function (resolve, reject) {
mysql.query(sqlstr, params, function (err, result) {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
promise.then((result) => {
var status = 0;
if (result[0].password == password) {
status = 1;
req.session.username = result[0].username;
//console.log(req)
}
else if (result == undefined || result.length == 0) {
status = 2;
}
else {
status = 3;
}
callback(status);
})
}
效果如下
注册基本原理一样,除了数据库部分有点不一样
var studentRegister = function (username, password, check, callback) {
var sqlstr = "SELECT username, password FROM student WHERE username=?"
var params = [username];
var promise = new Promise(function (resolve, reject) {
mysql.query(sqlstr, params, function (err, result) {
if (err) {
//alert("error");
reject(err);
}
else {
resolve(result);
}
});
});
promise.then((result) => {
var status = 0;
if (result[0] == username) {
//alert("1");
status = 1;
}
else {
if (password != check) {
status = 3;
}
else {
//alert(username);
var sql = "INSERT INTO student(id,username,password) values(null,?,?)";
var params = [username, password];
//console.log(params);
mysql.query(sql, params, function (err, result) {
console.log(result);
});
}
}
callback(status);
})
}
(其中很多注释掉的就是一遍一遍调试的过程,终于跑通的时候真的有成就感)
其中连接数据库的部分是用老师上课给的代码实现的
const mysql = require('mysql');
var pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'root',
database: 'database'
});
var query = function(sql, sqlparam, callback) {
pool.getConnection(function(err, conn) {
if (err) {
callback(err, null, null);
} else {
conn.query(sql, sqlparam, function(qerr, vals, fields) {
conn.release(); //释放连接
callback(qerr, vals, fields); //事件驱动回调
});
}
});
};
var query_noparam = function(sql, callback) {
pool.getConnection(function(err, conn) {
if (err) {
callback(err, null, null);
} else {
conn.query(sql, function(qerr, vals, fields) {
conn.release(); //释放连接
callback(qerr, vals, fields); //事件驱动回调
});
}
});
};
exports.query = query;
exports.query_noparam = query_noparam;
2.下载
app.get("/download", function (req, res) {
fs.readdir("./public/upload", function (err, data) {
//console.log(data)
if (err) {
console.log(err)
//console.log("error")
} else {
//console.log(req)
res.render("../public/download.html", {
files: data
})
}
})
})
3.做题目
app.post("/doneproblem", function (req, res) {
var data = req.body
var total = 0;
var right = 0;
connection.query("select * from problems", function (res_, rows) {
for (var i = 0; i < rows.length; i++) {
total++;
var id_ = rows[i].id;
var answer_ = rows[i].answer;
console.log(data[id_])
if (data[id_] == answer_) {
right++;
}
}
res.render("../views/situation.html");
})
})
效果如下:
做题目我还加了用饼图可视化实现(根据每个同学的情况生成一张图)
可以完善的是,应该收集所有的学生的答题信息,在老师端生成可视化的图或者表更合理一些。
4.看老师讲题
老师讲题是,老师在图中修改,学生应该是可以看到老师的墨迹
这里用到了socket实现
学生端前端代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>看图</title>
<link rel="stylesheet" type="text/css" href="./stylesheets/nav.css">
</head>
<body>
<ul>
<li><a class="active" href="#">主页</a></li>
<li id="download"><a href="#">下载</a></li>
<li id="live"><a href="#">进入直播</a></li>
<li id="problem"><a href="#">完成作业</a></li>
<li id="getpicture"><a href="#">看图</a></li>
</ul>
<div class="paint">
<canvas id="canvas" width="500" height="400" style="border:1px solid #c3c3c3;"></canvas>
</div>
</body>
<script src="javascripts/jquery-3.5.1.js"></script>
<script src="./socket.io.js"></script>
<script src="../node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
document.getElementById("download").onclick = function(){
location.href = "/download"
}
document.getElementById("problem").onclick = function(){
location.href = "/doproblem"
}
document.getElementById("getpicture").onclick = function(){
location.href = "/getpicture"
}
</script>
<script>
var socket = io("http://localhost:3000");
socket.on('connect',function(){
console.log('connected')
})
socket.on('info',function(data){
var img=new Image()
img.src=data;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
img.onload = function(){
context.drawImage(img,0,0,500,400);
}
})
socket.on('disconnect',function(){
console.log('disconnected')
})
window.onload=function(){
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var temp = false;
socket.on('info1',function(data){
temp=true;
var x=data[0];
var y=data[1];
context.moveTo(x,y);
})
socket.on('info2',function(data){
var x=data[0];
var y=data[1];
if(temp){
context.lineTo(x,y);
context.stroke();
}
})
socket.on("info3",function(data){
if(data==1){
temp=false;
}
})
}
</script>
</html>
效果如下(现在是一个画布)
教师端
大致与学生端一样
以下是与学生不太一样的
1.出题界面
app.get("/giveproblem", function (req, res) {
connection.query("select * from problems", function (err, rows) {
connection.query("select * from situation", function (error, info) {
//console.log(info)
res.render("../views/giveproblem.html", {
problems: rows,
situations: info
})
})
})
})
2.会绘图讲题实现,让学生可以实时看到老师的墨迹
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>绘图</title>
<link rel="stylesheet" type="text/css" href="./stylesheets/nav.css">
</head>
<body>
<ul>
<li><a class="active" href="#">主页</a></li>
<li id="upload"><a href="#">上传</a></li>
<li id="live"><a href="#">进入直播</a></li>
<li id="problem"><a href="#">发布作业</a></li>
<li id="draw"><a href="#">画图</a></li>
</ul>
<div class="paint">
<canvas id="canvas" width="500" height="400" style="border:1px solid #c3c3c3;"></canvas>
</div>
<input accept="image/*" type="file" id="uploadIMG" onchange="btnUploadFile(event)" />
</body>
<script src="javascripts/jquery-3.5.1.js"></script>
<script src="./socket.io.js"></script>
<script src="../node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
var socket = io("http://localhost:3003");
socket.on('connect', function () {
console.log('连接成功')
})
socket.on('disconnect', function () {
console.log('断开连接')
})
function btnUploadFile(e, type) {
var files = e.target.files;
var file = files[0];
if (!/\/(?:jpeg|jpg|png)/i.test(file.type)) {
return;
}
var reader = new FileReader();
reader.onload = function () {
var result = this.result;
socket.emit("send", result)
};
reader.readAsDataURL(file);
}
socket.on('info', function (data) {
var img = new Image()
//console.log(data)
img.src = data;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
//console.log(result)
img.onload = function () {
context.drawImage(img, 0, 0, 500, 400);
}
})
window.onload = function () {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
paint(context);
}
function paint(context) {
var temp = false;
$("canvas").mousedown(function (e) {
temp = true;
var x = e.pageX - 8;
var y = e.pageY - 8;
context.moveTo(x, y);
socket.emit("send1", [x, y])
})
$("canvas").mousemove(function (e) {
var x = e.pageX - 8;
var y = e.pageY - 8;
//$("#info").html("( "+x+" , "+y+" )");
socket.emit("send2", [x, y])
if (temp) {
context.lineTo(x, y);
context.stroke();
}
})
$("canvas").mouseup(function (e) {
temp = false;
socket.emit("send3", 1)
})
}
</script>
<script>
document.getElementById("upload").onclick = function () {
location.href = "/upload.html"
}
document.getElementById("problem").onclick = function () {
location.href = "/giveproblem"
}
// document.getElementById("live").onclick = function () {
// location.href = "/live"
// }
document.getElementById("draw").onclick = function () {
location.href = "/draw"
}
</script>
</html>
后端代码
var server = require("http").createServer(app);
var io = require('socket.io')(server);
io.listen(3003);
io.on('mysql', function (socket) {
socket.on("send", function (data) {
io.emit("info", data)
})
socket.on("send1", function (data) {
console.log(data);
io.emit("info1", data)
})
socket.on("send2", function (data) {
io.emit("info2", data)
})
socket.on("send3", function (data) {
io.emit("info3", data)
})
socket.on('reply', function () { })
})
总结
这算我完成的第一个项目,可能很多大佬觉得简单,但是实现的过程中我真的学到了很多,有了一些前后端分离的想法,也提升了一点调试代码的能力。最后感谢一下老师,以及帮助我的同学,真的非常感谢。