├── .gitattributes ├── LICENSE ├── README.md ├── app.js ├── config ├── pri.pem └── pub.pem ├── db └── index.js ├── package.json ├── router ├── blog.js ├── img.js ├── index.js ├── note.js └── user.js └── utils ├── index.js └── tip.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 jiangxueyang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | A backend project building with node and mysql. 3 | 4 | To start,you should install mysql and pm2.For detail,please read this [tutorial](http://jiangxy.cn/jxy/blog/detail/17) 5 | 6 | ``` 7 | //install 8 | npm install 9 | 10 | //run your project 11 | node app 12 | or 13 | pm2 start app.js --watch 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const koa = require('koa'); 3 | const etag = require('koa-etag'); 4 | const bodyParser = require('koa-bodyparser'); 5 | const errorHandler = require('koa-error'); 6 | const compress = require('koa-compress'); 7 | const log = global.console.log.bind(console); 8 | const PORT = process.env.PORT || 8080; 9 | const koaBody = require('koa-body'); 10 | const app = new koa(); 11 | const Utils = require('./utils'); 12 | const router = require('./router'); 13 | const Tips = require('./utils/tip'); 14 | app.use(koaBody()); 15 | 16 | app.use(async(ctx, next) => { 17 | let {url = ''} = ctx; 18 | if(url.indexOf('/oa/user/') > -1){//需要校验登录态 19 | let header = ctx.request.header; 20 | let {loginedtoken} = header; 21 | 22 | if (loginedtoken) { 23 | let result = Utils.verifyToken(loginedtoken); 24 | let {uid} = result; 25 | if(uid){ 26 | ctx.state = {uid}; 27 | await next(); 28 | }else{ 29 | return ctx.body = Tips[1005]; 30 | } 31 | } else { 32 | return ctx.body = Tips[1005]; 33 | } 34 | }else{ 35 | await next(); 36 | } 37 | 38 | 39 | 40 | }); 41 | app.use(errorHandler()); 42 | app.use(bodyParser()); 43 | 44 | app.use(etag()); 45 | 46 | // compressor 47 | app.use(compress({ 48 | filter: contentType => /text|javascript/i.test(contentType), 49 | threshold: 2048 50 | })); 51 | router(app); 52 | http.createServer(app.callback()).listen(PORT); 53 | 54 | 55 | log('server is running on port: %s', PORT); -------------------------------------------------------------------------------- /config/pri.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAvtH4wKLYlIXZlfYQFJtXZVC3fD8XMarzwvb/fHUyJ6NvNStN 3 | +H7GHp3/QhZbSaRyqK5hu5xXtFLgnI0QG8oE1NlXbczjH45LeHWhPIdc2uHSpzXi 4 | c78kOugMY1vng4J10PF6+T2FNaiv0iXeIQq9xbwwPYpflViQyJnzGCIZ7VGan6Gb 5 | RKzyTKcB58yx24pJq+CviLXEY52TIW1l5imcjGvLtlCp1za9qBZa4XGoVqHi1kRX 6 | kdDSHty6lZWj3KxoRvTbiaBCH+75U7rifS6fR9lqjWE57bCGoz7+BBu9YmPKtI1K 7 | kyHFqWpxaJc/AKf9xgg+UumeqVcirUmAsHJrMwIDAQABAoIBAQCYKw05YSNhXVPk 8 | eHLeW/pXuwR3OkCexPrakOmwMC0s2vIF7mChN0d6hvhVlUp68X7V8SnS2JxAGo8v 9 | iHY+Et3DdwZ3cxnzwh+BEhzgDfoIOmkoGppZPyX/K6klWtbGUrTtSISOWXbvEXQU 10 | G0qGAvDOzIGTsdMDX7slnU70Ac23JybPY5qBSiE+ky8U4dm2fUHMroWub4QP5vA/ 11 | nqyWqX2FB/MEAbcujaknDQrFCtbmtUYlBbJCKGd9V3cGEqp6H7oH+ah2ofMc91gJ 12 | mCHk3YyWZB/bcVXH3CA+s1ywvCOVDBZ3Nw7Pt9zIcv6Rl9UKIy+Nx0QjXxR90Hla 13 | Tr0GHIShAoGBAPsD7uXm+0ksnGyKRYgvlVad8Z8FUFT6bf4B+vboDbx40FO8O/5V 14 | PraBPC5z8YRSBOQ/WfccPQzakkA28F2pXlRpXu5JcErVWnyyUiKpX5sw6iPenQR2 15 | JO9hY/GFbKiwUhVHpvWMcXFqFLSQu2A86jPnFFEfG48ZT4IhTzINKJVZAoGBAMKc 16 | B3YGfVfY9qiRFXzYRdSRLg5c8p/HzuWwXc9vfJ4kQTDkPXe/+nqD67rzeT54uVec 17 | jKoIrsCu4BfEaoyvOT+1KmUfdEpBgYZuuEC4CZf7dgKbXOpPVvZDMyJ/e7HyqTpw 18 | mvIYJLPm2fNAcAsnbrNX5mhLwwzEIltbplUUeRdrAoGBAKhZgPYsLkhrZRXevreR 19 | wkTvdUfD1pbHxtFfHqROCjhnhsFCM7JmFcNtdaFqHYczQxiZ7IqxI7jlNsVek2Md 20 | 3qgaa5LBKlDmOuP67N9WXUrGSaJ5ATIm0qrB1Lf9VlzktIiVH8L7yHHaRby8fQ8U 21 | i7b3ukaV6HPW895A3M6iyJ8xAoGAInp4S+3MaTL0SFsj/nFmtcle6oaHKc3BlyoP 22 | BMBQyMfNkPbu+PdXTjtvGTknouzKkX4X4cwWAec5ppxS8EffEa1sLGxNMxa19vZI 23 | yJaShI21k7Ko3I5f7tNrDNKfPKCsYMEwgnHKluDwfktNTnyW/Uk2dgXuMaXSHHN5 24 | XZt59K8CgYArGVOWK7LUmf3dkTIs3tXBm4/IMtUZmWmcP9C8Xe/Dg/IdQhK5CIx4 25 | VXl8rgZNeX/5/4nJ8Q3LrdLau1Iz620trNRGU6sGMs3x4WQbSq93RRbFzfG1oK74 26 | IOo5yIBxImQOSk5jz31gF9RJb15SDBIxonuWv8qAERyUfvrmEwR0kg== 27 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /config/pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDtTCCAp2gAwIBAgIJAMKR/NsyfcazMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTIxMTEyMjM0MzQxWhcNMTYxMjIxMjM0MzQxWjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 7 | CgKCAQEAvtH4wKLYlIXZlfYQFJtXZVC3fD8XMarzwvb/fHUyJ6NvNStN+H7GHp3/ 8 | QhZbSaRyqK5hu5xXtFLgnI0QG8oE1NlXbczjH45LeHWhPIdc2uHSpzXic78kOugM 9 | Y1vng4J10PF6+T2FNaiv0iXeIQq9xbwwPYpflViQyJnzGCIZ7VGan6GbRKzyTKcB 10 | 58yx24pJq+CviLXEY52TIW1l5imcjGvLtlCp1za9qBZa4XGoVqHi1kRXkdDSHty6 11 | lZWj3KxoRvTbiaBCH+75U7rifS6fR9lqjWE57bCGoz7+BBu9YmPKtI1KkyHFqWpx 12 | aJc/AKf9xgg+UumeqVcirUmAsHJrMwIDAQABo4GnMIGkMB0GA1UdDgQWBBTs83nk 13 | LtoXFlmBUts3EIxcVvkvcjB1BgNVHSMEbjBsgBTs83nkLtoXFlmBUts3EIxcVvkv 14 | cqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV 15 | BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAMKR/NsyfcazMAwGA1UdEwQF 16 | MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABw7w/5k4d5dVDgd/OOOmXdaaCIKvt7d 17 | 3ntlv1SSvAoKT8d8lt97Dm5RrmefBI13I2yivZg5bfTge4+vAV6VdLFdWeFp1b/F 18 | OZkYUv6A8o5HW0OWQYVX26zIqBcG2Qrm3reiSl5BLvpj1WSpCsYvs5kaO4vFpMak 19 | /ICgdZD+rxwxf8Vb/6fntKywWSLgwKH3mJ+Z0kRlpq1g1oieiOm1/gpZ35s0Yuor 20 | XZba9ptfLCYSggg/qc3d3d0tbHplKYkwFm7f5ORGHDSD5SJm+gI7RPE+4bO8q79R 21 | PAfbG1UGuJ0b/oigagciHhJp851SQRYf3JuNSc17BnK2L5IEtzjqr+Q= 22 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /db/index.js: -------------------------------------------------------------------------------- 1 | var mysql = require('mysql'); 2 | let config = { 3 | host : 'localhost', 4 | user : 'root', 5 | password : '123456', 6 | database : 'test', 7 | port:3306, 8 | multipleStatements: true//允许多条sql同时执行 9 | }; 10 | let pool = mysql.createPool(config); 11 | let query = (sql, values) => { 12 | 13 | return new Promise((resolve, reject) => { 14 | pool.getConnection((err, connection) => { 15 | if (err) { 16 | reject(err) 17 | } else { 18 | connection.query(sql, values, (err, rows) => { 19 | if (err) { 20 | reject(err) 21 | } else { 22 | resolve(rows) 23 | } 24 | connection.end() 25 | }) 26 | } 27 | }) 28 | }) 29 | }; 30 | module.exports = { 31 | query 32 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "servertest", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "jxy", 10 | "license": "MIT", 11 | "dependencies": { 12 | "kcors": "^2.2.1", 13 | "koa": "^2.3.0", 14 | "koa-body": "^2.3.0", 15 | "koa-bodyparser": "^4.2.0", 16 | "koa-compress": "^2.0.0", 17 | "koa-error": "^3.0.1", 18 | "koa-etag": "^3.0.0", 19 | "koa-logger": "^3.1.0", 20 | "koa-router": "^7.2.1" 21 | }, 22 | "devDependencies": { 23 | "async-busboy": "^0.6.2", 24 | "is": "^3.2.1", 25 | "jsonwebtoken": "^8.2.0", 26 | "locutus": "^2.0.9", 27 | "lodash": "^4.17.5", 28 | "log4js": "^2.3.12", 29 | "md5": "^2.2.1", 30 | "mysql": "^2.15.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /router/blog.js: -------------------------------------------------------------------------------- 1 | const router = require('koa-router')(); 2 | const Utils = require('../utils'); 3 | const Tips = require('../utils/tip'); 4 | const db = require('../db/index'); 5 | const fs = require('fs'); 6 | const asyncBusboy = require('async-busboy'); 7 | //创建一篇博客,必须登录 8 | router.post('/oa/user/addBlog', async (ctx, next) => { 9 | let data = Utils.filter(ctx.request.body, ['title', 'content', 'tag_id', 'note_id', 'brief', 'publish', 'create_time']), 10 | {uid} = ctx.state || {}; 11 | let res = Utils.formatData(data, [ 12 | {key: 'note_id', type: 'number'}, 13 | {key: 'title', type: 'string'}, 14 | {key: 'brief', type: 'string'}, 15 | {key: 'content', type: 'string'}, 16 | {key: 'publish', type: 'number'} 17 | ]); 18 | if (! res) return ctx.body = Tips[1007]; 19 | let {title = '无标题', content = '', note_id = '', brief = '', publish = 0, create_time = ''} = data; 20 | create_time = Utils.formatCurrentTime(create_time); 21 | let sql = `INSERT INTO t_blog(title,content,note_id,create_time,uid,brief,publish) VALUES (?,?,?,?,?,?,?)`, 22 | value = [title, content, note_id, create_time, uid, brief, publish]; 23 | await db.query(sql, value).then(async res => { 24 | let {insertId: id} = res; 25 | ctx.body = { 26 | ...Tips[0], 27 | data: {id} 28 | } 29 | 30 | }).catch(e => { 31 | ctx.body = Tips[1002]; 32 | }); 33 | 34 | }); 35 | 36 | //修改博客 37 | router.post('/oa/user/modifyBlog', async (ctx, next) => { 38 | let data = Utils.filter(ctx.request.body, ['title', 'origin_tag_id', 'content', 'tag_id', 'note_id', 'id', 'brief', 'publish', 'create_time']), 39 | {uid} = ctx.state || {}; 40 | let res = Utils.formatData(data, [ 41 | {key: 'note_id', type: 'number'}, 42 | {key: 'id', type: 'number'}, 43 | {key: 'title', type: 'string'}, 44 | {key: 'brief', type: 'string'}, 45 | {key: 'content', type: 'string'}, 46 | {key: 'publish', type: 'number'} 47 | ]); 48 | if (! res) return ctx.body = Tips[1007]; 49 | let {title, content, note_id, id, brief, publish = 0, create_time = ''} = data; 50 | create_time = Utils.formatCurrentTime(create_time); 51 | let sql = `UPDATE t_blog set title=?,content=?,note_id=?,brief=?,publish=?,create_time=? WHERE uid=? AND id=?;`, 52 | value = [title, content, note_id, brief, publish, create_time, uid, id]; 53 | 54 | await db.query(sql, value).then(async res => { 55 | ctx.body = Tips[0]; 56 | }).catch(e => { 57 | ctx.body = Tips[1002]; 58 | }) 59 | 60 | }); 61 | 62 | //删除博客 63 | router.post('/oa/user/removeBlog', async (ctx, next) => { 64 | let data = Utils.filter(ctx.request.body, ['id']), {uid} = ctx.state || {}; 65 | let res = Utils.formatData(data, [ 66 | {key: 'id', type: 'number'} 67 | ]); 68 | if (! res) return ctx.body = Tips[1007]; 69 | let {id} = data; 70 | let sql = 'UPDATE t_blog set is_delete=1 WHERE id=? AND uid=?', value = [id, uid]; 71 | await db.query(sql, value).then(async res => { 72 | ctx.body = Tips[0]; 73 | }).catch(e => { 74 | ctx.body = Tips[1002]; 75 | }); 76 | }); 77 | 78 | //发布或上线博客 79 | router.post('/oa/user/changeBlogStatus', async (ctx, next) => { 80 | let data = Utils.filter(ctx.request.body, ['id', 'publish']), uid = ctx.session.uid; 81 | let res = Utils.formatData(data, [ 82 | {key: 'id', type: 'number'}, 83 | {key: 'publish', type: 'number'} 84 | ]); 85 | if (! res) return ctx.body = Tips[1007]; 86 | let {id, publish} = data; 87 | await db.query('UPDATE t_blog set publish=? WHERE uid=? AND id=?', [publish, uid, id]).then(res => { 88 | ctx.body = Tips[0]; 89 | }).catch(e => { 90 | ctx.body = Tips[1002]; 91 | }) 92 | }) 93 | 94 | //分页查询我所有的博客 type:0:我所有的 1 根据笔记本查询 95 | router.get('/oa/user/myBlog', async (ctx, next) => { 96 | let data = Utils.filter(ctx.request.query, ['pageSize', 'pageNum', 'note_id', 'type']), {uid} = ctx.state || {}; 97 | let res = Utils.formatData(data, [ 98 | {key: 'note_id', type: 'number'} 99 | ]); 100 | if (! res) return ctx.body = Tips[1007]; 101 | let filterData = {}; 102 | for (let i in data) { 103 | filterData[i] = parseInt(data[i]) 104 | } 105 | let {pageSize = 15, pageNum = 1, note_id, type = 0} = filterData; 106 | let offset = (pageNum - 1) * pageSize, sql, sql1; 107 | if (+type === 1) { 108 | sql = `SELECT content,id,title,note_id,brief,create_time,update_time,publish FROM t_blog WHERE uid=${uid} AND note_id=${note_id} AND is_delete=0 ORDER BY create_time DESC limit ${offset},${pageSize};`; 109 | sql1 = `SELECT count(1) FROM t_blog WHERE uid=${uid} AND note_id=${note_id} AND is_delete=0;`; 110 | } else { 111 | sql = `SELECT content,id,title,note_id,brief,create_time,update_time,publish FROM t_blog WHERE uid=${uid} AND is_delete=0 ORDER BY create_time DESC limit ${offset},${pageSize};`; 112 | sql1 = `SELECT count(1) FROM t_blog WHERE uid=${uid} AND is_delete=0;`; 113 | } 114 | await db.query(sql1+sql).then(async result => { 115 | let res1 = result[0],res2 = result[1],total = 0,list = []; 116 | if(res1 && res1.length >0 && res2 && res2.length >0){ 117 | total = res1[0]['count(1)']; 118 | list = res2; 119 | } 120 | ctx.body = { 121 | ...Tips[0], 122 | data: { 123 | list, 124 | pageSize, 125 | total 126 | } 127 | }; 128 | 129 | }).catch(e => { 130 | ctx.body = Tips[1002]; 131 | }) 132 | }); 133 | //查看博客详情 134 | router.get('/oa/blog/:id', async (ctx, next) => { 135 | let data = ctx.params; 136 | let res = Utils.formatData(data, [ 137 | {key: 'id', type: 'number'} 138 | ]); 139 | if (! res) return ctx.body = Tips[1007]; 140 | let {id} = data; 141 | id = parseInt(id); 142 | let sql = `SELECT content,id,title,note_id,brief,create_time,publish FROM t_blog WHERE id=${id} AND is_delete=0;`; 143 | await db.query(sql).then(res => { 144 | let detail = res[0] || []; 145 | if(detail.length >0){ 146 | ctx.body = {...Tips[0],data:detail} 147 | 148 | }else{ 149 | ctx.body = Tips[1003] 150 | } 151 | }).catch(e => { 152 | ctx.body = Tips[1002]; 153 | }) 154 | }); 155 | 156 | //识别md文件 157 | router.post('/oa/user/recognizeFile', async (ctx, next) => { 158 | try { 159 | let data = await asyncBusboy(ctx.req); 160 | let {files = []} = data; 161 | if (files.length > 0) { 162 | let file = files[0]; 163 | let {path: filePath} = file; 164 | try { 165 | let content = fs.readFileSync(filePath, 'utf-8'); 166 | fs.unlinkSync(filePath);//清除 167 | ctx.body = { 168 | ...Tips[0], 169 | data: content 170 | } 171 | } catch (e) { 172 | ctx.body = Tips[1008]; 173 | } 174 | } else { 175 | ctx.body = Tips[1008]; 176 | } 177 | } catch (e) { 178 | ctx.body = Tips[1008]; 179 | } 180 | 181 | 182 | }); 183 | 184 | module.exports = router; -------------------------------------------------------------------------------- /router/img.js: -------------------------------------------------------------------------------- 1 | const router = require('koa-router')(); 2 | const Utils = require('../utils'); 3 | const Tips = require('../utils/tip'); 4 | const db = require('../db/index'); 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | const asyncBusboy = require('async-busboy'); 8 | // 上传图片 9 | router.post('/oa/user/upFiles', async (ctx, next) => { 10 | try { 11 | let data = await asyncBusboy(ctx.req), {uid} = ctx.state || {}; 12 | let { files = [] } = data; 13 | if(files.length === 0) return ctx.body = Tips[1002]; 14 | let file = files[0]; 15 | let { mimeType = '', filename, path: filepath } = file; 16 | if(mimeType.indexOf('image') === -1) return ctx.body = Tips[1002]; 17 | let name = Date.now() + '.' + filename.split('.').pop(); 18 | let savePath = path.join(__dirname, `../../img/${name}`); 19 | try { 20 | let create_time = Utils.formatCurrentTime(); 21 | let sql = 'INSERT INTO t_user_img(name,uid,create_time) VALUES (?,?,?)', value = [name, uid, create_time]; 22 | await db.query(sql, value).then(res => { 23 | let img = fs.readFileSync(filepath); 24 | fs.writeFileSync(savePath, img); 25 | fs.unlinkSync(filepath);//清除缓存文件 26 | ctx.body = { 27 | ...Tips[0], data: { name } 28 | }; 29 | }).catch(() => { 30 | ctx.body = Tips[1002]; 31 | }) 32 | 33 | } catch (e) { 34 | ctx.body = Tips[1005]; 35 | } 36 | } catch (e) { 37 | ctx.body = Tips[1002]; 38 | } 39 | }); 40 | 41 | //删除图片 42 | router.post('/oa/user/removeImg', async (ctx, next) => { 43 | let data = Utils.filter(ctx.request.body, ['name']),{uid} = ctx.state || {}; 44 | let res = Utils.formatData(data, [ 45 | { key: 'name', type: 'string' } 46 | ]); 47 | if (!res) return ctx.body = Tips[1007]; 48 | let { name } = data; 49 | let sql = 'UPDATE t_user_img set is_delete=1 WHERE name=? AND uid=?;', value = [name, uid]; 50 | await db.query(sql, value).then(res => { 51 | fs.unlinkSync(path.join(__dirname, `../../img/${name}`));//清除缓存文件 52 | ctx.body = Tips[0]; 53 | }).catch(() => { 54 | ctx.body = Tips[1002]; 55 | }) 56 | 57 | }); 58 | //分页查询 图片 59 | router.get('/oa/user/myImg', async (ctx, next) => { 60 | let data = Utils.filter(ctx.request.query, ['pageSize', 'pageNum']), uid = ctx.session.uid; 61 | let { pageNum = 1, pageSize = 10 } = data; 62 | pageNum = Number(pageNum); 63 | pageSize = Number(pageSize); 64 | let offset = (pageNum - 1) * pageSize; 65 | let sql = `SELECT name,create_time,id FROM t_user_img WHERE uid=${uid} AND is_delete=0 ORDER BY create_time DESC limit ${offset},${pageSize};`, 66 | sql1 = `SELECT count(1) FROM t_user_img WHERE uid=${uid} AND is_delete=0;`; 67 | await db.query(sql1+sql).then(async result => { 68 | let res1 = result[0],res2 = result[1],total = 0,list =[]; 69 | if(res1 && res1.length >0 && res2 && res2.length >0){ 70 | total = res1[0]['count(1)']; 71 | list = res2; 72 | } 73 | ctx.body = { 74 | ...Tips[0], 75 | data: { 76 | list, 77 | pageSize, 78 | total 79 | } 80 | }; 81 | }).catch(e => { 82 | ctx.body = Tips[1002]; 83 | }) 84 | }); 85 | 86 | 87 | module.exports = router; -------------------------------------------------------------------------------- /router/index.js: -------------------------------------------------------------------------------- 1 | const user = require('./user'); 2 | const note = require('./note'); 3 | const blog = require('./blog'); 4 | const img = require('./img'); 5 | module.exports = function(app){ 6 | app.use(user.routes()).use(user.allowedMethods()); 7 | app.use(note.routes()).use(note.allowedMethods()); 8 | app.use(blog.routes()).use(blog.allowedMethods()); 9 | app.use(img.routes()).use(img.allowedMethods()); 10 | } 11 | -------------------------------------------------------------------------------- /router/note.js: -------------------------------------------------------------------------------- 1 | const router = require('koa-router')(); 2 | const Utils = require('../utils'); 3 | const Tips = require('../utils/tip'); 4 | const db = require('../db'); 5 | 6 | //创建一个笔记本 7 | router.post('/oa/user/addNote',async (ctx,next)=>{ 8 | let data = Utils.filter(ctx.request.body, ['name']); 9 | let {name} = data, {uid} = ctx.state || {}; 10 | let res = Utils.formatData(data, [ 11 | {key: 'name', type: 'string'} 12 | ]); 13 | if (! res) return ctx.body = Tips[1007]; 14 | let create_time = Utils.formatCurrentTime(); 15 | let sql = `INSERT INTO t_note(name,uid,create_time) VALUES(?,?,?)`, 16 | value = [name, uid, create_time]; 17 | await db.query(sql, value).then(res => { 18 | let {insertId: id} = res; 19 | if (id) { 20 | ctx.body = { 21 | ...Tips[0], 22 | data: { 23 | id 24 | } 25 | } 26 | } else { 27 | ctx.body = Tips[1002] 28 | } 29 | }).catch(e => { 30 | if(+e.errno === 1062){//笔记本不能重复 31 | ctx.body = { 32 | code: 1010, 33 | msg: '笔记本已存在!' 34 | }; 35 | }else{ 36 | ctx.body = Tips[1002] 37 | } 38 | }) 39 | }); 40 | 41 | //修改笔记本名称 42 | router.post('/oa/user/modifyNote', async (ctx, next) => { 43 | let data = Utils.filter(ctx.request.body, ['name', 'id']), {uid} = ctx.state || {}; 44 | let res = Utils.formatData(data, [ 45 | {key: 'name', type: 'string'}, 46 | {key: 'id', type: 'number'} 47 | ]); 48 | if (! res) return ctx.body = Tips[1007]; 49 | let {name, id} = data; 50 | let sql = `UPDATE t_note set name=? WHERE id=? AND uid=?`, value = [name, id, uid]; 51 | await db.query(sql, value).then(res => { 52 | ctx.body = Tips[0]; 53 | }).catch(e => { 54 | ctx.body = Tips[1002]; 55 | }) 56 | 57 | }); 58 | 59 | 60 | //删除笔记本 61 | router.post('/oa/user/removeNote', async (ctx, next) => { 62 | let data = Utils.filter(ctx.request.body, ['id']), {uid} = ctx.state || {}; 63 | let res = Utils.formatData(data, [ 64 | {key: 'id', type: 'number'} 65 | ]); 66 | if (! res) return ctx.body = Tips[1007]; 67 | let {id} = data; 68 | let sql = `UPDATE t_note set is_delete=1 WHERE id=${id} AND uid=${uid};`, 69 | sql1 = `UPDATE t_blog set is_delete=1 WHERE note_id=${id} AND uid=${uid}` 70 | await db.query(`${sql}${sql1}`).then(res => { 71 | ctx.body = Tips[0]; 72 | }).catch(e => { 73 | ctx.body = Tips[1002] 74 | }) 75 | 76 | }); 77 | 78 | //查询笔记本详情 79 | router.get('/oa/user/noteDetail/:id', async (ctx, next) => { 80 | let data = Utils.filter(ctx.params, ['id']); 81 | let res = Utils.formatData(data, [ 82 | {key: 'id', type: 'number'} 83 | ]); 84 | if (! res) return ctx.body = Tips[1007]; 85 | let {id} = data; 86 | await db.query('SELECT name FROM t_note WHERE id=? AND is_delete=0', [id]).then(res => { 87 | if (res.length > 0) { 88 | ctx.body = { 89 | ...Tips[0], 90 | data: res[0] 91 | }; 92 | } else { 93 | ctx.body = Tips[1003]; 94 | } 95 | }).catch(() => { 96 | ctx.body = Tips[1002]; 97 | }) 98 | }) 99 | 100 | //查询我的笔记本列表 type:0 所有 1分页查询 101 | 102 | router.get('/oa/user/myNote', async (ctx, next) => { 103 | let data = Utils.filter(ctx.request.query, ['pageSize', 'pageNum', 'type']), {uid} = ctx.state || {}; 104 | let res = Utils.formatData(data, [ 105 | {key: 'type', type: 'number'}, 106 | ]); 107 | if (! res) return ctx.body = Tips[1007]; 108 | let {pageSize = 15, pageNum = 1, type = 0} = data; 109 | pageSize = Number(pageSize); 110 | pageNum = Number(pageNum); 111 | let offset = (pageNum - 1) * pageSize; 112 | let sql1 = `SELECT count(1) FROM t_note WHERE uid=${uid} AND is_delete=0;`, 113 | sql= `SELECT name,id,create_time,update_time FROM t_note WHERE uid=${uid} AND is_delete=0 ORDER BY create_time DESC`; 114 | if(+type === 1){ 115 | sql += ` limit ${offset},${pageSize};` 116 | } 117 | 118 | await db.query(sql1+sql).then(async result => { 119 | let res1 = result[0],res2 = result[1],total = 0,list = [] 120 | if(res1 && res1.length >0 && res2 && res2.length >0){ 121 | total = res1[0]['count(1)'] 122 | list = res2 123 | } 124 | ctx.body = { 125 | ...Tips[0], 126 | data: { 127 | list, 128 | pageSize, 129 | total 130 | } 131 | }; 132 | }).catch(e => { 133 | ctx.body = Tips[1002]; 134 | }) 135 | 136 | }); 137 | 138 | module.exports = router; -------------------------------------------------------------------------------- /router/user.js: -------------------------------------------------------------------------------- 1 | const router = require('koa-router')(); 2 | const Utils = require('../utils'); 3 | const Tips = require('../utils/tip'); 4 | const md5 = require('md5'); 5 | const db = require('../db'); 6 | 7 | //登录 8 | router.post('/oa/login', async (ctx, next) => { 9 | let data = Utils.filter(ctx.request.body, ['name', 'password']); 10 | let res = Utils.formatData(data, [ 11 | {key: 'name', type: 'string'}, 12 | {key: 'password', type: 'string'} 13 | ]); 14 | if (! res) return ctx.body = Tips[1007]; 15 | let {name, password} = data; 16 | let sql = 'SELECT uid FROM t_user WHERE name=? and password=? and is_delete=0', value = [name, md5(password)]; 17 | await db.query(sql, value).then(res => { 18 | if (res && res.length > 0) { 19 | let val = res[0]; 20 | let uid = val['uid']; 21 | let token = Utils.generateToken({uid}); 22 | ctx.body = { 23 | ...Tips[0], data: {token} 24 | } 25 | } else { 26 | ctx.body = Tips[1006]; 27 | } 28 | }).catch(e => { 29 | ctx.body = Tips[1002]; 30 | }); 31 | 32 | }); 33 | 34 | //查询登录信息 35 | router.get('/oa/user/auth', async (ctx, next) => { 36 | let {uid} = ctx.state || {}; 37 | let sql = 'SELECT name,uid,nick_name FROM t_user WHERE uid=? AND is_delete=0', value = [uid]; 38 | await db.query(sql, value).then(res => { 39 | if (res && res.length > 0) { 40 | ctx.body = {...Tips[0], data: res[0]}; 41 | } else { 42 | ctx.body = Tips[1005]; 43 | } 44 | }).catch(e => { 45 | ctx.body = Tips[1005]; 46 | }) 47 | }); 48 | //退出登录 49 | router.post('/oa/quit', async (ctx, next) => { 50 | ctx.state = null; 51 | ctx.body = Tips['0'] 52 | 53 | }); 54 | module.exports = router; -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | const Tips = require('./tip'); 2 | const IS = require('is'); 3 | const php_date = require('locutus/php/datetime/date'); 4 | const strtotime = require('locutus/php/datetime/strtotime'); 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | const jwt = require('jsonwebtoken'); 8 | 9 | let util = { 10 | //formatData 必须为 {key,type}的格式,可以不传type 11 | formatData(params, valids) { 12 | let res = true; 13 | if (!IS.object(params)) return false; 14 | if (!IS.array(valids)) return false; 15 | for (let i = 0; i < valids.length; i++) { 16 | let e = valids[i]; 17 | let {key, type} = e; 18 | if (!key) { 19 | res = false; 20 | break; 21 | } 22 | let value = params[key] || ''; 23 | if (type === 'not_empty') { 24 | if (IS.empty(value)) { 25 | res = false; 26 | break; 27 | } 28 | } else if (type === 'number') { 29 | value = Number(value); 30 | if (!IS.number(value) || IS.nan(value)) { 31 | res = false; 32 | break; 33 | } 34 | } else if(type === 'reg'){ 35 | let reg = e['reg']; 36 | if(!reg || !reg.test(value)){ 37 | res = false; 38 | break; 39 | } 40 | }else { 41 | if (!IS[type](value)) { 42 | res = false; 43 | break; 44 | } 45 | } 46 | } 47 | return res; 48 | 49 | 50 | }, 51 | filter(params, filterArr) { 52 | if (IS.object(params) && IS.array(filterArr)) { 53 | let data = {}; 54 | filterArr.forEach(e => { 55 | let val = params[e]; 56 | if (!IS.undefined(val) && !IS.null(val) && !IS.empty(val) || IS.array.empty(val)) { 57 | data[e] = val; 58 | } 59 | }); 60 | return data; 61 | } else { 62 | return params; 63 | } 64 | }, 65 | queryData(params, queryArr) {//仅适用于列 66 | let data = {}; 67 | if (this.type(params) == 'object' && this.type(queryArr) == 'array') { 68 | queryArr.forEach(e => { 69 | let val = params[e]; 70 | if (!!val || val == 0) { 71 | data[e] = params[e]; 72 | } 73 | 74 | }) 75 | 76 | } 77 | return data; 78 | }, 79 | //创建当前时间 80 | formatCurrentTime(create_time) { 81 | let time = create_time ? strtotime(create_time)*1000 : Date.now(); 82 | return php_date('Y-m-d H:i:s', time / 1000); 83 | }, 84 | checkLogin(ctx) { 85 | let uid = ctx.cookies.get('uid'); 86 | if (!uid) { 87 | return Tips[1005]; 88 | } else { 89 | return Tips[0]; 90 | } 91 | }, 92 | generateToken(data){ 93 | let created = Math.floor(Date.now() / 1000); 94 | let cert = fs.readFileSync(path.join(__dirname, '../config/pri.pem')); 95 | let token = jwt.sign({ 96 | data, 97 | exp: created + 3600 * 24 98 | }, cert, {algorithm: 'RS256'}); 99 | return token; 100 | }, 101 | verifyToken(token){ 102 | let cert = fs.readFileSync(path.join(__dirname, '../config/pub.pem')),res = {}; 103 | try{ 104 | let result = jwt.verify(token, cert, {algorithms: ['RS256']}) || {}; 105 | let {exp = 0} = result,current = Math.floor(Date.now()/1000); 106 | if(current <= exp){ 107 | res = result.data || {}; 108 | } 109 | }catch(e){ 110 | 111 | } 112 | return res; 113 | 114 | } 115 | } 116 | 117 | module.exports = util; -------------------------------------------------------------------------------- /utils/tip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 0:{ 3 | code:0, 4 | msg:'ok!' 5 | }, 6 | 1002:{ 7 | code:1002, 8 | msg:'系统繁忙!', 9 | }, 10 | 1003:{ 11 | code:1003, 12 | msg:'暂无数据!', 13 | }, 14 | 1005:{ 15 | code:1005, 16 | msg:'请先登录' 17 | }, 18 | 1006:{ 19 | code:1006, 20 | msg:'账号或密码错误!' 21 | }, 22 | 1007:{ 23 | code:1007, 24 | msg:'参数格式错误' 25 | }, 26 | 1008:{ 27 | code:1008, 28 | msg:'查询失败' 29 | }, 30 | 1009:{ 31 | code:1009, 32 | msg:'账号异常!' 33 | }, 34 | 1010:{ 35 | code:1010, 36 | msg:'网络繁忙,请稍后重试!' 37 | } 38 | } 39 | --------------------------------------------------------------------------------