node+koa2+mysql搭建博客后台
本文将详细讲解使用node+koa2+mysql搭建博客后台的全过程。
开发环境
- node 8.3.0及以上
- npm 5.3.0及以上
- mysql 5.7.21
具体的环境配置可查看我的上一篇文章
准备工作
- npm下载pm2(进程守护),并设置全局变量
- 创建博客需要的数据库与表
- 开启mysql并创建数据库test:
create database test;
- 切换到数据库test
use tests;
,输入命令创建以下数据表:
- 开启mysql并创建数据库test:
//系统管理员表 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
。 - 在项目下创建以下文件夹和文件
- 安装以下依赖包:
- koa node框架
- koa-bodyparser 表单解析中间件
- koa-router 路由框架
- koa-session 基于koa的session模块
- mysql 数据库
- md5 md5加密
- async-busboy 带文件的表单解析模块
- 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 管理员
- 登录
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];})});复制代码
- 查询登录信息
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 笔记本管理
- 创建笔记本
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]}}) }); 复制代码
- (分页)查询笔记本列表
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 博客
- 创建博客
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];});}); 复制代码
- 分页查询博客,与笔记本列表查询类似
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];} }); 复制代码
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];})}); 复制代码
- 图片列表查询同笔记本列表查询
路由统一管理
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搭建博客后台相关推荐
- node mysql和koa_node+koa2+mysql搭建博客后台
本文将详细讲解使用node+koa2+mysql搭建博客后台的全过程. 开发环境 node 8.3.0及以上 npm 5.3.0及以上 mysql 5.7.21 具体的环境配置可查看我的上一篇文章 准 ...
- node mysql 搭建博客_node.js+Hexo+Git搭建个人博客
今早上考完试回来,接到腾讯云的每月邮件续费通知. 对于一个小开发来讲,买一个云服务器建站最方便不过,但是对于学生党来说还是有些贵. 一想明年7月份,云服务器就一元每月变65每月,加上30来块的域名费, ...
- 《全栈营销之如何制作个人博客》之二:php环境安装及个人博客后台搭建 让你的博客跑起来...
上一节我们讲了个人博客用什么开发语言,用什么CMS系统,从这一节我们就开始真正的干货,这一节我们讨论一下PHP环境的安装,及个人博客后台的搭建,让你的博客在正常的PHP环境中运行起来,你就可以进行后台 ...
- 建站规划—基于私有化gitlab/node+hexo搭建博客网站
目录 概述 建站方案及成本 建站方案 成本 低成本替代方案 概述 本合辑(建站合辑)将介绍如何基于私有化gitlab+pages+Hexo搭建博客网站,由于域名备案周期较长,因此更新可能较慢.根据功能 ...
- ty博客后台搭建教程
分享一款好看的ty博客后台源码,本人目前用的就是这款,电脑 手机都能很好的自适应! 准备材料:主机 源码 脑子 现在开始:首先下载ty博客源码:http://typecho.org/download下 ...
- Node项目实战开发-博客系统
Nodejs项目实战开发-博客系统(已完结) 个人博客系统 欢迎访问我的博客~ MaXiaoYu's Bolg 前言: 开发技术 技术 版本 Node ^14.3.0 ejs ^3.1.3 expre ...
- Ghost 搭建博客小记
前言 点击 我用 Ghost 搭建的博客 查看成品示例. 早就听说 Ghost 的大名了,不过一直都是处于观望状态.主要是想等 Ghost 各方面再成熟一些,所以迟迟没有行动.最近听闻 Ghost 已 ...
- 详解Hexo搭建博客的底层原理
文章目录 前言 Github page Hexo 工作原理 每次部署的流程 模板引擎--Hexo怎样生成HTML 数据填充 配置文件中的数据 配置文件中数据的使用 总结 前言 在2021年初对照着攻略 ...
- 使用Docker 实现微服务并搭建博客,一文全掌握
转载自 使用Docker 实现微服务并搭建博客,一文全掌握 Docker 是一个容器工具,提供虚拟环境.很多人认为,它改变了我们对软件的认识. 本文,通过搭建一个博客的例子,来介绍如何使用Docke ...
最新文章
- UML博客建模--用例图
- 用VMWARE学习组网(四)
- 今天的你,又被带节奏了吗?
- mac中apache服务器及虚拟主机配置
- Intel 11代全新核显出现了!好强 好乱
- dederss.php美国与,dedecms添加rss订阅功能实现代码
- 鼠标点击改变单元格颜色或点击改变行颜色
- cad快速选择命令快捷键_CAD快捷键命令大全
- xshell如何上传文件
- 常用ADSS光缆的代表结构和主要参数介绍
- 2014年12月CCF软考试题
- 关于marked数组处理
- 面上大厂需要准备的面试题
- python 头条 sign 参数 此篇针对实时列表 请使用73版本的谷歌浏览器
- 计算机毕业设计ssm+vue基本微信小程序的拼车自助服务小程序
- hex颜色透明度对比表
- LEFT OUTER JOIN 使用实例
- java中的双冒号操作符
- spec cpu 2017使用教程
- html手机偏左,判断方向盘跑偏有妙招 一部手机就搞定