node+koa2+mysql搭建博客后台
生活随笔
收集整理的這篇文章主要介紹了
node+koa2+mysql搭建博客后台
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文將詳細(xì)講解使用node+koa2+mysql搭建博客后臺的全過程。
開發(fā)環(huán)境
- node 8.3.0及以上
- npm 5.3.0及以上
- mysql 5.7.21
具體的環(huán)境配置可查看我的上一篇文章
準(zhǔn)備工作
- npm下載pm2(進(jìn)程守護(hù)),并設(shè)置全局變量
- 創(chuàng)建博客需要的數(shù)據(jù)庫與表
- 開啟mysql并創(chuàng)建數(shù)據(jù)庫test: create database test;
- 切換到數(shù)據(jù)庫testuse tests;,輸入命令創(chuàng)建以下數(shù)據(jù)表:
node后臺目錄創(chuàng)建及npm包安裝
- 創(chuàng)建項(xiàng)目文件夾server,進(jìn)入文件夾后初始化項(xiàng)目npm init。
- 在項(xiàng)目下創(chuàng)建以下文件夾和文件
- 安裝以下依賴包:
- koa node框架
- koa-bodyparser 表單解析中間件
- koa-router 路由框架
- koa-session 基于koa的session模塊
- mysql 數(shù)據(jù)庫
- md5 md5加密
- async-busboy 帶文件的表單解析模塊
- is 數(shù)據(jù)格式校驗(yàn)插件
node連接mysql
db/index.js配置文件如下:
var mysql = require('mysql'); let config = {host : 'localhost',user : 'root',password : '123456',database : 'test',port:3306,multipleStatements: true//允許多條sql同時(shí)執(zhí)行 }; let pool = mysql.createPool(config); let query = (sql, values) => {return new Promise((resolve, reject) => {pool.getConnection((err, connection) => {if (err) {reject(err)} else {connection.query(sql, values, (err, rows) => {if (err) {reject(err)} else {resolve(rows)}connection.end()})}})}) }; module.exports = {query } 復(fù)制代碼其他配置
- 框架公用方法,包括參數(shù)校驗(yàn)、登錄態(tài)校驗(yàn)等。config/index.js
- 框架接口返回碼規(guī)范 config/tip.js
路由 Rouer
以上配置完成后,便可以開始寫設(shè)計(jì)路由了。
引入相關(guān)配置
const router = require('koa-router')(); const Utils = require('../utils'); const Tips = require('../utils/tip'); const db = require('../db'); 復(fù)制代碼根據(jù)表設(shè)計(jì)路由
- user表 -> user.js 管理員管理,可登錄、查詢登錄態(tài)、退出登錄
- note表 -> note.js 筆記本管理,可添加、修改、刪除,查詢筆記本列表
- blog表 -> blog.js 博客管理 可添加、修改、刪除、查詢博客列表。每篇博客必須關(guān)聯(lián)對應(yīng)的筆記本。可根據(jù)筆記本查詢博客列表
- img表 -> img.js 圖片管理,可上傳、刪除、查詢圖片列表
具體路由部分實(shí)現(xiàn)內(nèi)容
注意:所有的刪除操作均為將表字段is_delete設(shè)置為1即可,方便恢復(fù)數(shù)據(jù)
-
user.js 管理員
- 登錄 router.post('/oa/login', async (ctx, next) => {let data = Utils.filter(ctx.request.body, ['name', 'password']);let res = Utils.formatData(data,[{key:'name',type:'string'},{key:'password',type:'string'}]);if(!res) return ctx.body = Tips[1007];let { name, password } = data;let sql = 'SELECT uid FROM t_user WHERE name=? and password=? and is_delete=0', value = [name, md5(password)];await db.query(sql, value).then(res => {if (res && res.length > 0) {let val = res[0];let uid = val['uid']ctx.session.uid = uid;ctx.cookies.set('uid', uid, {maxAge:86400000,httpOnly: true});ctx.body = {...Tips[0],data:{uid}};} else {ctx.body = Tips[1006];}}).catch(e => {ctx.body = Tips[1002];})});復(fù)制代碼
- 查詢登錄信息 router.get('/oa/user/auth', async (ctx, next) => {let uid = ctx.session.uid;let sql = 'SELECT name,uid,nick_name FROM t_user WHERE uid=? AND is_delete=0', value = [uid];await db.query(sql, value).then(res => {if (res && res.length > 0) {ctx.body = { ...Tips[0], data: res[0] };} else {ctx.body = Tips[1005];}}).catch(e => {ctx.body = Tips[1005];}) }); 復(fù)制代碼
-
note.js 筆記本管理
- 創(chuàng)建筆記本 router.post('/oa/user/addNote',async (ctx,next)=>{let data = Utils.filter(ctx.request.body, ['name']);let {name} = data, uid = ctx.session.uid;let res = Utils.formatData(data, [{key: 'name', type: 'string'}]);if (! res) return ctx.body = Tips[1007];let create_time = Utils.formatCurrentTime();let sql = `INSERT INTO t_note(name,uid,create_time) VALUES(?,?,?)`,value = [name, uid, create_time];await db.query(sql, value).then(res => {let {insertId: id} = res;if (id) {ctx.body = {...Tips[0],data: {id}}} else {ctx.body = Tips[1002]}}).catch(e => {if(+e.errno === 1062){//筆記本不能重復(fù)ctx.body = {code: 1010,msg: '筆記本已存在!'};}else{ctx.body = Tips[1002]}}) }); 復(fù)制代碼
- (分頁)查詢筆記本列表 router.get('/oa/user/myNote', async (ctx, next) => {let data = Utils.filter(ctx.request.query, ['pageSize', 'pageNum', 'type']), uid = ctx.session.uid;let res = Utils.formatData(data, [{key: 'type', type: 'number'},]);if (! res) return ctx.body = Tips[1007];let {pageSize = 15, pageNum = 1, type = 0} = data;pageSize = Number(pageSize);pageNum = Number(pageNum);let offset = (pageNum - 1) * pageSize;let sql1 = `SELECT count(1) FROM t_note WHERE uid=${uid} AND is_delete=0;`,sql= `SELECT name,id,create_time,update_time FROM t_note WHERE uid=${uid} AND is_delete=0 ORDER BY create_time DESC`;if(+type === 1){sql += ` limit ${offset},${pageSize};`}await db.query(sql1+sql).then(async result => {let res1 = result[0],res2 = result[1],total = 0,list = []if(res1 && res1.length >0 && res2 && res2.length >0){total = res1[0]['count(1)']list = res2}ctx.body = {...Tips[0],data: {list,pageSize,total}};}).catch(e => {ctx.body = Tips[1002];})}); 復(fù)制代碼
-
blog.js 博客
- 創(chuàng)建博客 router.post('/oa/user/addBlog', async (ctx, next) => {let data = Utils.filter(ctx.request.body, ['title', 'content', 'tag_id', 'note_id', 'brief', 'publish', 'create_time']),uid = ctx.session.uid;let res = Utils.formatData(data, [{key: 'note_id', type: 'number'},{key: 'title', type: 'string'},{key: 'brief', type: 'string'},{key: 'content', type: 'string'},{key: 'publish', type: 'number'}]);if (! res) return ctx.body = Tips[1007];let {title = '無標(biāo)題', content = '', note_id = '', brief = '', publish = 0, create_time = ''} = data;create_time = Utils.formatCurrentTime(create_time);let sql = `INSERT INTO t_blog(title,content,note_id,create_time,uid,brief,publish) VALUES (?,?,?,?,?,?,?)`,value = [title, content, note_id, create_time, uid, brief, publish];await db.query(sql, value).then(async res => {let {insertId: id} = res;ctx.body = {...Tips[0],data: {id}}}).catch(e => {ctx.body = Tips[1002];});}); 復(fù)制代碼
- 分頁查詢博客,與筆記本列表查詢類似
-
img.js 圖片管理
- 上傳圖片 router.post('/oa/user/upFiles', async (ctx, next) => {try {let data = await asyncBusboy(ctx.req), uid = ctx.session.uid;let { files = [] } = data;if(files.length === 0) return ctx.body = Tips[1002];let file = files[0];let { mimeType = '', filename, path: filepath } = file;if(mimeType.indexOf('image') === -1) return ctx.body = Tips[1002];let name = Date.now() + '.' + filename.split('.').pop();let savePath = path.join(__dirname, `../../img/${name}`);try {let create_time = Utils.formatCurrentTime();let sql = 'INSERT INTO t_user_img(name,uid,create_time) VALUES (?,?,?)', value = [name, uid, create_time];await db.query(sql, value).then(res => {let img = fs.readFileSync(filepath);fs.writeFileSync(savePath, img);fs.unlinkSync(filepath);//清除緩存文件ctx.body = {...Tips[0], data: { name }};}).catch(() => {ctx.body = Tips[1002];})} catch (e) {ctx.body = Tips[1005];}} catch (e) {ctx.body = Tips[1002];} }); 復(fù)制代碼
- 圖片列表查詢同筆記本列表查詢
2.刪除圖片
router.post('/oa/user/removeImg', async (ctx, next) => {let data = Utils.filter(ctx.request.body, ['name']), uid = ctx.session.uid;let res = Utils.formatData(data, [{ key: 'name', type: 'string' }]);if (!res) return ctx.body = Tips[1007];let { name } = data;let sql = 'UPDATE t_user_img set is_delete=1 WHERE name=? AND uid=?;', value = [name, uid];await db.query(sql, value).then(res => {fs.unlinkSync(path.join(__dirname, `../../img/${name}`));//清除緩存文件ctx.body = Tips[0];}).catch(() => {ctx.body = Tips[1002];})}); 復(fù)制代碼路由統(tǒng)一管理
router/index.js將所有的路由集成并掛載至app.js
-
router/index.js
const user = require('./user'); const note = require('./note'); const blog = require('./blog'); const img = require('./img'); module.exports = function(app){app.use(user.routes()).use(user.allowedMethods());app.use(note.routes()).use(note.allowedMethods());app.use(blog.routes()).use(blog.allowedMethods());app.use(img.routes()).use(img.allowedMethods()); }復(fù)制代碼 -
app.js(對需要登錄的路由統(tǒng)一管理)
const http = require('http'); const koa = require('koa'); const etag = require('koa-etag'); const session = require('koa-session'); const bodyParser = require('koa-bodyparser'); const errorHandler = require('koa-error'); const compress = require('koa-compress'); const PORT = process.env.PORT || 8080; const koaBody = require('koa-body'); const app = new koa(); const Utils = require('./utils'); const router = require('./router'); app.keys = ['session@&'];app.use(session({key: 'abc::sess',maxAge: 86400000,overwrite: true,httpOnly: true,signed: true,rolling: false }, app)); app.use(koaBody()); app.use(async(ctx, next) => {let {url = ''} = ctx;if(url.indexOf('/oa/user/') >-1){//需要校驗(yàn)登錄態(tài)let check = Utils.checkLogin(ctx);if(check.code != 0) return ctx.body = check;}await next();}); app.use(errorHandler()); app.use(bodyParser());app.use(etag());// compressor app.use(compress({filter: contentType => /text|javascript/i.test(contentType),threshold: 2048 })); router(app); http.createServer(app.callback()).listen(PORT); log('server is running on port: %s', PORT); 復(fù)制代碼
以上便是后臺搭建全過程,點(diǎn)此查看后臺源碼。
閱讀原文
前端項(xiàng)目源碼
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的node+koa2+mysql搭建博客后台的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: notion函数_Notion使用指南
- 下一篇: mysql安装条款_mysql 安装注意