包含功能
登錄注冊(不開放注冊只是用固定的賬號信息)
查看列表
查看詳情
發布信息
編輯信息
刪除信息
項目接口
npm init -y
npm install koa --save
npm istall koa-router --save (舊版本) 或者 npm install @koa/router --save (新版本)
npm install bluebird --save
npm install koa-ejs --save
npm install koa-bodyparser --save
執行完畢之后 ,使用vscode 打開項目文件夾,繼續往里面添加對應的文件目錄和文件
authenticate.js
//認證中間件
module.exports = async function (ctx,next) {const logined = ctx.cookies.get('logined',{signed: true});ctx.state.logined = !!logined;await next();
}
路由開發
routes/post.js
const Router = require('koa-router');
const postService = require('../services/post');
const router = new Router();//發布表單頁面
router.get('/publish', async (ctx) => {await ctx.render('publish');
});//發布處理
router.post('/publish', async (ctx) => {const data = ctx.body;if (!data.title || !data.content) {ctx.throw(500, '缺失必填參數');}const item = postService.publish(data.title, data.content);ctx.redirect(`/post/${item.id}`);
});//詳情頁面
router.get('/post/:postId', async (ctx) => {const post = postService.show(ctx.params.postId);if (!post) {ctx.throw(404, '消息記錄不存在');}await ctx.render('post', { post: post });
});//編輯表單頁面
router.get('/update/:postId',async (ctx)=>{const post = postService.show(ctx.params.postId); if (!post) {ctx.throw(404, '消息記錄不存在');}await ctx.render('post', { post: post });
});//編輯處理
router.post('/update/:postId',async (ctx)=>{const data = ctx.body;if (!data.title || !data.content) {ctx.throw(500, '缺失必填參數');}const postId = ctx.params.postId;postService.update(postId,data.title,data.content);ctx.redirect(`/post/${postId}`);
});//刪除
router.get('delete/:postId',async (ctx)=>{postService.delete(ctx.params.postId);ctx.redirect('/');
});module.exports = router;
routes/site.js
const Router = require('koa-router');
const postService = require('../services/post');
const router = new Router();//網站首頁
router.get('/', async (ctx)={const list = postService.list();await ctx.render('index',{list : list});
});module.exports = router;
routes/user.js
const Router = require('koa-router');
const userService = require('../services/user');
const router = new Router();//登陸頁面
router.get('/login', async(ctx) = {await ctx.render('login');
});//登錄處理
router.post('/login', async(ctx) = {const data = ctx.request.body;if(!data.userName || !data.password){ctx.throw(500, '用戶名或密碼缺失必填參數');
}
const logined = userService.login(data.userName, data.password);
if (!logined) {ctx.throw(500, '用戶名或密碼錯誤');
}
ctx.cookies.set('logined', 1, {signed: true,httpOnly: true
});
ctx.router('/', '登陸成功');
});//退出登錄
router.get('/logout', (ctx) => {ctx.cookies.set('logined', 0, {signed: true,maxAge: -1});ctx.router('/', '退出登陸成功');
});```**服務層開發
services/post.js**
```
const fs = require('fs');
const bluebird = require('bluebird');//Promise 化 fs 的api
bluebird.promisifyAll(fs);//文章數據
const posts = [];
//文章ID
let postId = 1;//發表文章
exports.publish = function(title,content){const item = {id: postId++,title: title,content: content,time: (new Date()).toLocaleDateString()};posts.push(item);return item;
}//查看文章
exports.show = function(id){id = Number(id);for(const post of posts){if(post.id === id){return post;}}return null;
}//編輯文章
exports.update =function(id,title,content){id = Number(id);posts.forEach((post)=>{if(post.id === id){post.title = title;post.content = content;}});
}//刪除文章
exports.delete = function (id){id = Number(id);let index = -1;posts.forEach((post)=>{if(post.id === id){index = id;}});if(index > -1){posts.slice(index,1)}
}exports.list = function(){return posts.map(item => item);
}```**serivce/user.js**```
const user = {liuyifei: 'password'
};//登錄
exports.login = function(userName,password){if(user[userName] === undefined){return false;}return user[userName] === password;
};
```=======================================================
**前端模板:**
**index.ejs**
```
<h1>文章顯示列表</h1>
<% if(list.length === 0){ %>
<p>文章顯示列表</p>
<% }else{ %>
<table><tr><th>id</th><th>標題</th><th>發布時間</th><% if(logined){ %><th>操作</th><% } %> </tr><% list.forEach(post => { %><td><%= post.id %></td> <td><a href="/post/<%= post.id %>"><%= post.title %></a></td> <td><%= post.time %></td> <% if(logined){ %><th><a href="/update/<%= post.id %>">編輯</a></th><th><a href="/delete/<%= post.id %>" onclick="return confirm('確認刪除?')">刪除</a></th><% } %><% }) %>
</table>
<% } %>
```**login.ejs**
```
<form action="/login" method="post" enctype="application/x-www-form-urlencoded"><fieldset><legend>登錄</legend><div><label for="userName">賬號</label><input type="text" name="userName" id="userName" required /></div><div><label for="userName">密碼</label><input type="password" name="password" id="password" required /></div> <div><button type="submit">登錄</button></div> </fieldset>
</form>
```
**main.ejs**
```
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>首頁</title>
</head><body><% if(logined) { %><a href="/">首頁</a><a href="/publish">發表文章</a><a href="/logout">退出登錄</a><% }else{%><a href="/login">退出登錄</a><% } %><%- body %></body>
</html>
```
**post.ejs**
```
<div><h1><%= post.title %></h1> <time>發布時間:<%= post.time %></time>
<hr><div><%= post.content %></div>
</div>
```
**publish.ejs**```
<form action="/publish" method="post" enctype="application/x-www-form-urlencoded"><fieldset><legend>發表文章</legend><div><label for="title">標題</label><input type="text" name="title" id="title" required></div><div><label for="content">內容</label><textarea name="content" id="content" required></textarea></div><div><button type="submit">發布</button><button type="reset">重置</button></div></fieldset>
</form>
```****update.ejs****
```
<form action="/update/<%=post.id %>" method="post" enctype="application/x-www-form-urlencoded"><fieldset><legend>編輯文章</legend><div><label for="title">標題</label><input type="text" name="title" id="title" value="<%= post.title %>" required></div><div><label for="content">內容</label><textarea name="content" id="content" required ><%= post.content %></textarea></div><div><button type="submit">發布</button><button type="reset">重置</button></div></fieldset></fieldset>
</form>
```
**index.js : 項目的入口文件,負責掛載中間件,路由,應用配置以及啟動服務器**```
const Koa = require('koa');
const render = reuire('koa-ejs');
const bodyParser = require('koa-bodyParser');
//認證組件
const authenticate = require('./middlewares/authenticate');//路由
const siteRoute = require('./routes/site');
const userRoute = require('./routes/user');
const postRoute = require('./routes/post');const app = new Koa(); //定義服務
app.keys = ['wusoddn09Wa']; //定義認證使用的key//掛載中間件
app.use(bodyParser());//關聯使用模版
render(app,{root: './templates',layout: 'main',viewExt: 'ejs'}
);//掛載路由
app.use(siteRoute.routes()).use(siteRoute.allowedMethods());
app.use(userRoute.routes()).use(userRoute.allowedMethods());
app.use(postRoute.routes()).use(postRoute.allowedMethods());app.listen(8080,()=>{console.log(server start up on port: 8080);
});```