** 项目一共有 16 个页面,是一个电商网销项目,自己在网上的某网上找的一个要做的网站的设计图;
页面主要包括: 登录页 -- 注册页 -- 首页 -- 产品列表页 -- 产品详情页 -- 会员中心页 -- 我的购物车页 -- 支付页 -- 支付成功页 -- 支付失败页 -- 评价页 -- 评价详情页 -- 我的订单页 -- 订单详情页 -- 确认订单页 -- 收货地址列表页;
后端技术: node express mongo;
前端技术:vue-cli elementui axios ;
编辑器: vscode;
项目的暂时github地址:https://github.com/13476075014/node-vue/tree/master/mynodeproject/10.moon ; 纯属个人记录下这个整个项目的过程,并非教程。 **
一:配置基本的接口controller地址
** 后台项目前面有说过是用的express生成器直接生成的一个后台项目 **
1.1 进入主入口文件 app.js ,对请求头做一些处理,来跨域保存session ,在该文件加入下面的代码(红色是需要新加的代码,黑色为位置参照物):
var app = express(); //在这个下面,加上下面的代码
//session
var session = require('express-session');
app.use(cookieParser());
app.use(session({
secret: 'classweb531234', //设置 session 签名
name: 'classweb',
cookie: {
maxAge: 60 * 1000 * 60 * 24
}, // 储存的时间 24小时
resave: false, // 每次请求都重新设置session
saveUninitialized: true
}));
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:8081"); //为了跨域保持session,所以指定地址,;第二个参数是自己前台的express项目的网址头;
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Credentials', true); //是否允许发送cookie
next();
});
1.2 对路由的设置,还是修改app.js文件,在该文件加上下面的代码:
var router = require('./routes/routes'); var app = express(); app.use(express.static(path.join(__dirname, 'public'))); router(app);//路由的使用,所有的路由都写在这个router中
1.3 进入 router文件夹 新建router.js 文件,在这个文件里面写所有的路由地址指向,代码如下:
// 主要的路由文件 module.exports = function(app) { app.use('/', require('./index')) app.use('/users', require('./users')) //用户表路由 }
1.4 安装上面session需要的npm包 ,控制台输入 npm i express-session --save-dev
最后整个app.js文件如下:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var router = require('./routes/routes'); var app = express(); //跨域 后期删 app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "http://localhost:8081"); //为了跨域保持session,所以指定地址,不能用* res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS'); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header('Access-Control-Allow-Headers', 'Content-Type'); res.header('Access-Control-Allow-Credentials', true); //是否允许发送cookie next(); }); //session var session = require('express-session'); app.use(cookieParser()); app.use(session({ secret: 'classweb531234', //设置 session 签名 name: 'classweb', cookie: { maxAge: 60 * 1000 * 60 * 24 }, // 储存的时间 24小时 resave: false, // 每次请求都重新设置session saveUninitialized: true })); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // uncomment after placing your favicon in /public //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); router(app);//路由的使用 // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
二:用对mongodb封装好的增删改查,方便后面对数据库的操作,进入 routes文件夹,新建 dbhandler.js文件,具体代码如下:
/*网上别人写好的针对[email protected]版本的增删改查的封装,后面有改成mongoose,后面会提到 */ var mongo = require("mongodb"); var MongoClient = mongo.MongoClient; var assert = require('assert'); var url = require('url'); var host = "localhost"; var port = "27017"; var Urls = 'mongodb://localhost:27017/moon'; // moon ===> 是自己要连接的这个项目的数据库名 //add一条数据 var add = function(db, collections, selector, fn) { var collection = db.collection(collections); collection.insertMany([selector], function(err, result) { try { assert.equal(err, null) } catch (e) { console.log(e); result = []; }; fn(result); db.close(); }); } //delete var deletes = function(db, collections, selector, fn) { var collection = db.collection(collections); collection.deleteOne(selector, function(err, result) { try { assert.equal(err, null); assert.notStrictEqual(0, result.result.n); } catch (e) { console.log(e); result.result = ""; }; fn(result.result ? [result.result] : []); //如果没报错且返回数据不是0,那么表示操作成功。 db.close; }); }; //find var find = function(db, collections, selector, fn) { //collections="hashtable"; var collection = db.collection(collections); collection.find(selector).toArray(function(err, result) { //console.log(docs); try { assert.equal(err, null); } catch (e) { console.log(e); result = []; } fn(result); db.close(); }); } //page var page = function(db, collections, selector, fn) { var collection = db.collection(collections); var count = 0; collection.count({}, function(err1, count1) { try { assert.equal(err1, null); } catch (e) { console.log(e); } count = count1; }); collection.find(selector[0], selector[1]).toArray(function(err, result) { try { assert.equal(err, null); } catch (e) { console.log(e); result = []; } fn(result, count); //回掉函数可接收两个参数,查询的数据 和 总数据条数 db.close(); }); } //update var updates = function(db, collections, selector, fn) { var collection = db.collection(collections); collection.updateOne(selector[0], selector[1], function(err, result) { try { assert.equal(err, null); assert.notStrictEqual(0, result.result.n); } catch (e) { console.log("update错啦:" + e); result.result = ""; }; fn(result.result ? [result.result] : []); //如果没报错且返回数据不是0,那么表示操作成功。 db.close(); }); } /*var methodType = { // 项目所需 login:find, // type ---> 不放在服务器上面 // 放入到服务器 // 请求---> 根据传入进来的请求 数据库操作 // req.query req.body show:find, //后台部分 add:add, find:find, courseList:updates, update:updates, delete:deletes, updatePwd:updates, //portal部分 showCourse:find, register:add, page:page //分页 };*/ //主逻辑 服务器 , 请求 --》 // req.route.path ==》 防止前端的请求 直接操作你的数据库 /*module.exports = function(req,res,collections,selector,fn){ MongoClient.connect(Urls, function(err, db) { assert.equal(null, err); console.log("Connected correctly to server"); // 根据 请求的地址来确定是什么操作 (为了安全,避免前端直接通过请求url操作数据库) methodType[req.route.path.substr(1)](db,collections,selector,fn); db.close(); }); };*/ /*自己修改的向外暴露的增删改的接口*/ var methodType = { login: find, show: find, //后台部分 add: add, find: find, courseList: updates, update: updates, delete: deletes, updatePwd: updates, //portal部分 showCourse: find, register: add, page: page //分页 }; module.exports = function(req, res, i, collections, selector, fn) { //i是要执行的操作,例如find,delete和上面的methodType对应 //collections 要操作的表名 //selector要传的参数 //fn回调函数 MongoClient.connect(Urls, function(err, db) { assert.equal(null, err); console.log("Connected correctly to server"); // 根据 请求的地址来确定是什么操作 (为了安全,避免前端直接通过请求url操作数据库) methodType[i](db, collections, selector, fn); db.close(); }); };
三:新增user用户表的操作,还是进入routes文件夹,把自动生成的users.js换成下面的代码:
var express = require('express'); var router = express.Router(); var crypto = require('crypto'); var ObjectId = require('mongodb').ObjectId; var handler = require('./dbhandler.js'); //极客验证 var slide = require('../public/javascripts/slide.js'); router.get("/gt/register-slide", function(req, res) { // 向极验申请每次验证所需的challenge slide.register(null, function(err, data) { if (err) { console.error(err); res.status(500); res.send(err); return; } if (!data.success) { req.session.fallback = true; res.send(data); // 2. 使用自己提供的备用方案 // todo } else { // 正常模式 req.session.fallback = false; res.send(data); } }); }); /* GET users listing. */ router.post('/login', function(req, res, next) { var username = req.body.username; var password = req.body.password; slide.validate(req.session.fallback, { geetest_challenge: req.body.geetest_challenge, geetest_validate: req.body.geetest_validate, geetest_seccode: req.body.geetest_seccode }, function(err, success) { if (err) { // 网络错误 res.send({ status: "error", info: err }); } else if (!success) { // 二次验证失败 res.send({ status: "fail", info: '登录失败' }); } else { //验证成功后就对账号密码进行验证 /*res.send({ status: "success", info: '登录成功' });*/ var md5 = crypto.createHash('md5'); var password = md5.update(req.body.password).digest('base64'); handler(req, res, "login", "user", { username: req.body.username }, function(data) { if (data.length === 0) { //没有这个账号 res.send({ status: "error", info: "账号或密码错误" }); } else if (data[0].pass !== password) { res.send({ status: "error", info: "账号或密码错误" }); } else if (data.length !== 0 && data[0].pass === password) { req.session.username = username; //存session req.session.password = password; //存密码 req.session._id = data[0]._id; res.send({ status: "success", info: "成功" }); } }); } }); }); /* 注册接口 */ router.post('/register', function(req, res, next) { var user = req.body.user; delete(user["pass2"]); var md5 = crypto.createHash('md5'); req.body.user.pass = md5.update(req.body.user.pass).digest('base64'); //对密码加密 //查询是否这个账号已经存在,需要更换账号去注册 handler(req, res, "find", "user", { 'username': user.username }, function(data) { if (data.length == 0) { //没有找到有相同用户民的; handler(req, res, "add", "user", user, function(data) { if (data.length == 0) { res.end('{"err":"抱歉,添加失败"}'); } else { res.end('{"success":"添加成功"}'); } }); } else { //账号已经存在了 res.end('{"err":"抱歉,添加失败,这个账号已经存在了!"}'); } }) }) /*分页的接口 */ router.post('/getpage', function(req, res, next) { console.log(req.body) var page = req.body.page || 1; //当前页数 var rows = req.body.rows || 5; //一页显示的条数 handler(req, res, "page", "user", [{}, { limit: rows, skip: (page - 1) * rows }], function(data, count) { var obj = { data: data, total: count, success: "成功" }; var str = JSON.stringify(obj); res.send(str); }); }) module.exports = router;