项目说明
该项目的功能
- 登录、注册
- 查看详情页
- 写留言
- 发布留言
- 修改、删除留言
- 上传文件
项目用到的技术
- express框架
- art-template模板引擎
- uikit框架
- ajax数据交互
- mongodb数据库
- 用session保持用户登录
项目使用express框架
项目使用nodemon启动项目
- 保证项目可以实时更新
- 更改
package.json
配置,将start: npm
改为start: nodemon
- 使用
npm start
启动项目
链接mongodb数据库
- 使用
mongo
在项目中链接数据库
-
use project
创建数据库名为project
- 创建集合(users:管理所有用户信息)
db.createCollection("users") //{ "ok" : 1 }
//查看集合
show collections //users
//向集合中插入一条信息
db.users.insertOne({name:"lala"})
/* {
"acknowledged" : true,
"insertedId" : ObjectId("5fc921cc6a3f8f70f6d0157d")
}*/
//查看插入信息
db.users.find()
//{ "_id" : ObjectId("5fc921cc6a3f8f70f6d0157d"), "name" : "lala" } 插入成功!
- 使用erpress框架链接数据库,使用mongodb模块链接数据库
npm install mogodb --save
- 创建model文件夹分装数据库数据
数据库连接方法分装:
function connect(callback){
MongoClient.connect(url, function(err,client) {
if(err){
console.log("数据库连接错误", err);
}else{
var db = client.db(dbName);
callback && callback(db);
client.close(); //关闭数据库
}
})
}
前端页面
- 前端页面放在views文件下
- 在express中使用ejs模板引擎
- 使用uikit框架
session
- 使用session来保存用户的登录状态
npm install express-session
- 在app.js中引入并配置
var session = require('express-session');
//session的配置
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { maxAge:1000 * 60 * 5 } //指定登录会话的有效时长为5分钟
}))
//登录拦截
app.get('*', function(req, res, next){
var username = req.session.username;
var path = req.path;
console.log(username);
if(path != '/login' && path != '/regiist'){
if(!username){
res.redirect('/login');
}
}
next();
})
//退出登录
router.get('/logout' ,function(req, res ,next){
req.session.username = null;
res.redirect('/login')
})
写留言
- 使用xheditor写复文本框 (现在不能使用了)
- 创建article路由文件
- 增加文件上传功能,使用uikit组件
- 定义服务端接口(文件上传为post方法)
-
npm install multiparty -s
使用第三方库multiparty(呜呜呜,失败)
//1、先引入
var multiparty = require('multiparty');
首页
app.get('/img', function (req, res, next) {
res.sendFile(path.join(__dirname, 'public/2.png'));
})
- 修改时间格式
npm install moment -S
- 增加分页功能
router.get('/', function(req, res, next) {
var username = req.session.username || "";
var page = req.query.page || 1;
var data = {
total: 0, //总共多少页
curPage: page, //当前页
list :[] //当前页的文章列表
}
var pageSize = 6; //每页展示6篇留言
model.connect(function(db){
// 1、查询所有文章
db.collection('articles').find().toArray(function(err, docs){
data.total = Math.ceil(docs.length / pageSize);
// 2、查询当前页的文章列表
model.connect(function(db) {
// sort({_id:-1})倒序查询,最新数据最先显示
//limit(pageSize)每次查询页数
//skip((page -1) * pageSize) 游标向前移动多少格查询;每次点击页数跳过前一次页数内的留言
db.collection('articles').find().sort({_id:-1}).limit(pageSize).skip((page -
1) * pageSize).toArray(function(err, docs2){
//删除留言效果
if(docs2.length == 0 ){
res.redirect('/?page ='+((page -1) || 1)) //页面最少也为第一页
}else{
docs2.map((ele, index) => {
ele['time'] = moment(ele.id).format('YYYY-MM-DD HH:mm:ss')
})
data.list = docs2
}
res.render('index', { username:username ,data:data});
})
})
})
})
});
- 如何让button变成<a href='链接'></a>效果
<button class="uk-button uk-button-primary " style="background-color: #7952b3d6"
onclick="window.location.href='/article/delete?id=<%= item.id%>&page=<%=data.curPage%>' ">
删除</button>
- 数据库的删除
// 删除留言
router.get('/delete', function(req, res, next){
var id = parseInt(req.query.id);
var page = req.query.page;
model.connect(function(db){
db.collection('articles').deleteOne({id: id},function(err,ret){
if(err){
console.log("删除失败");
}else{
console.log("删除成功");
}
res.redirect('/?page=' + page)
})
})
})
- 修改页面可以和写留言页面复用,但是修改页面内要显示原始数据
- 修改留言和写留言的button不相同
<% if(item.id){ %>
<button class="uk-button uk-button-primary " style="background-color: #7952b3d6">修改</button>
<% }else{ %>
<button class="uk-button uk-button-primary" style="background-color: #7952b3d6">发布</button>
<% }%>
- 通过隐藏域将修改留言内的id和page传给服务端,以区分是修改页面还是新增页面
<input type="hidden" value="<%= item.title %>" name="id"/>
<input type="hidden" value="<%= item.page %>" name="page"/>
// 渲染写留言页面 /编辑留言页
router.get("/write", function(req ,res ,next){
var username = req.session.username || '';
var id = parseInt(req.query.id);
var page = req.query.page;
var item = {
title:'',
content:'',
}
if(id){ //编辑
model.connect(function(db){
db.collection('articles').findOne({id:id}, function(err,docs){
if(err){
console.log('查询失败');
}else{
item = docs;
console.log(docs);
item['page'] = page;
res.render('write',{username:username, item:item})
}
})
})
}else{ //新增
res.render('write',{username:username, item:item})
}
})
//新增、编辑
router.post('/add', function(req, res ,next){
var id = parseInt(req.body.id);
if(id){ //编辑
var page = req.body.page;
var title = req.body.title;
var content = req.body.content;
model.connect(function(db){
db.collection('articles').updateOne({id:id},{ $set: {
title:title,
content:content
}}, function(err, ret){
if(err) {
console.log("修改失败",err);
}else{
console.log("修改成功");
// console.log(title,content);
res.redirect('/?page='+page);
}
})
})
}else{ //新增
var data = {
title:req.body.title,
content:req.body.content,
id:Date.now(),
username:req.session.username
}
model.connect(function(db){
db.collection('articles').insertOne(data, function(err, ret){
if(err){
console.log("文章发布失败、")
res.redirect('/write')
}else{
res.redirect("/")
}
})
})
}
})