现在基本上整个增删改查都有了,但是我们发现所有路由和接口api全部写在app.js里面,现在我们把路由拆分出来,单独建立文件夹,用来存储路由和视图ejs,方便后期的维护
大概目录如下
路由架构/js
登录路由 --- router-login
商品路由 --- router-product
其他路由 --- router-other
商品页面/ejs
公共页面 --- views-public-header.ejs
登录页面 --- views-login-login.ejs
商品页面 ---- views-product
---商品列表---list.ejs
---商品新增---add.ejs
---商品编辑---edit.ejs
其他页面 --- views-other-other.ejs
1:先来拆分路由吧
新建一个router文件夹,分别建立login、product文件夹
login中新建login.js实现路由,代码如下
let express = require('express');
let router = express.Router(); //路由拆分使用
const app = express();
//这里就不是app.get啦全部用router来接管啦
router.get("/",(req,res)=>{
res.render("login/login");
});
router.get("/login",(req,res)=>{
res.render("login/login");
});
//导出去暴露使用
module.exports = router;
2:在app.js中引入使用
//路由封装
var login=require('./router/login/login.js');
//express的自定义路由Router
//login全部去寻找login这个模块里面 再具体定义就好了
//login/
//login/user
//login/pic
app.use('/login',login); //去寻找login.js这个里面匹配
效果如下
ps:类似于在路由前面加了一个前缀/login
对,就是这样理解就对啦,现在我们把登录所有的功能移过来
let express = require('express');
let router = express.Router();
const app = express();
var md5=require("md5-node");
//解析post提交的数据
const bodyParser = require('body-parser')
router.use(bodyParser.urlencoded({ extended: false }))
router.use(bodyParser.json())
const ejs = require('ejs');
const session = require("express-session");
//设置cookie参数
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 30*60*1000 },
rolling:true
}))
//数据库操作
var DB =require('../../module/db.js');
//静态文件服务 容易出错2 是express
app.use(express.static('public'))
//映射upload为虚拟目录,去upload里面寻找图片
app.use('/upload',express.static('upload'))
router.get("/",(req,res)=>{
res.render("login/login");
});
router.get("/login",(req,res)=>{
res.render("login/login");
});
//表单提交的后台接口
router.all('/doLogin',(req,res)=>{
let username = req.body.username;
let password = md5(req.body.pwd);
console.log(`${username}---${password}`);
//var body= { 'username': 'admin', 'pwd': '123456' };
console.log(req.body);//{ username: 'admin', pwd: '123456' }
//数据库操作
DB.find("user",{
username:username,
pwd:password
},function(err,data){
if(data.length>0){
//console.log("登录成功");
req.session.userinfo= data[0];
//ejs 全局设置数据,其他页面可以共用
//app.locals.userinfo=data[0]; 分开后无法这样使用
var userinfo =req.session.userinfo;
console.log('userinfo=====>'+userinfo);
res.redirect("/product/list");
}else{
console.log("登录失败");
res.send("")
}
});
});
//退出
router.all("/loginOut",(req,res)=>{
req.session.destroy((err)=>{
if(err){
console.log(err);
}else{
res.redirect('/login/');
}
})
});
module.exports = router;
ps:这里我遇到了几个小问题,需要注意点
1:所有的app.use和app.post都得改成router.use和router.all,方便接管路由
2:所有的路径问题,静态资源库css、图片路径、接口路径都得修改
3:session问题,我在这里卡了很久终于解决了
开始一直报错,找不到userinfo,尝试用redirect传递,发现无法使用没有这个api,然后想着用render这里直接渲染list页面,但是发现又得查询一遍数据库,比较麻烦,后来又想用本地存储存储storage来实现,发现有点麻烦,主要是不想在ejs里面写js代码,后面一步步调试,决定用req来传递,发现登录页面成功后,list页面虽然是include引入了header这个模块,也是可以获取到req里面的对象,所以最后决定直接获取,本来想用 //app.locals.userinfo=data[0]; 分开后无法这样使用,这个自带的locals对象的,发现编译一直报错,找不到,就算用router接管传递也不行,最后放弃,主要是没时间折腾了
最后效果图
登录模块弄完了,接下来弄商品模块
根据功能,分别拆分接口,新建文件夹存储单独的模块视图ejs,这里用一个product.js来存储所有商品的相关api接口和路由,代码如下
let express = require('express');
const app = express();
let router = express.Router();
//图片上传
var multiparty = require('multiparty');
var http = require('http');
//var util = require('util');
//数据库操作
var DB =require('../../module/db.js');
//静态文件服务 容易出错2 是express
router.use(express.static('public'))
//映射upload为虚拟目录,去upload里面寻找图片
router.use('/upload',express.static('upload'))
router.get("/",(req,res)=>{
res.send("product index")
});
//商品列表
router.all("/list",(req,res)=>{
DB.find('shop',{},function(err,data){
//if(data.length>0){
res.render("product/list",{shopList:data,userinfo:req.session.userinfo});
//}else{
// res.render("productList");
//}
});
});
//商品增加
router.all("/add",(req,res)=>{
res.render("product/add")
});
router.all("/edit",(req,res)=>{
res.render("product/edit")
});
router.all("/del",(req,res)=>{
res.send("product/delete")
});
//商品新增接口
router.all("/shopAdd",(req,res)=>{
var form = new multiparty.Form();
//配置文件上传目录,后续需要映射虚拟目录才可以显示
form.uploadDir = "upload";//新建一个upload目录,专门存储上传图片
form.parse(req, function(err, fields, files) {
//console.log(fields);
//console.log(files);
let shopname= fields.shopname[0];
//图片路径 注意是files
let shoppic = files.shoppic[0].path;
let shopprice = fields.shopprice[0];
let shopfee = fields.shopfee[0];
let shopDesc = fields.shopDesc[0];
//console.log(shopname);
//console.log(shoppic);
//console.log(shopprice);
//console.log(shopfee);
//console.log(shopDesc);
//插入数据库
DB.insert('shop',{
title:shopname,
pic:shoppic,
price:shopprice,
fee:shopfee
},(err,data)=>{
//if(!err){
res.redirect("/product/list")
//}
})
})
});
//商品修改初始化页面
router.all("/shopEdit",(req,res)=>{
//获取id
let id =req.query.id;
console.log(id);
//查询数据
DB.find('shop',{_id:new DB.objectId(id)},(err,data)=>{
//console.log(data[0]);
//console.log(data);
//渲染修改视图页面
res.render('product/edit',{shopList:data[0]})
})
});
//商品修改接口提交修改
router.all("/doshopEdit",(req,res)=>{
var form = new multiparty.Form();
//配置文件上传目录,后续需要映射虚拟目录才可以显示
form.uploadDir = "upload";//新建一个upload目录,专门存储上传图片
form.parse(req, function(err, fields, files) {
//console.log(fields);
//先拿到修改的ID,更新使用
let _id = fields._id[0];
console.log(_id);
let shopname= fields.shopname[0];
//图片路径 注意是files
let shoppic = files.shoppic[0].path;
let shopprice = fields.shopprice[0];
let shopfee = fields.shopfee[0];
let shopDesc = fields.shopDesc[0];
console.log(files);
//console.log(shoppic);
//console.log(shopprice);
//console.log(shopfee);
//console.log(shopDesc);
//单独处理图片
let orginFileName =files.shoppic[0].originalFilename;
if(orginFileName){//有修改图片
var setData={
title:shopname,
pic:shoppic,
price:shopprice,
fee:shopfee
}
}else{ //没有修改图片就不添加
var setData={
title:shopname,
price:shopprice,
fee:shopfee
}
}
//删除临时文件
//fs.unlink(shoppic,(err)=>{console.log(err)});
//根据id修改更新数据库
DB.update('shop',{"_id":new DB.objectId(_id)},setData
,function(err,data){
if(!err){
res.redirect('/product/list');
}
}
);
})
});
//删除文件
router.all("/shopDel",(req,res)=>{
let _id= req.query.id;
console.log("_id==="+_id);
//根据id修改更新数据库
DB.deleteOne('shop',{"_id":new DB.objectId(_id)}
,function(err){
if(!err){
res.redirect('/product/list');
console.log("删除成功");
}
}
);
});
module.exports = router;
ps:这个还算顺利,没遇到什么麻烦,基本只要修改接口地址和路径,不会有太大的问题,不过这渲染list页面的时候,需要把登录的userinfo传递过来,否则获取不到登录名哦
最后按步骤提取add.edit.remove等ejs放到对应目录
最后再来看看app.js,修改完之后,很清爽吧
const express =require('express');
const app = express();
const ejs = require('ejs');
var fs = require("fs");
const session = require("express-session");
//设置cookie参数
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 30*60*1000 },
rolling:true
}))
//注意这里是字符串 容易出错1
app.set("view engine",'ejs')
//路由封装
var login=require('./router/login/login.js');
var admin = require('./router/admin.js');
var product = require('./router/product/product.js');
//静态文件服务 容易出错2 是express
app.use(express.static('public'))
//映射upload为虚拟目录,去upload里面寻找图片
app.use('/upload',express.static('upload'))
//必须放在上面 否则不生效
app.use((req,res,next)=>{
console.log(req.url);
let visUrl = req.url;
//通过session来做 然后login页个访问接口不需要判断
if(visUrl == "/login/login" || visUrl == "/login/" || visUrl == "/login/doLogin"){
console.log("visUrl======"+visUrl);
next(); //不需要校验
}else{
console.log("userinfo="+req.session.userinfo);
if(req.session.userinfo && req.session.userinfo.username !=''){
next();
}else{
res.redirect('/login/login');
}
}
});
//有session 可以直接访问主页 productList 没有就不能访问
//登录前的中间件判断 没有登录就不能进入主页 productList
//express的自定义路由
//admin 全部去寻找admin这个模块里面 再具体定义就好了
//admin/user
//admin/pic
app.use('/login',login);
app.use('/admin',admin)
app.use('/product',product)
app.listen("3333",()=>console.log("server start"));
这里需要做的就是中间件登录前的判断,没有登录过的用户,无法直接进入商品列表list页面哦
同样这里也要再次定义一下静态文件托管中间件static,删除会报错哦
最后大功告成,加油···