本文将详细讲解使用node+koa2+mysql搭建博客后台的全过程。

开发环境

  • node 8.3.0及以上
  • npm 5.3.0及以上
  • mysql 5.7.21

具体的环境配置可查看我的上一篇文章

准备工作

  • npm下载pm2(进程守护),并设置全局变量
  • 创建博客需要的数据库与表
    1. 开启mysql并创建数据库test: create database test;
    2. 切换到数据库testuse tests;,输入命令创建以下数据表:
//系统管理员表 t_user
CREATE TABLE `t_user` (`uid` int(11) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL COMMENT '姓名',`password` varchar(50) NOT NULL COMMENT '密码',`create_time` datetime NOT NULL COMMENT '注册时间',`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',`is_delete` tinyint(1) DEFAULT '0',PRIMARY KEY (`uid`),UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;//笔记本表 t_note
CREATE TABLE `t_note` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL COMMENT '笔记本名',`uid` int(11) NOT NULL COMMENT 'uid',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',`is_delete` tinyint(1) DEFAULT '0',PRIMARY KEY (`id`),UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;//博客记录表 t_blog
CREATE TABLE `t_blog` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`title` varchar(200) DEFAULT NULL COMMENT '标题',`uid` int(11) DEFAULT '1' COMMENT 'uid',`content` text COMMENT '内容',`create_time` datetime NOT NULL COMMENT '注册时间',`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',`note_id` varchar(45) DEFAULT NULL,`publish` tinyint(4) DEFAULT '0' COMMENT '是否发布',`brief` text,`is_delete` tinyint(1) DEFAULT '0' COMMENT '是否删除',`ext_info` text,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;//图片上传记录表 t_img
CREATE TABLE `t_img` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`uid` int(11) NOT NULL COMMENT 'uid',`create_time` datetime NOT NULL COMMENT '注册时间',`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',`name` varchar(40) DEFAULT NULL,`is_delete` tinyint(1) DEFAULT '0',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0  DEFAULT CHARSET=utf8;复制代码

node后台目录创建及npm包安装

  • 创建项目文件夹server,进入文件夹后初始化项目npm init
  • 在项目下创建以下文件夹和文件
  • 安装以下依赖包:
    1. koa node框架
    2. koa-bodyparser 表单解析中间件
    3. koa-router 路由框架
    4. koa-session 基于koa的session模块
    5. mysql 数据库
    6. md5 md5加密
    7. async-busboy 带文件的表单解析模块
    8. is 数据格式校验插件

node连接mysql

db/index.js配置文件如下:

var mysql = require('mysql');
let config = {host     : 'localhost',user     : 'root',password : '123456',database : 'test',port:3306,multipleStatements: true//允许多条sql同时执行
};
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
}
复制代码

其他配置

  • 框架公用方法,包括参数校验、登录态校验等。config/index.js
  • 框架接口返回码规范 config/tip.js

路由 Rouer

以上配置完成后,便可以开始写设计路由了。

引入相关配置

const router = require('koa-router')();
const Utils = require('../utils');
const Tips = require('../utils/tip');
const db = require('../db');
复制代码

根据表设计路由

  • user表 -> user.js 管理员管理,可登录、查询登录态、退出登录
  • note表 -> note.js 笔记本管理,可添加、修改、删除,查询笔记本列表
  • blog表 -> blog.js 博客管理 可添加、修改、删除、查询博客列表。每篇博客必须关联对应的笔记本。可根据笔记本查询博客列表
  • img表 -> img.js 图片管理,可上传、删除、查询图片列表

具体路由部分实现内容

注意:所有的删除操作均为将表字段is_delete设置为1即可,方便恢复数据

  • user.js 管理员

    1. 登录
        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];})});复制代码
    1. 查询登录信息
    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];})
    });
    复制代码
  • note.js 笔记本管理

    1. 创建笔记本
    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){//笔记本不能重复ctx.body = {code: 1010,msg: '笔记本已存在!'};}else{ctx.body = Tips[1002]}})
    });
    复制代码
    1. (分页)查询笔记本列表
    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];})});
    复制代码
  • blog.js 博客

    1. 创建博客
    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 = '无标题', 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];});});
    复制代码
    1. 分页查询博客,与笔记本列表查询类似
  • img.js 图片管理

    1. 上传图片
    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];}
    });
    复制代码

    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];})});
    复制代码
    1. 图片列表查询同笔记本列表查询

路由统一管理

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());
    }复制代码
  • app.js(对需要登录的路由统一管理)

    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){//需要校验登录态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);
    复制代码

以上便是后台搭建全过程,点此查看后台源码。

阅读原文

前端项目源码

node+koa2+mysql搭建博客后台相关推荐

  1. node mysql和koa_node+koa2+mysql搭建博客后台

    本文将详细讲解使用node+koa2+mysql搭建博客后台的全过程. 开发环境 node 8.3.0及以上 npm 5.3.0及以上 mysql 5.7.21 具体的环境配置可查看我的上一篇文章 准 ...

  2. node mysql 搭建博客_node.js+Hexo+Git搭建个人博客

    今早上考完试回来,接到腾讯云的每月邮件续费通知. 对于一个小开发来讲,买一个云服务器建站最方便不过,但是对于学生党来说还是有些贵. 一想明年7月份,云服务器就一元每月变65每月,加上30来块的域名费, ...

  3. 《全栈营销之如何制作个人博客》之二:php环境安装及个人博客后台搭建 让你的博客跑起来...

    上一节我们讲了个人博客用什么开发语言,用什么CMS系统,从这一节我们就开始真正的干货,这一节我们讨论一下PHP环境的安装,及个人博客后台的搭建,让你的博客在正常的PHP环境中运行起来,你就可以进行后台 ...

  4. 建站规划—基于私有化gitlab/node+hexo搭建博客网站

    目录 概述 建站方案及成本 建站方案 成本 低成本替代方案 概述 本合辑(建站合辑)将介绍如何基于私有化gitlab+pages+Hexo搭建博客网站,由于域名备案周期较长,因此更新可能较慢.根据功能 ...

  5. ty博客后台搭建教程

    分享一款好看的ty博客后台源码,本人目前用的就是这款,电脑 手机都能很好的自适应! 准备材料:主机 源码 脑子 现在开始:首先下载ty博客源码:http://typecho.org/download下 ...

  6. Node项目实战开发-博客系统

    Nodejs项目实战开发-博客系统(已完结) 个人博客系统 欢迎访问我的博客~ MaXiaoYu's Bolg 前言: 开发技术 技术 版本 Node ^14.3.0 ejs ^3.1.3 expre ...

  7. Ghost 搭建博客小记

    前言 点击 我用 Ghost 搭建的博客 查看成品示例. 早就听说 Ghost 的大名了,不过一直都是处于观望状态.主要是想等 Ghost 各方面再成熟一些,所以迟迟没有行动.最近听闻 Ghost 已 ...

  8. 详解Hexo搭建博客的底层原理

    文章目录 前言 Github page Hexo 工作原理 每次部署的流程 模板引擎--Hexo怎样生成HTML 数据填充 配置文件中的数据 配置文件中数据的使用 总结 前言 在2021年初对照着攻略 ...

  9. 使用Docker 实现微服务并搭建博客,一文全掌握

    转载自  使用Docker 实现微服务并搭建博客,一文全掌握 Docker 是一个容器工具,提供虚拟环境.很多人认为,它改变了我们对软件的认识. 本文,通过搭建一个博客的例子,来介绍如何使用Docke ...

最新文章

  1. UML博客建模--用例图
  2. 用VMWARE学习组网(四)
  3. 今天的你,又被带节奏了吗?
  4. mac中apache服务器及虚拟主机配置
  5. Intel 11代全新核显出现了!好强 好乱
  6. dederss.php美国与,dedecms添加rss订阅功能实现代码
  7. 鼠标点击改变单元格颜色或点击改变行颜色
  8. cad快速选择命令快捷键_CAD快捷键命令大全
  9. xshell如何上传文件
  10. 常用ADSS光缆的代表结构和主要参数介绍
  11. 2014年12月CCF软考试题
  12. 关于marked数组处理
  13. 面上大厂需要准备的面试题
  14. python 头条 sign 参数 此篇针对实时列表 请使用73版本的谷歌浏览器
  15. 计算机毕业设计ssm+vue基本微信小程序的拼车自助服务小程序
  16. hex颜色透明度对比表
  17. LEFT OUTER JOIN 使用实例
  18. java中的双冒号操作符
  19. spec cpu 2017使用教程
  20. html手机偏左,判断方向盘跑偏有妙招 一部手机就搞定

热门文章

  1. navicat 只对比一张表的数据_Excel VBA批量新建工作表(对比数据透视表的使用)...
  2. 【matlab函数】convn多维卷积
  3. LDAP第三天 MySQL+LDAP 安装
  4. Web开发编程实用手册
  5. 创业,程序员心中说不出的痛
  6. vue-provide/inject轻松实现跨级访问祖先组件
  7. Vue -项目创建(rem适配项的设置)
  8. kubernetes--配置文件
  9. 第八模块:算法设计模式、企业应用 第2章 企业应用工具学习
  10. 【bzoj3994】[SDOI2015]约数个数和 莫比乌斯反演