- 浏览: 5162775 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
silence19841230:
先拿走看看
SpringBoot2.0开发WebSocket应用完整示例 -
wallimn:
masuweng 写道发下源码下载地址吧!三个相关文件打了个包 ...
SpringBoot2.0开发WebSocket应用完整示例 -
masuweng:
发下源码下载地址吧!
SpringBoot2.0开发WebSocket应用完整示例 -
masuweng:
SpringBoot2.0开发WebSocket应用完整示例 -
wallimn:
水淼火 写道你好,我使用以后,图标不显示,应该怎么引用呢,谢谢 ...
前端框架iviewui使用示例之菜单+多Tab页布局
这些天有点儿空闲,学习了一下node.js。先把《Node.js开发指南》书中的博客例子调通了,费了挺大的劲儿,因为好多插件出了新的版本,而新版本中有的函数、方法又失效了。
自已又练习着做了一个例子,个人记账系统。主要是想在手机上用,所以界面做得很简单。
解决了以下一些问题:express使用、bootstrap排版布局、mongodb模糊查询、mongodb统计(group/mapReduce)、session处理、req.flash方法使用等、路由设置等。花了不少的心思。
例子中用到的插件的版本:
connect-flash@0.1.1
connect-mongo@0.4.0
ejs@0.8.5
express@3.4.8
mongodb@1.3.23
Bootstrap V3.0.3
贴几张系统运行的图片,有图有真相嘛。
核心代码贴一下:
一、app.js
二、路由处理(routes\index.js)
三、消费数据处理(modules\consume.js)
全部源码见附件。
另,2014-04-02
系统开发好了之后,找了个服务器部署了一下,老婆用得不错,原来不太喜欢记账,现在记账很积极。我就又把系统完善了一下,增加了翻页、权限控制功能,将几个按钮修改成图标,布局更紧凑了一些,使用全局变量保存系统名称,方便修改。
自已又练习着做了一个例子,个人记账系统。主要是想在手机上用,所以界面做得很简单。
解决了以下一些问题:express使用、bootstrap排版布局、mongodb模糊查询、mongodb统计(group/mapReduce)、session处理、req.flash方法使用等、路由设置等。花了不少的心思。
例子中用到的插件的版本:
connect-flash@0.1.1
connect-mongo@0.4.0
ejs@0.8.5
express@3.4.8
mongodb@1.3.23
Bootstrap V3.0.3
贴几张系统运行的图片,有图有真相嘛。
核心代码贴一下:
一、app.js
/** * Module dependencies. */ var express = require('express'); var http = require('http'); var path = require('path'); var util=require('util'); var routes = require('./routes'); //var User = require('./modules/user.js'); var settings=require('./Settings'); var MongoStore = require('connect-mongo')(express); var flash = require('connect-flash'); var app = express(); //app.set('appTitle','老王个人记账系统'); app.locals.gAppTitle = settings.appName; //这个没有使用 app.locals.gPageSize = settings.pageSize; // all environments app.set('port', process.env.PORT || 8484); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.json()); app.use(express.bodyParser()); app.use(express.urlencoded()); app.use(express.methodOverride()); app.use(express.cookieParser()); app.use(flash()); app.use(express.session({ "secret":settings.cookieSecret, "store":new MongoStore({ db:settings.db }) })); app.use(function(req, res, next){ //跟踪; //console.log("req.method="+req.method); //console.log("req.url="+req.url); //console.log("req.originalUrl="+req.originalUrl); var url = req.originalUrl; //简单地定义一个登录拦截器 if ((url == "/month" || url=="/stat" || url=='/list' || url=='/record') && !req.session.user) { console.log("登录拦截器提示:必须登录,才能执行此项操作。"); req.flash('error', '请先登录。'); return res.redirect("/login"); } res.locals.user = req.session.user; var error = req.flash('error'); res.locals.error = error.length?error:null; //console.log("转移flash中的error值:"+error); var success = req.flash('success'); res.locals.success = success.length?success:null; //console.log("转移flash中的success值:"+success); res.locals.session = req.session; next(); }); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); //console.log(util.inspect(app)); // development only if ('development' == app.get('env')) { app.use(express.errorHandler()); } //console.log('注册路由.'); routes(app); http.createServer(app).listen(app.get('port'), function(){ console.log(); console.log(); console.log('/**************************************************/'); console.log('/* 我的第一个NODE.JS例子。BY 隔壁老王 2014-3-29 */'); console.log('/* 欢迎访问我的博客:http://wallimn.iteye.com */'); console.log('/**************************************************/'); console.log('============服务启动成功,监听端口:' + app.get('port')+"============"); });
二、路由处理(routes\index.js)
var crypto = require('crypto'); var User = require('../modules/user.js'); var Consume = require('../modules/consume.js'); /* * GET home page. */ module.exports = function(app) { app.get('/',function(req, res){ res.render('index', { title: '首页' }); /* res.render('login',{ title:'用户登录', }); */ //res.redirect('/login'); }); app.get('/record',function(req,res){ var user = req.session.user; if(!user){ req.flash('error', '用户未登录,请登录。'); return res.redirect('/login'); } Consume.get(user.name,{limit:16}, function(err, records) { if (err) { req.flash('error', err); return res.redirect('/error'); } res.render('record', { title: user.name, consumes: records, }); }); }); //预处理,如果通过,再进行下一个。 app.post('/record',checkLogin); app.post('/record', function(req, res) { var currentUser = req.session.user; var record = new Consume(); record.loadFromReq(currentUser.name, req.body); record.save(function(err) { if (err) { req.flash('error', err); return res.redirect('/'); } req.flash('success', '发表成功'); res.redirect('/record'); }); }); //这个应该去掉。留在这里当个后门吧 //可以查看其他用户的数据 app.get('/u/:user', function(req, res) { var username = req.params.user; if (!username) { req.flash('error', '未指定用户'); return res.redirect('/error'); } Consume.get(username,{limit:0}, function(err, records) { if (err) { req.flash('error', err); return res.redirect('/error'); } console.log(records); res.render('list', { title: username, consumes: records, }); }); }); app.get('/del/:id', function(req, res) { var id = req.params.id; if (!id) { req.flash('error', '未指定要删除的记录ID'); return res.redirect('/error'); } console.log("准备删除记账记录,_id="+id); Consume.del(id, function(err, records) { if (err) { req.flash('error', err); return res.redirect('/error'); } res.redirect('/record');; }); }); app.get('/logout',function(req,res){ req.session.user = null; req.flash('success','登出成功'); res.redirect('/login'); }); app.get('/list',function(req,res){ var user = req.session.user; if(!user){ req.flash('error', "您没有登录,请登录。"); console.log("没有登录,重定向的登录界面。"); return res.redirect('/login'); } Consume.get(user.name,{limit:0}, function(err, records) { if (err) { req.flash('error', err); return res.redirect('/error'); } res.render('list', { title: user.name, consumes: records, }); }); }); app.post('/search',function(req,res){ var user = req.session.user; if(!user){ req.flash('error', "您没有登录,请登录。"); return res.redirect('/login'); } var keyword = req.body.keyword; console.log("搜索关键字:"+keyword); Consume.get(user.name,{limit:0,keyword:keyword}, function(err, records) { if (err) { req.flash('error', err); return res.redirect('/error'); } res.render('record', { title: user.name, consumes: records, }); }); }); app.get('/stat',function(req,res){ var user = req.session.user; Consume.stat(user.name, function(err, results) { if (err) { req.flash('error', err); return res.redirect('/error'); } res.render('stat', { title: user.name, results: results, }); }); }); app.get('/month',function(req,res){ var user = req.session.user; Consume.month(user.name, function(err, results) { if (err) { req.flash('error', err); return res.redirect('/error'); } res.render('stat', { title: user.name, results: results, }); }); }); app.get('/error',function(req,res){ res.render('error'); }); //处理用户登录。 app.post('/login',function(req,res){ var md5=crypto.createHash('md5'); var password = md5.update(req.body.password).digest('hex'); User.get(req.body.username,function(err,user){ if(!user){ req.flash('error','用户不存在'); return res.redirect('/login'); } if(user.password!=password){ req.flash('error','用户口令错误'); return res.redirect('/login'); } req.session.user = user; req.flash('success','登入成功'); //res.redirect('/'); res.redirect('/record'); }); }); app.get('/login',function(req,res){ res.render('login',{ title:'用户登录', }); }); app.get('/reg',function(req,res){ res.render('reg',{ title:'用户注册' }); }); app.post('/reg',function(req,res){ if(req.body['password-repeat']!=req.body['password']){ req.flash('error','两次输入的口令不一致!'); return res.redirect('/reg'); } var md5=crypto.createHash('md5'); var password = md5.update(req.body.password).digest('hex'); var newUser = new User({ name:req.body.username, password:password, }); User.get(newUser.name,function(err,user){ if(user) err='同名用户已经存在,请更换名字.'; if(err){ req.flash('error',err); return res.redirect('/reg'); } newUser.save(function(err){ if(err){ req.error=err; return res.redirect('/reg'); } req.session.user = newUser; req.flash('success','注册成功!'); res.redirect('/record'); }); }); }); //测试函数 app.get('/hello',function(req,res){ res.send('The time is '+new Date().toString()); }); //测试函数 app.get('/sayhello',function(req,res){ res.send('hello '+req.params.username); }); }; //检查是否登入. function checkLogin(req, res, next) { if (!req.session.user) { req.flash('error', '尚未登录,无法操作。'); return res.redirect('/error'); } next(); } function checkNotLogin(req, res, next) { if (req.session.user) { req.flash('error', '已登入'); return res.redirect('/'); } next(); }
三、消费数据处理(modules\consume.js)
var mongodb = require('./db'); var BSON = require('mongodb').BSONPure; var util=require('util'); function toObjectId(id){ console.log("转换值:"+id); if( id=="" || id=="null" || id=="undefined" || id==undefined || id==null)return null; return BSON.ObjectID.createFromHexString(id); } function Consume(username, consumeDate,consumeSubject,consumeAmount,consumeRemark, time) { //加载时要单独赋值 this._id=null; this.userName = username; this.consumeDate = consumeDate; this.consumeSubject = consumeSubject; this.consumeAmount = consumeAmount; this.consumeRemark = consumeRemark; if (time) { this.time = time; } else { this.time = new Date(); } }; module.exports = Consume; Consume.prototype.loadFromReq = function loadFromReq(username,reqBody,time){ //自动进行了ID类型的转换。 this._id = toObjectId(reqBody._id); this.userName = username; this.consumeDate = reqBody.consumeDate; this.consumeSubject = reqBody.consumeSubject; this.consumeAmount = reqBody.consumeAmount; this.consumeRemark = reqBody.consumeRemark; if (time) { this.time = time; } else { this.time = new Date(); } } Consume.prototype.save = function save(callback) { // 存入 Mongodb 的文档 var record = { _id:this._id, userName: this.userName, consumeDate: this.consumeDate, consumeSubject: this.consumeSubject, consumeAmount: this.consumeAmount, consumeRemark: this.consumeRemark, time: this.time, }; console.log('保存,记录日期:'+record.consumeDate); mongodb.open(function(err, db){ if (err) { return callback(err); } // 读取 posts 集合 db.collection('consume', function(err, collection){ if (err) { mongodb.close(); return callback(err); } // 插入 /* collection.insert(record, {safe: true} , function(err, post){ mongodb.close(); callback(err, post); }); */ console.log("插入或更新,判断依据_id="+record._id); if(record._id==null){ delete record._id; console.log("删除_id,record._id="+record._id); } collection.update({_id:(record._id?record._id:'no-record')}, record, {upsert:true,multi:false} , function(err, post){ mongodb.close(); callback(err, post); }); }); }); }; //删除方法 Consume.del = function del(id,callback){ mongodb.open(function(err,db){ if (err){ return callback(err); } var query = {_id:BSON.ObjectID.createFromHexString(id)}; db.collection('consume', function(err, collection){ if (err){ mongodb.close(); return callback(err); } collection.remove(query,{safe:true},function(err,result){ mongodb.close(); if (err){ return callback(err); } console.log("删除成功。"); callback(null); }) ; }); }); }; Consume.get = function get(username,options, callback) { mongodb.open(function(err, db){ if (err){ return callback(err); } // 读取 posts 集合 db.collection('consume', function(err, collection){ if (err){ mongodb.close(); return callback(err); } var query = {}; if(options.keyword){ //var regx = new RegExp("/"+options.keyword+"/"); //注意,不用/ var regx = new RegExp(options.keyword); //限制用户名,科目或者金额与输入关键相等 query={"$and":[{userName:username}, {"$or":[{consumeSubject:regx}, {consumeDate:regx}, {consumeAmount:options.keyword} ] }] }; } else{ query.userName = username; } console.log("搜索条件:"); console.log(query); if(!options.limit){ options.limit=0; } collection.find(query).sort({consumeDate:-1 }).limit(options.limit).toArray(function(err, docs){ mongodb.close(); if (err){ callback(err, null); } var consumes = []; docs.forEach(function(doc, index){ var record = new Consume(doc.userName, doc.consumeDate,doc.consumeSubject,doc.consumeAmount,doc.consumeRemark, doc.time); record._id = doc._id; consumes.push(record); }); callback(null, consumes); }); }); }); }; Consume.stat = function stat(username, callback) { mongodb.open(function(err, db){ if (err){ return callback(err); } // 读取 posts 集合 db.collection('consume', function(err, collection){ if (err){ mongodb.close(); return callback(err); } var reduce = function(obj,prev){ prev.amount += isNaN(obj.consumeAmount)?0:Number(obj.consumeAmount); prev.count++; }; collection.group( [ 'consumeSubject' ], {userName:username}, {count:0,amount:0}, reduce, function(err, result){ mongodb.close(); if (err){ callback(err, null); } else{ console.log(result[0]); var amount = 0,count=0; result.forEach(function (item,index){ amount += item.amount; count += item.count; }); result.push({consumeSubject:'【合计】',count:count,amount:amount}); callback(null, result); } }); }); }); }; Consume.month = function month(username, callback) { mongodb.open(function(err, db){ if (err){ return callback(err); } // 读取 posts 集合 db.collection('consume', function(err, collection){ if (err){ mongodb.close(); return callback(err); } var map = function(){ emit(this.consumeDate.substr(0,7),{amount:this.consumeAmount,count:1}); }; var reduce = function(key,vals){ var val = 0,count=0; for(var i=0; i<vals.length;i++){ val += isNaN(vals[i].amount)?0:Number(vals[i].amount); count++; } return {amount:val,count:count}; } console.log("统计:"+username); collection.mapReduce( map, reduce, {out: {replace : 'temp', readPreference : 'secondary', query:{userName:username}}}, function(err, collection){ if (err){ mongodb.close(); callback(err, null); } else{ //console.log(collection); /* var amount = 0,count=0; result.forEach(function (item,index){ amount += item.amount; count += item.count; }); result.push({consumeSubject:'【合计】',count:count,amount:amount}); */ var results = []; collection.find().toArray(function(err,docs){ docs.forEach(function(item,idx){ console.log(item); //为了共用结果页面,统一使用consumeSubject results.push({consumeSubject:item._id,amount:item.value.amount,count:item.value.count}); }); mongodb.close(); callback(null, results); }); } }); }); }); };
全部源码见附件。
另,2014-04-02
系统开发好了之后,找了个服务器部署了一下,老婆用得不错,原来不太喜欢记账,现在记账很积极。我就又把系统完善了一下,增加了翻页、权限控制功能,将几个按钮修改成图标,布局更紧凑了一些,使用全局变量保存系统名称,方便修改。
- account.rar (297 KB)
- 描述: 个人记账系统源码
- 下载次数: 1012
- microblog.rar (250.8 KB)
- 描述: 调试通过的书中例子
- 下载次数: 529
- account(查询后修改保持查询条件V0.0.6).rar (308.1 KB)
- 描述: 查询后保持查询条件,较新的版本。
- 下载次数: 418
发表评论
-
gradle编译错误:Could not find method compile() for arguments
2020-09-19 10:50 18528编译(IDEA+Gradle)一个别人的工程,出现一个 ... -
netty心跳检查之UDP篇
2019-09-15 08:50 2406部分UDP通信场景中,需要客户端定期发送心跳信息,以获取终 ... -
解决tomcat部署两个SpringBoot应用提示InstanceAlreadyExistsException
2019-06-30 11:49 3403两个SpringBoot应用部署在一个Tomcat中,单独 ... -
Eclipse配置MyBatis代码自动化功能
2019-06-29 10:16 17811.安装插件 Eclipse中,Help->Ecli ... -
vue.js中使用qrcode生成二维码
2019-05-20 00:00 7660一、安装包 npm install qrcodejs2 --s ... -
MySQL插入数据报错: Incorrect string value: '\xFD\xDE'
2019-03-31 23:19 1260我MySQL数据库用的uft-8字符集,插入数据一直很正常 ... -
vue自定义组件并双向绑定属性
2019-03-08 22:46 3261做了两个子组件,原理基本一样,一个是使用原生的select ... -
vue-router简单示例
2019-03-05 00:32 1158写个基本完整、稍有借鉴意义的示例,防止自己忘记。 &l ... -
“联通充值系统繁忙”轻松应对
2019-02-06 11:03 3976大过年的,联通充个值一直报“充值系统繁忙”。昨天晚上试了几 ... -
electron.js数据库应用---导航菜单(element-ui+mysql)
2019-02-05 21:33 2366一、环境搭建 略, ... -
electron.js数据库应用---入门(mysql+element-ui)
2019-01-27 23:19 7505我的机器:Windows10,64 ... -
SpringMVC 在controller层中注入成员变量request,是否线程安全
2018-12-17 21:17 2752@RestController public class ... -
VueJS 组件参数名命名与组件属性转化
2018-12-03 00:00 2078转自:https://www.cnblogs.com/meiy ... -
vue-resource拦截器实现token发送及检验自动化
2018-11-16 22:38 3080用了很长时间vue-resource,最近思考$http发 ... -
element-ui试用手记
2018-10-29 20:25 1751element-ui、iviewui都以vue.js为基础 ... -
iviewui中表格控件中render的使用示例
2018-07-07 16:46 9791示例了如何在表格中显示按钮,如何将代码转化为文字。 i ... -
Tomcat错误“Alias name tomcat does not identify a key entry”解决
2018-07-05 21:39 6579申请到了阿里云的证书后,下载、按照说明生成jks格式证书、 ... -
阿里云免费证书“fileauth.txt内容配置错误”解决
2018-07-05 20:43 5306最近研究微信小程序开发,上阿里云申请了个证书,使用文件验证 ... -
springboot2.0跨域配置
2018-07-04 22:11 5288springboot2.0跨域配置: 一、代码 ... -
微信小程序使用code换openid的方法(JAVA、SpringBoot)
2018-07-01 21:52 10401微信小程序序的代码中提示,使用code换取openid,但 ...
相关推荐
总的来说,《新时期的Node.js入门》是一本全面介绍Node.js基础与实践的书籍,通过李锴精心编写的实例代码,读者不仅能学习到Node.js的基本语法,还能掌握实际开发中的各种技巧,为步入Node.js的世界打下坚实基础。
《Node.js入门经典》的源代码提供了丰富的示例,涵盖上述知识点。通过分析和运行这些代码,你可以: 1. 学习如何设置项目结构和模块化代码。 2. 理解Node.js的错误处理机制。 3. 掌握Node.js中各种模块的使用方法,...
### Node.js 学习入门知识点详解 #### 一、前言 Node.js 是一种流行的开源后端 JavaScript 运行环境,它使用 Google 的 V8 JavaScript 引擎来执行服务器端的 JavaScript。本书旨在帮助读者从零开始掌握 Node.js 的...
最佳node入门例子,用到了express + ejs + mysql,程序功能是给出音乐列表,音乐可以播放,可以上传音乐。程序中没有用到其它各种包,很单纯,而且项目的readme文件中对...把本程序研究清楚,node.js就可以算是入门了。
总之,这份2013年的"Node.js入门经典源代码"是一份宝贵的资源,它不仅让我们重温了Node.js的早期形态,也为我们提供了学习和理解JavaScript服务器端编程历史的窗口。通过深入研究,我们可以更好地掌握Node.js的核心...
这个"Node.js入门经典源代码"压缩包文件显然包含了用于学习和理解Node.js基础知识和实践的源代码示例。以下是一些关于Node.js的重要知识点,结合这个资源包,你可能会学到: 1. **异步非阻塞I/O**: Node.js的核心...
**:这是每个编程语言的入门示例,Node.js也不例外。通过创建一个简单的JavaScript文件,输出"Hello, World!",你可以了解Node.js如何执行脚本。 2. **命令行工具**:学习如何创建命令行工具,例如读取用户输入、...
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它让开发者能够在服务器端使用 JavaScript 进行开发,极大地推动了全栈开发的流行。本教程旨在为初学者提供一个快速学习 Node.js 的入口,帮助你从零开始...
### Node.js 入门知识点详解 #### 一、Node.js简介 Node.js 是一种让 JavaScript 运行在服务器端的应用平台。它利用 Chrome V8 引擎的强大性能,结合事件驱动和非阻塞 I/O 模型,为 Web 开发者提供了一种全新的构建...
通过深入阅读并实践这些书籍中的示例,你将能够建立坚实的Node.js基础,从而更好地利用JavaScript进行服务器端开发,实现全栈Web开发。无论你是初学者还是经验丰富的开发者,这些资源都将为你的Node.js技能树添加...
这些内容有助于JavaScript开发者快速入门并深入理解Node.js在构建可扩展的服务器端应用中的使用。 书中被Allen Wirfs-Brock(ECMAScript语言规范的项目编辑)等人高度评价,Allen Wirfs-Brock甚至声称,对于刚开始...
《Node.js开发指南》是一本面向初学者的Node.js教程,旨在帮助开发者快速掌握这个基于Chrome V8引擎的JavaScript运行环境。Node.js以其高效的非阻塞I/O模型和事件驱动特性,成为构建网络应用的强大工具,尤其在实时...
在本资源中,我们关注的是"Node.js入门学习demo练习",这是一系列基于菜鸟教程的实践项目。Node.js是一个开放源代码、跨平台的JavaScript运行环境,它允许开发人员在服务器端执行JavaScript代码,极大地扩展了...
学习 Node.js 不仅能让你构建高性能的 Web 应用,还能帮助你理解和应用现代 JavaScript 的特性,为全栈开发打下坚实基础。这个"Node.js中文资料导航"对于中文学习者来说,无疑是一个宝贵的资源集合。