├── model ├── Live.js ├── Activity.js ├── Advertising.js ├── Area.js ├── Notices.js ├── Log.js ├── ArticleComments.js ├── Tag.js ├── Topic.js ├── Folder.js ├── Carousel.js ├── TagType.js ├── Token.js ├── TechSquare.js ├── TagRelation.js ├── Column.js ├── File.js ├── Question.js ├── DataPerms.js ├── Menu.js ├── Base.js └── Role.js ├── controller ├── Live.js ├── Activity.js ├── Advertising.js ├── Count.js ├── TagRelation.js ├── Notices.js ├── Log.js ├── Charts.js ├── ArticleComments.js ├── Area.js ├── Base.js ├── Draft.js ├── RoleRelation.js ├── Authority.js ├── Question.js ├── Carousel.js ├── TechSquare.js ├── DataPerms.js ├── Menu.js └── Tag.js ├── router ├── activity.js ├── live.js ├── advertising.js ├── token.js ├── count.js ├── charts.js ├── notices.js ├── tagRelation.js ├── log.js ├── area.js ├── draft.js ├── articleComments.js ├── roleRelation.js ├── tag.js ├── file.js ├── topic.js ├── folder.js ├── tagType.js ├── role.js ├── index.js ├── column.js ├── article.js ├── question.js ├── carousel.js ├── techSquare.js ├── dataPerms.js └── menu.js ├── validate ├── Live.js ├── Activity.js ├── Advertising.js ├── Notices.js ├── Base.js ├── TagRelation.js ├── RoleRelation.js ├── Draft.js ├── Log.js ├── Area.js ├── ArticleComments.js ├── Tag.js ├── Topic.js ├── TagType.js ├── File.js ├── Column.js ├── Question.js ├── Article.js ├── Folder.js ├── Carousel.js ├── Role.js ├── TechSquare.js ├── DataPerms.js └── Menu.js ├── exception └── BaseException.js ├── public └── article │ ├── admin_20190611102707_m1r5.md │ ├── admin_20190611102759_b32l.md │ ├── admin_20190611103430_wsfj.md │ ├── admin_20190611103605_4ape.md │ ├── admin_20190611103626_towc.md │ ├── admin_20190611103752_v2wm.md │ ├── admin_20190611103834_sd5r.md │ ├── admin_20190611112403_yb8x.md │ ├── admin_20190611112409_msve.md │ ├── admin_20190611112747_eh56.md │ ├── admin_20190611112757_qjgf.md │ ├── admin_20190611205650_z4lb.md │ ├── admin_20190611205652_ks06.md │ ├── admin_20190626151452_53m3.md │ ├── admin_20190626151453_j70q.md │ ├── test_20190516144154_uw7l.md │ ├── test_20190522093346_nd73.md │ ├── test_20190522093351_plb5.md │ ├── test_20190523135745_bc9y.md │ ├── test_20190523140051_ayvo.md │ ├── test_20190819151530_6b6m.md │ ├── admin_20190611102821_bgfk.md │ ├── admin_20190611102847_qnhn.md │ ├── admin_20190611102920_6ddn.md │ ├── admin_20190611103247_3duv.md │ ├── admin_20190611103316_nkfg.md │ ├── admin_20190611103419_0wqz.md │ ├── admin_20190611103534_svsi.md │ ├── admin_20190611103744_808j.md │ ├── admin_20190611103752_2q21.md │ ├── admin_20190611112400_ki0d.md │ ├── admin_20190611205647_r1nl.md │ ├── test_20190523134346_fvh5.md │ ├── test_20190523134446_ag52.md │ ├── test_20190523135838_xb7n.md │ ├── test_20190523135924_z2vg.md │ ├── test_20190523140118_glo6.md │ ├── test_20190819152114_noax.md │ ├── test_20190523140113_qaok.md │ └── test_20190516145913_bun1.md ├── index.js ├── config ├── default.js └── development.js ├── .babelrc ├── .gitignore ├── mqtt ├── client.js └── server.js ├── redis └── demo.js ├── .github └── FUNDING.yml ├── mysql └── demo.js ├── app.js ├── README.md ├── package.json └── log └── index.js /model/Live.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /controller/Live.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /model/Activity.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /router/activity.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /router/live.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /validate/Live.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /controller/Activity.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /model/Advertising.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /router/advertising.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /validate/Activity.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /validate/Advertising.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /controller/Advertising.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /exception/BaseException.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/article/admin_20190611102707_m1r5.md: -------------------------------------------------------------------------------- 1 | 11122 -------------------------------------------------------------------------------- /public/article/admin_20190611102759_b32l.md: -------------------------------------------------------------------------------- 1 | 11111 -------------------------------------------------------------------------------- /public/article/admin_20190611103430_wsfj.md: -------------------------------------------------------------------------------- 1 | 11111 -------------------------------------------------------------------------------- /public/article/admin_20190611103605_4ape.md: -------------------------------------------------------------------------------- 1 | 11111 -------------------------------------------------------------------------------- /public/article/admin_20190611103626_towc.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/admin_20190611103752_v2wm.md: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /public/article/admin_20190611103834_sd5r.md: -------------------------------------------------------------------------------- 1 | 12 -------------------------------------------------------------------------------- /public/article/admin_20190611112403_yb8x.md: -------------------------------------------------------------------------------- 1 | 11 -------------------------------------------------------------------------------- /public/article/admin_20190611112409_msve.md: -------------------------------------------------------------------------------- 1 | 111 -------------------------------------------------------------------------------- /public/article/admin_20190611112747_eh56.md: -------------------------------------------------------------------------------- 1 | 111 -------------------------------------------------------------------------------- /public/article/admin_20190611112757_qjgf.md: -------------------------------------------------------------------------------- 1 | 111 -------------------------------------------------------------------------------- /public/article/admin_20190611205650_z4lb.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/admin_20190611205652_ks06.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/admin_20190626151452_53m3.md: -------------------------------------------------------------------------------- 1 | 111 -------------------------------------------------------------------------------- /public/article/admin_20190626151453_j70q.md: -------------------------------------------------------------------------------- 1 | 111 -------------------------------------------------------------------------------- /public/article/test_20190516144154_uw7l.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/test_20190522093346_nd73.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/test_20190522093351_plb5.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/test_20190523135745_bc9y.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/test_20190523140051_ayvo.md: -------------------------------------------------------------------------------- 1 | 暂不提供删除 -------------------------------------------------------------------------------- /public/article/test_20190819151530_6b6m.md: -------------------------------------------------------------------------------- 1 | 1111 -------------------------------------------------------------------------------- /public/article/admin_20190611102821_bgfk.md: -------------------------------------------------------------------------------- 1 | 1111111 -------------------------------------------------------------------------------- /public/article/admin_20190611102847_qnhn.md: -------------------------------------------------------------------------------- 1 | 11111111 -------------------------------------------------------------------------------- /public/article/admin_20190611102920_6ddn.md: -------------------------------------------------------------------------------- 1 | 1111111 -------------------------------------------------------------------------------- /public/article/admin_20190611103247_3duv.md: -------------------------------------------------------------------------------- 1 | 11111111 -------------------------------------------------------------------------------- /public/article/admin_20190611103316_nkfg.md: -------------------------------------------------------------------------------- 1 | 1111111 -------------------------------------------------------------------------------- /public/article/admin_20190611103419_0wqz.md: -------------------------------------------------------------------------------- 1 | 111111 -------------------------------------------------------------------------------- /public/article/admin_20190611103534_svsi.md: -------------------------------------------------------------------------------- 1 | 111111 -------------------------------------------------------------------------------- /public/article/admin_20190611103744_808j.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/admin_20190611103752_2q21.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/admin_20190611112400_ki0d.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/admin_20190611205647_r1nl.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/test_20190523134346_fvh5.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/test_20190523134446_ag52.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/test_20190523135838_xb7n.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/test_20190523135924_z2vg.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/test_20190523140118_glo6.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /public/article/test_20190819152114_noax.md: -------------------------------------------------------------------------------- 1 | undefined -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('babel-core/register'); // 让页面可以使用es6语法 2 | require('./app.js'); -------------------------------------------------------------------------------- /public/article/test_20190523140113_qaok.md: -------------------------------------------------------------------------------- 1 | shh社会化和哈哈哈哈哈哈军绿扩军绿绿军扩绿据了解李经理据了解了解了教练教了解连接了交流交流。1 -------------------------------------------------------------------------------- /config/default.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | port: process.env.PORT || 1313 5 | } -------------------------------------------------------------------------------- /config/development.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | port: process.env.PORT || 1313 5 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["stage-3"], 3 | "plugins": [ 4 | "transform-async-to-generator", 5 | "transform-es2015-modules-commonjs", 6 | "transform-export-extensions" 7 | ] 8 | } -------------------------------------------------------------------------------- /router/token.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Authority from '../controller/Authority' 3 | const router = express.Router() 4 | 5 | router.get('/getToken', Authority.getToken) 6 | 7 | export default router -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /log/file 4 | public/apidoc 5 | public/file 6 | /mysql/index.js 7 | /redis/index.js 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Editor directories and files 13 | .idea 14 | .vscode 15 | *.suo 16 | *.ntvs* 17 | *.njsproj 18 | *.sln 19 | -------------------------------------------------------------------------------- /mqtt/client.js: -------------------------------------------------------------------------------- 1 | import mqtt from 'mqtt' 2 | 3 | const client = mqtt.connect('mqtt://127.0.0.1:1883') // 客户端,用来做转发 4 | 5 | // 连接 6 | client.on('connect', () => { 7 | console.log('连接' + new Date()) 8 | }) 9 | 10 | client.on('close', () => { 11 | console.log('close重新连接' + new Date()) 12 | }) 13 | 14 | // 将数据转发到当前mqtt服务 15 | // client.publish('/11123', '111111') 16 | 17 | export default client 18 | -------------------------------------------------------------------------------- /validate/Notices.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Notices extends Base{ 4 | constructor () { 5 | super() 6 | this.setNotices = this.setNotices.bind(this) 7 | this.getNotices = this.getNotices.bind(this) 8 | } 9 | async setNotices (req, res, next) { 10 | next() 11 | } 12 | async getNotices (req, res, next) { 13 | next() 14 | } 15 | } 16 | 17 | export default new Notices() 18 | -------------------------------------------------------------------------------- /redis/demo.js: -------------------------------------------------------------------------------- 1 | import redis from 'redis' 2 | 3 | const client = redis.createClient(6379, '127.0.0.1') 4 | client.auth('redis') 5 | client.on('connect', () => { 6 | console.log( 'redis连接成功:' + new Date()) 7 | }) 8 | client.on('reconnecting', () => { 9 | console.log('redis重新连接:' + new Date()) 10 | }) 11 | client.on('error', function (err) { 12 | console.log('Error ' + err) 13 | }) 14 | 15 | export default client 16 | -------------------------------------------------------------------------------- /validate/Base.js: -------------------------------------------------------------------------------- 1 | import validate from '../lib/js/validate' 2 | 3 | class Base{ 4 | check (arr) { 5 | let success = true, message 6 | for (let item of arr) { 7 | if (!validate(item).success) { 8 | message = validate(item).message 9 | success = false 10 | return {success, message} 11 | } 12 | } 13 | return {success, message} 14 | } 15 | } 16 | 17 | export default Base 18 | -------------------------------------------------------------------------------- /validate/TagRelation.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class TagRelation extends Base{ 4 | constructor () { 5 | super() 6 | this.setBindTag = this.setBindTag.bind(this) 7 | this.getBindTag = this.getBindTag.bind(this) 8 | } 9 | async setBindTag (req, res, next) { 10 | next() 11 | } 12 | async getBindTag (req, res, next) { 13 | next() 14 | } 15 | } 16 | 17 | export default new TagRelation() 18 | -------------------------------------------------------------------------------- /mqtt/server.js: -------------------------------------------------------------------------------- 1 | import mosca from 'mosca' 2 | 3 | function mqttServer() { 4 | const settings = { 5 | port: 1883, 6 | http: { 7 | port: 1212, 8 | bundle: true, 9 | static: './' 10 | }, 11 | backend: {} 12 | }; 13 | const server = new mosca.Server(settings) 14 | 15 | 16 | //监听链接 17 | server.on("clientConnected", (client) => { 18 | console.log("client connected",client.id) 19 | }) 20 | } 21 | 22 | export default mqttServer 23 | -------------------------------------------------------------------------------- /router/count.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Count from '../controller/Count' 3 | 4 | const router = express.Router() 5 | 6 | /** 7 | * 平台相关数据统计 8 | * @api {POST} /api/Count/platformData 平台相关数据统计 9 | * @apiDescription 平台相关数据统计 10 | * @apiName platformData 11 | * @apiHeader {String} Authorization token 12 | * @apiSampleRequest /api/Count/platformData 13 | * @apiGroup Count 14 | * @apiVersion 0.0.1 15 | */ 16 | router.get('/platformDataCount', Count.platformDataCount) 17 | 18 | export default router 19 | -------------------------------------------------------------------------------- /router/charts.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Charts from '../controller/Charts' 3 | 4 | const router = express.Router() 5 | 6 | /** 7 | * 用户登陆分析 8 | * @api {POST} /api/Charts/userLoginAnalyze 用户登陆分析 9 | * @apiDescription 用户登陆分析 10 | * @apiName userLoginAnalyze 11 | * @apiHeader {String} Authorization token 12 | * @apiSampleRequest /api/Charts/userLoginAnalyze 13 | * @apiGroup Charts 14 | * @apiVersion 0.0.1 15 | */ 16 | router.get('/userLoginAnalyze', Charts.userLoginAnalyze) 17 | 18 | export default router 19 | -------------------------------------------------------------------------------- /validate/RoleRelation.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class RoleRelation extends Base{ 4 | constructor () { 5 | super() 6 | this.setPermissions = this.setPermissions.bind(this) 7 | this.getPermissions = this.getPermissions.bind(this) 8 | this.setBindUser = this.setBindUser.bind(this) 9 | this.getBindUser = this.getBindUser.bind(this) 10 | } 11 | async setPermissions (req, res, next) { 12 | next() 13 | } 14 | async getPermissions (req, res, next) { 15 | next() 16 | } 17 | async setBindUser (req, res, next) { 18 | next() 19 | } 20 | async getBindUser (req, res, next) { 21 | next() 22 | } 23 | } 24 | 25 | export default new RoleRelation() 26 | -------------------------------------------------------------------------------- /validate/Draft.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Draft extends Base{ 4 | constructor () { 5 | super() 6 | this.giveUp = this.giveUp.bind(this) 7 | } 8 | async giveUp (req, res, next) { 9 | const params = req.body, 10 | arr = [ 11 | {label: 'id', value: params.id, rules: ['notnull', 'number']}, 12 | {label: '数据类型', value: params.dataType, rules: ['notnull', 'number']} 13 | ], 14 | result = this.check(arr) 15 | if (!result.success) { 16 | res.json({ 17 | code: 20301, 18 | success: false, 19 | message: result.message 20 | }) 21 | return 22 | } 23 | next() 24 | } 25 | } 26 | 27 | export default new Draft() 28 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /router/notices.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Notices from '../controller/Notices' 3 | import ValidateNotices from '../validate/Notices' 4 | const router = express.Router() 5 | 6 | /** 7 | * 设置 8 | * @api {POST} /api/Notices/set 设置 9 | * @apiDescription 设置通知 10 | * @apiName set 11 | * @apiHeader {String} Authorization token 12 | * @apiSampleRequest /api/Notices/set 13 | * @apiGroup Notices 14 | * @apiVersion 0.0.1 15 | */ 16 | router.post('/set', ValidateNotices.setNotices, Notices.setNotices) 17 | /** 18 | * 获取 19 | * @api {POST} /api/Notices/get 获取 20 | * @apiDescription 获取通知 21 | * @apiName get 22 | * @apiHeader {String} Authorization token 23 | * @apiSampleRequest /api/Notices/get 24 | * @apiGroup Notices 25 | * @apiVersion 0.0.1 26 | */ 27 | router.get('/get', ValidateNotices.getNotices, Notices.getNotices) 28 | 29 | export default router 30 | -------------------------------------------------------------------------------- /router/tagRelation.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import TagRelation from '../controller/TagRelation' 3 | import ValidateTagRelation from '../validate/TagRelation' 4 | const router = express.Router() 5 | 6 | /** 7 | * 设置绑定标签 8 | * @api {POST} /api/TagRelation/setBindTag 设置绑定标签 9 | * @apiDescription 设置绑定标签 10 | * @apiName setBindTag 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Object} Object 13 | * @apiSampleRequest /api/TagRelation/setBindTag 14 | * @apiGroup TagRelation 15 | * @apiVersion 0.0.1 16 | */ 17 | router.post('/setBindTag', ValidateTagRelation.setBindTag, TagRelation.setBindTag) 18 | /** 19 | * 获取绑定标签 20 | * @api {put} /api/TagRelation/getBindTag 获取绑定标签 21 | * @apiDescription 获取绑定标签 22 | * @apiName getBindTag 23 | * @apiHeader {String} Authorization token 24 | * @apiSampleRequest /api/TagRelation/getBindTag 25 | * @apiGroup TagRelation 26 | * @apiVersion 0.0.1 27 | */ 28 | router.get('/getBindTag', ValidateTagRelation.getBindTag, TagRelation.getBindTag) 29 | 30 | export default router 31 | -------------------------------------------------------------------------------- /controller/Count.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import QuestionModel from '../model/Question' 3 | import ArticleModel from '../model/Article' 4 | import ColumnModel from '../model/Column' 5 | import UserModel from '../model/User' 6 | 7 | class Count extends Base { 8 | constructor () { 9 | super() 10 | } 11 | // 平台相关数据统计 12 | async platformDataCount (req, res, next) { 13 | let params = {flag: 1}, result 14 | try { 15 | result = { 16 | questions: (await QuestionModel.getTotals({get: params}))[0].count, 17 | articles: (await ArticleModel.getTotals({get: {...params, flag: 3}}))[0].count, 18 | columns: (await ColumnModel.getTotals({get: params}))[0].count, 19 | users: (await UserModel.getTotals({get: {...params, create_user: 1}}))[0].count + 1 20 | } 21 | } catch (e) { 22 | this.handleException(req, res, e) 23 | return 24 | } 25 | res.json({ 26 | code: 20000, 27 | success: true, 28 | content: result, 29 | message: '操作成功' 30 | }) 31 | } 32 | } 33 | 34 | export default new Count() 35 | -------------------------------------------------------------------------------- /mysql/demo.js: -------------------------------------------------------------------------------- 1 | import mysql from 'mysql' 2 | import NodeLog from '../log/index' 3 | var pool = mysql.createPool({ 4 | host : 'host', 5 | user : 'user', 6 | password : 'password', 7 | port: '3306', 8 | database : 'LLLyh_BBS' 9 | }); 10 | function query (sql) { 11 | // 写入sql 12 | NodeLog.writeLog(`\n运行sql时间${new Date()}: \n${sql}`, 'sql') 13 | return new Promise((resolve, reject) => { 14 | pool.getConnection((err, conn) => { 15 | if (err) { 16 | // 如果是连接断开,自动重新连接 17 | if (err.code === 'PROTOCOL_CONNECTION_LOST') { 18 | setTimeout(query(), 2000); 19 | reject('断开重连'); 20 | } else { 21 | console.error(err.stack || err); 22 | reject(err); 23 | } 24 | } else { 25 | // 得到结果 26 | conn.query(sql, (queryErr, result) => { 27 | if (queryErr) { 28 | reject(queryErr); 29 | } else { 30 | resolve(result); 31 | } 32 | // 释放连接 33 | conn.release(); 34 | }) 35 | } 36 | }) 37 | }) 38 | } 39 | export default query 40 | -------------------------------------------------------------------------------- /model/Area.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Area extends Base{ 5 | constructor () { 6 | super() 7 | this.update = this.update.bind(this) 8 | this.getList = this.getList.bind(this) 9 | this.getTotals = this.getTotals.bind(this) 10 | this.getAll = this.getAll.bind(this) 11 | } 12 | async update (obj) { 13 | let sql = `UPDATE bbs_area set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 14 | return query(sql) 15 | } 16 | async getList (obj) { 17 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 18 | let sql = `select * from bbs_area where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 19 | return query(sql) 20 | } 21 | async getTotals (obj) { 22 | let sql = `select COUNT(*) as count from bbs_area where 1 = 1 ${this.joinStr('get', obj.get)};` 23 | return query(sql) 24 | } 25 | async getAll (obj) { 26 | let sql = `select * from bbs_area where 1 = 1 ${this.joinStr('get', obj.get)};` 27 | return query(sql) 28 | } 29 | } 30 | 31 | export default new Area() 32 | -------------------------------------------------------------------------------- /model/Notices.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Notices extends Base{ 5 | constructor () { 6 | super() 7 | this.setNotices = this.setNotices.bind(this) 8 | this.getNotices = this.getNotices.bind(this) 9 | } 10 | async setNotices (obj) { 11 | const setData = { 12 | status: 0, 13 | update_user: obj.set.create_user, 14 | update_time: new Date() 15 | } 16 | // 将当前所有数据状态置为0 17 | const sql1 = `UPDATE bbs_notices set ${this.joinStr('set', setData)} where 1 = 1 ${this.joinStr('get', obj.get)};` 18 | // 添加新数据 19 | const sql2 = `INSERT INTO bbs_notices set ${this.joinStr('set', obj.set)};` 20 | // 事务开始 21 | await query('begin;') 22 | const result1 = await query(sql1) 23 | const result2 = await query(sql2) 24 | if (result1.affectedRows >= 0 && result2.affectedRows) { 25 | // 事务提交 26 | await query('commit;') 27 | } else { 28 | // 事务回滚 29 | await query('rollback;') 30 | } 31 | return result1.affectedRows >= 0 && result2.affectedRows 32 | } 33 | async getNotices (obj) { 34 | let sql = `select * from bbs_notices where 1 = 1 ${this.joinStr('get', obj.get)};` 35 | return query(sql) 36 | } 37 | } 38 | 39 | export default new Notices() 40 | -------------------------------------------------------------------------------- /validate/Log.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Log extends Base{ 4 | constructor () { 5 | super() 6 | this.writeLog = this.writeLog.bind(this) 7 | this.getList = this.getList.bind(this) 8 | } 9 | async writeLog (req, res, next) { 10 | const params = req.body, 11 | arr = [ 12 | {label: '日志来源', value: params.origin, rules: ['notnull']}, 13 | {label: '日志类型', value: params.type, rules: ['notnull']} 14 | ], 15 | result = this.check(arr) 16 | if (!result.success) { 17 | res.json({ 18 | code: 20301, 19 | success: false, 20 | message: result.message 21 | }) 22 | return 23 | } 24 | next() 25 | } 26 | async getList (req, res, next) { 27 | const data = req.query, 28 | arr = [ 29 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 30 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 31 | ], 32 | result = this.check(arr) 33 | if (!result.success) { 34 | res.json({ 35 | code: 20301, 36 | success: false, 37 | message: result.message 38 | }) 39 | return 40 | } 41 | next() 42 | } 43 | } 44 | 45 | export default new Log() 46 | -------------------------------------------------------------------------------- /router/log.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Log from '../controller/Log' 3 | import ValidateLog from '../validate/Log' 4 | const router = express.Router() 5 | 6 | /** 7 | * 写日志 8 | * @api {POST} /api/log/registered 写日志 9 | * @apiDescription 写日志 10 | * @apiName registered 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} origin 日志来源:0: 手机 1: 论坛 2: 管理平台 13 | * @apiParam (参数) {Number} type 日志类型: 1.用户登录 2. 用户登出 3. 模块访问 4.功能操作 14 | * @apiParam (参数) {String} title 日志标题 15 | * @apiParam (参数) {String} desc 日志描述 16 | * @apiParam (参数) {String} ip ip 17 | * @apiSampleRequest /api/log/registered 18 | * @apiGroup Log 19 | * @apiVersion 0.0.1 20 | */ 21 | router.post('/writeLog', ValidateLog.writeLog, Log.writeLog) 22 | /** 23 | * 获取日志列表 24 | * @api {get} /api/log/getList 获取日志列表 25 | * @apiDescription 获取日志列表 26 | * @apiName getList 27 | * @apiHeader {String} Authorization token 28 | * @apiParam (path参数) {Number} curPage 29 | * @apiParam (path参数) {Number} pageSize 30 | * @apiParam (path参数) {Number} origin 日志来源:0: 手机 1: 论坛 2: 管理平台 31 | * @apiParam (path参数) {Number} type 日志类型: 1.用户登录 2. 用户登出 3. 模块访问 4.功能操作 32 | * @apiSampleRequest /api/log/getList 33 | * @apiGroup Log 34 | * @apiVersion 0.0.1 35 | */ 36 | router.get('/getList', ValidateLog.getList, Log.getList) 37 | 38 | export default router -------------------------------------------------------------------------------- /router/area.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Area from '../controller/Area' 3 | import ValidateArea from '../validate/Area' 4 | const router = express.Router() 5 | 6 | /** 7 | * 编辑 8 | * @api {POST} /api/Area/update 编辑 9 | * @apiDescription 编辑 10 | * @apiName update 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} status 13 | * @apiSampleRequest /api/Area/update 14 | * @apiGroup Area 15 | * @apiVersion 0.0.1 16 | */ 17 | router.put('/update', ValidateArea.update, Area.update) 18 | /** 19 | * 获取区域列表 20 | * @api {get} /api/Area/getList 获取日志列表 21 | * @apiDescription 获取日志列表 22 | * @apiName getList 23 | * @apiHeader {String} Authorization token 24 | * @apiParam (path参数) {Number} curPage 25 | * @apiParam (path参数) {Number} pageSize 26 | * @apiParam (path参数) {Number} pid 27 | * @apiSampleRequest /api/Area/getList 28 | * @apiGroup Area 29 | * @apiVersion 0.0.1 30 | */ 31 | router.get('/getList', ValidateArea.getList, Area.getList) 32 | /** 33 | * 获取所有区域 34 | * @api {get} /api/Area/getAll/:pid 获取所有区域 35 | * @apiDescription 获取所有区域 36 | * @apiName getAll 37 | * @apiHeader {String} Authorization token 38 | * @apiParam {Number} pid 39 | * @apiSampleRequest /api/Area/getAll 40 | * @apiGroup Area 41 | * @apiVersion 0.0.1 42 | */ 43 | router.get('/getAll/:pid', ValidateArea.getAll, Area.getAll) 44 | 45 | export default router -------------------------------------------------------------------------------- /model/Log.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Log extends Base{ 5 | constructor () { 6 | super() 7 | this.writeLog = this.writeLog.bind(this) 8 | this.getList = this.getList.bind(this) 9 | this.getTotals = this.getTotals.bind(this) 10 | this.getLoginLog = this.getLoginLog.bind(this) 11 | } 12 | async writeLog (obj) { 13 | let sql = `INSERT INTO bbs_log set ${this.joinStr('set', obj.set)}` 14 | return query(sql) 15 | } 16 | async getList (obj) { 17 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 18 | let sql = `select a.*, b.name as create_user_name from bbs_log as a 19 | LEFT JOIN bbs_user as b ON a.create_user = b.id 20 | where 1 = 1 ${this.joinStr('get', obj.get)} ${this.joinStr('ORDER BY', {DESC: ['create_time', 'id']})} limit ${(curPage - 1) * pageSize}, ${pageSize};` 21 | // 处理表连接字段 22 | sql = sql.replace(/`type`/, 'a.type') 23 | return query(sql) 24 | } 25 | async getTotals (obj) { 26 | let sql = `select COUNT(*) as count from bbs_log where 1 = 1 ${this.joinStr('get', obj.get)};` 27 | return query(sql) 28 | } 29 | async getLoginLog (obj) { 30 | let sql = `select create_time as time from bbs_log where 1 = 1 ${this.joinStr('get', obj.get)};` 31 | return query(sql) 32 | } 33 | } 34 | 35 | export default new Log() 36 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import path from 'path' 3 | import router from './router' 4 | import bodyParser from 'body-parser' 5 | import config from 'config-lite' // 配置中间件 6 | import history from 'connect-history-api-fallback' 7 | import chalk from 'chalk' 8 | import mqttServer from './mqtt/server' // mqtt服务端 9 | import redis from './redis' 10 | 11 | mqttServer() 12 | const app = express() 13 | app.disable('etag') // 禁止304缓存 14 | app.all('*', (req, res, next) => { 15 | res.header("Access-Control-Allow-Origin", req.headers.origin || req.headers.referer || '*') 16 | res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With") 17 | res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS") 18 | res.header("Access-Control-Allow-Credentials", true) // 可以带cookies 19 | res.header("Access-Control-Max-Age", -1) // 禁止缓存 20 | res.header("X-Powered-By", 'Express') 21 | if (req.method === 'OPTIONS') { 22 | res.sendStatus(200) 23 | } else { 24 | next() 25 | } 26 | }) 27 | 28 | // const server = http.createServer(app) 29 | // const io = require('socket.io')(server) 30 | // new SocketServer(io) 31 | 32 | // 解析body参数 33 | app.use(bodyParser.json()) 34 | app.use(bodyParser.urlencoded({extended: false})) 35 | router(app) 36 | app.use(history()) 37 | app.use(express.static(path.join(__dirname, 'public'))) 38 | app.listen(config.port || '1313', () => { 39 | console.log( 40 | chalk.green(`成功监听端口${config.port || 1313}`) 41 | ) 42 | }) 43 | -------------------------------------------------------------------------------- /router/draft.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Draft from '../controller/Draft' 3 | import ValidateDraft from '../validate/Draft' 4 | const router = express.Router() 5 | 6 | /** 7 | * 获取草稿数量 8 | * @api {get} /api/Draft/getTotals 获取草稿数量 9 | * @apiDescription 获取草稿数量 10 | * @apiName getTotals 11 | * @apiHeader {String} Authorization token 12 | * @apiSampleRequest /api/Draft/getTotals 13 | * @apiGroup Draft 14 | * @apiVersion 0.0.1 15 | */ 16 | router.get('/getTotals', Draft.getTotals) 17 | /** 18 | * 获取草稿 19 | * @api {get} /api/Draft/getAll 获取草稿 20 | * @apiDescription 获取草稿 21 | * @apiName getAll 22 | * @apiHeader {String} Authorization token 23 | * @apiSampleRequest /api/Draft/getAll 24 | * @apiGroup Draft 25 | * @apiVersion 0.0.1 26 | */ 27 | router.get('/getAll', Draft.getAll) 28 | /** 29 | * 舍弃草稿 30 | * @api {delete} /api/Draft/giveUp 舍弃草稿 31 | * @apiDescription 舍弃草稿 32 | * @apiName giveUp 33 | * @apiHeader {String} Authorization token 34 | * @apiSampleRequest /api/Draft/giveUp 35 | * @apiGroup Draft 36 | * @apiVersion 0.0.1 37 | */ 38 | router.delete('/giveUp', ValidateDraft.giveUp, Draft.giveUp) 39 | /** 40 | * 舍弃全部草稿 41 | * @api {delete} /api/Draft/giveUpAll 舍弃全部草稿 42 | * @apiDescription 舍弃全部草稿 43 | * @apiName giveUpAll 44 | * @apiHeader {String} Authorization token 45 | * @apiSampleRequest /api/Draft/giveUpAll 46 | * @apiGroup Draft 47 | * @apiVersion 0.0.1 48 | */ 49 | router.delete('/giveUpAll', Draft.giveUpAll) 50 | 51 | export default router 52 | -------------------------------------------------------------------------------- /router/articleComments.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import ArticleComments from '../controller/ArticleComments' 3 | import ValidateArticleComments from '../validate/ArticleComments' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/ArticleComments/create 创建 9 | * @apiDescription 创建评论 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} article_id 文章ID 13 | * @apiParam (参数) {Number} pid 父节点,默认为0 14 | * @apiParam (参数) {String} content 内容 15 | * @apiSampleRequest /api/ArticleComments/create 16 | * @apiGroup Article 17 | * @apiVersion 0.0.1 18 | */ 19 | router.post('/create', ValidateArticleComments.create, ArticleComments.create) 20 | 21 | /** 22 | * 删除 23 | * @api {delete} /api/ArticleComments/delete/:id 删除 24 | * @apiDescription 删除 25 | * @apiName delete 26 | * @apiHeader {String} Authorization token 27 | * @apiParam {Number} id 28 | * @apiSampleRequest /api/ArticleComments/delete 29 | * @apiGroup Article 30 | * @apiVersion 0.0.1 31 | */ 32 | router.delete('/delete/:id', ValidateArticleComments.delete, ArticleComments.delete) 33 | 34 | /** 35 | * 获取所有评论 36 | * @api {get} /api/ArticleComments/getAll 获取所有评论 37 | * @apiDescription 获取所有评论 38 | * @apiName getAll 39 | * @apiParam {Number} type 40 | * @apiHeader {String} Authorization token 41 | * @apiSampleRequest /api/ArticleComments/getAll 42 | * @apiGroup Article 43 | * @apiVersion 0.0.1 44 | */ 45 | router.get('/getAll', ValidateArticleComments.getAll, ArticleComments.getAll) 46 | 47 | export default router 48 | -------------------------------------------------------------------------------- /controller/TagRelation.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import TagRelationModel from '../model/TagRelation' 3 | 4 | 5 | class TagRelation extends Base { 6 | constructor () { 7 | super() 8 | this.setBindTag = this.setBindTag.bind(this) 9 | this.getBindTag = this.getBindTag.bind(this) 10 | } 11 | // 设置标签类型绑定的标签 12 | async setBindTag (req, res, next) { 13 | let userInfo = await this.getUserInfo(req), result, 14 | data = req.body 15 | try { 16 | result = await TagRelationModel.setBindTag({ 17 | get: {tag_type_id: data.tagTypeId}, 18 | data: { 19 | tags: data.tags 20 | } 21 | }) 22 | } catch (e) { 23 | this.handleException(req, res, e) 24 | return 25 | } 26 | if (result) { 27 | res.json({ 28 | code: 20000, 29 | success: true, 30 | content: {}, 31 | message: '操作成功' 32 | }) 33 | } else { 34 | res.json({ 35 | code: 20001, 36 | success: false, 37 | content: {}, 38 | message: '操作失败' 39 | }) 40 | } 41 | } 42 | // 获取标签类型绑定的标签 43 | async getBindTag (req, res, next) { 44 | let tag_type_id = req.query.tagTypeId, result 45 | try { 46 | result = await TagRelationModel.getBindTag({get: {tag_type_id}}) 47 | } catch (e) { 48 | this.handleException(req, res, e) 49 | return 50 | } 51 | res.json({ 52 | code: 20000, 53 | success: true, 54 | content: result, 55 | message: '操作成功' 56 | }) 57 | } 58 | } 59 | 60 | export default new TagRelation() 61 | -------------------------------------------------------------------------------- /model/ArticleComments.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class ArticleComments extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getTotals = this.getTotals.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (obj) { 14 | let sql = `INSERT INTO bbs_article_comments set ${this.joinStr('set', obj.set)};` 15 | return query(sql) 16 | } 17 | async update (obj) { 18 | let sql = `UPDATE bbs_article_comments set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 19 | return query(sql) 20 | } 21 | async delete (obj) { 22 | let sql = `DELETE from bbs_article_comments where 1 = 1 ${this.joinStr('get', obj.get)};` 23 | return query(sql) 24 | } 25 | async getTotals (obj) { 26 | let sql = `select COUNT(*) as count from bbs_article_comments where 1 = 1 ${this.joinStr('get', obj.get)}` 27 | return query(sql) 28 | } 29 | async getAll (obj) { 30 | let sql = `select a.*, b.name as replier_name, b.avatar, c.name as by_replier_name from bbs_article_comments as a 31 | left join bbs_user as b on a.create_user = b.id 32 | left join bbs_user as c on a.p_user_id = c.id 33 | where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY create_time DESC` 34 | // 处理表连接字段 35 | // sql = sql.replace(/`id`/, 'a.id') 36 | sql = sql.replace(/`flag`/, 'a.flag') 37 | return query(sql) 38 | } 39 | } 40 | 41 | export default new ArticleComments() 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## start 2 | 1. 将mysql目录下的demo.js改成index.js, 并设置好相关的数据库连接信息 3 | 2. 在mysql中导入LLLyh_BBS.sql 4 | 33. 将redis目录下的demo.js改成index.js, 并设置好相关的redis连接信息 5 | 6 | ## Build Setup 7 | ``` bash 8 | # 安装依赖 9 | npm install 10 | 11 | # 运行项目 12 | npm run dev 13 | 14 | # 运行node服务 15 | npm run dev 16 | 17 | # 使用热更新打开node服务,方便边开发边调试 (调试时用Debug) 18 | npm run hot 19 | 20 | # 更新接口后使用此命令重新生成api相关文档 21 | npm run apidoc 22 | 23 | # 使用forever 实现在服务器上关闭控制台时node服务正常访问 24 | npm run start # 启用node服务 25 | npm run stop # 关闭node服务 26 | 27 | # 项目基本结构 28 | ├── config // 配置相关 29 | ├── controller // 控制器 30 | ├── model // model 31 | ├── mysql // mysql配置文件 32 | ├── node_modules // 项目依赖 33 | ├── public // 静态资源库 34 | ├── routes // 路由 35 | ├── .babelrc // babel-loader 配置 36 | ├── eslintrc.js // eslint 配置项 37 | ├── .gitignore // git 忽略项 38 | ├── app.js // 入口 加载配置 初始化 39 | ├── index.js // 启动文件 40 | └── package.json // package.json 41 | ``` 42 | 43 | # 返回的数据格式 44 | ``` 45 | { 46 | success: true, // 响应状态 47 | code: 20000, // 状态码 48 | content: {}, // 数据 49 | message: '操作成功' // 提示 50 | } 51 | ``` 52 | # 返回码和相关提示定义 53 | 1 为账号错误 54 | 2 为认证错误 55 | 3 为参数错误 56 | 4 为数据不存在 57 | 5 为系统错误 58 | 0 为成功 59 | 60 | |状态码|定义| 61 | |:----|:---| 62 | |20101|当前被登出| 63 | |20201|身份认证失败| 64 | |20202|无操作权限| 65 | |20203|用户未绑定角色| 66 | |20301|参数错误| 67 | |20401|数据不存在| 68 | |20501|服务器内部错误| 69 | |20000|操作成功| 70 | |20001|操作失败| 71 | -------------------------------------------------------------------------------- /controller/Notices.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import NoticesModel from '../model/Notices' 3 | 4 | class Notices extends Base { 5 | constructor () { 6 | super() 7 | this.setNotices = this.setNotices.bind(this) 8 | this.getNotices = this.getNotices.bind(this) 9 | } 10 | // 设置通知 11 | async setNotices (req, res, next) { 12 | let data = JSON.parse(JSON.stringify(req.body)), 13 | result, 14 | userInfo = await this.getUserInfo(req) 15 | // 参数处理 16 | data.create_user = userInfo.id 17 | data.create_time = new Date() 18 | delete data.id 19 | try { 20 | result = await NoticesModel.setNotices({set: data, get: {status: 1}}) 21 | } catch (e) { 22 | this.handleException(req, res, e) 23 | return 24 | } 25 | if (result) { 26 | res.json({ 27 | code: 20000, 28 | success: true, 29 | message: '操作成功' 30 | }) 31 | } else { 32 | res.json({ 33 | code: 20001, 34 | success: false, 35 | message: '操作失败' 36 | }) 37 | } 38 | } 39 | // 获取通知 40 | async getNotices (req, res, next) { 41 | const search = await NoticesModel.getNotices({get: {status: 1, flag: 1}}) 42 | if (search.length === 0) { 43 | res.json({ 44 | code: 20401, 45 | success: false, 46 | content: search, 47 | message: '查询信息不存在' 48 | }) 49 | } else { 50 | res.json({ 51 | code: 20000, 52 | success: true, 53 | content: search, 54 | message: '操作成功' 55 | }) 56 | } 57 | } 58 | } 59 | 60 | export default new Notices() 61 | -------------------------------------------------------------------------------- /model/Tag.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Tag extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_tag set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_tag set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_tag where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_tag where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_tag 34 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_tag where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select * from bbs_tag where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 43 | return query(sql) 44 | } 45 | } 46 | 47 | export default new Tag() 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node_BBS", 3 | "version": "0.0.1", 4 | "description": "BBSapi", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "cross-env NODE_ENV=development PORT=1313 node index.js", 8 | "start": "forever start index.js", 9 | "stop": "forever stop index.js", 10 | "hot": "supervisor index.js", 11 | "apidoc": "apidoc -i router/ -o public/apidoc", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "author": "ly", 15 | "license": "ISC", 16 | "dependencies": { 17 | "babel": "6.23.0", 18 | "babel-core": "6.24.0", 19 | "babel-preset-es2015": "6.24.0", 20 | "babel-preset-stage-3": "6.22.0", 21 | "babel-register": "6.24.0", 22 | "body-parser": "1.18.3", 23 | "chalk": "2.4.1", 24 | "config-lite": "2.1.0", 25 | "connect-history-api-fallback": "1.5.0", 26 | "cookie-parser": "1.4.3", 27 | "cross-env": "5.2.0", 28 | "crypto": "1.0.1", 29 | "express": "4.16.4", 30 | "express-winston": "3.0.1", 31 | "jsonwebtoken": "8.4.0", 32 | "log4js": "4.3.1", 33 | "mysql": "2.16.0", 34 | "supervisor": "0.12.0", 35 | "apidoc": "0.17.7", 36 | "request": "2.88.0", 37 | "connect-multiparty": "2.2.0", 38 | "mqtt": "2.18.8", 39 | "mosca": "2.8.3", 40 | "node-schedule": "1.3.2", 41 | "redis": "2.8.0" 42 | }, 43 | "devDependencies": { 44 | "babel-plugin-transform-async-to-generator": "6.24.1", 45 | "babel-plugin-transform-es2015-classes": "6.24.1", 46 | "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", 47 | "babel-plugin-transform-export-extensions": "6.22.0" 48 | }, 49 | "apidoc": { 50 | "title": "BBS接口文档", 51 | "url": "http://localhost:1313" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /model/Topic.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Topic extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_topic set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_topic set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_topic where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_topic where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_topic 34 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_topic where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select * from bbs_topic where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 43 | return query(sql) 44 | } 45 | } 46 | 47 | export default new Topic() 48 | -------------------------------------------------------------------------------- /model/Folder.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Folder extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_folder set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_folder set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_folder where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_folder where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_folder 34 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_folder where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select * from bbs_folder where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 43 | return query(sql) 44 | } 45 | } 46 | 47 | export default new Folder() 48 | -------------------------------------------------------------------------------- /model/Carousel.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Carousel extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_carousel set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_carousel set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_carousel where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_carousel where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_carousel 34 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_carousel where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select * from bbs_carousel where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 43 | return query(sql) 44 | } 45 | } 46 | 47 | export default new Carousel() 48 | -------------------------------------------------------------------------------- /model/TagType.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class TagType extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_tag_type set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_tag_type set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_tag_type where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_tag_type where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_tag_type 34 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_tag_type where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select * from bbs_tag_type where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 43 | return query(sql) 44 | } 45 | } 46 | 47 | export default new TagType() 48 | -------------------------------------------------------------------------------- /validate/Area.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Area extends Base{ 4 | constructor () { 5 | super() 6 | this.update = this.update.bind(this) 7 | this.getList = this.getList.bind(this) 8 | this.getAll = this.getAll.bind(this) 9 | } 10 | async update (req, res, next) { 11 | const params = req.body, 12 | arr = [ 13 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 14 | ], 15 | result = this.check(arr) 16 | if (!result.success) { 17 | res.json({ 18 | code: 20301, 19 | success: false, 20 | message: result.message 21 | }) 22 | return 23 | } 24 | next() 25 | } 26 | async getList (req, res, next) { 27 | const data = req.query, 28 | arr = [ 29 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 30 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']}, 31 | {label: '父级ID', value: data.pid, rules: ['notnull', 'number']} 32 | ], 33 | result = this.check(arr) 34 | if (!result.success) { 35 | res.json({ 36 | code: 20301, 37 | success: false, 38 | message: result.message 39 | }) 40 | return 41 | } 42 | next() 43 | } 44 | async getAll (req, res, next) { 45 | const data = req.params, 46 | arr = [ 47 | {label: 'pid', value: data.pid, rules: ['notnull', 'number']} 48 | ], 49 | result = this.check(arr) 50 | if (!result.success) { 51 | res.json({ 52 | code: 20301, 53 | success: false, 54 | message: result.message 55 | }) 56 | return 57 | } 58 | next() 59 | } 60 | } 61 | 62 | export default new Area() 63 | -------------------------------------------------------------------------------- /validate/ArticleComments.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class ArticleComments extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.delete = this.delete.bind(this) 8 | this.getAll = this.getAll.bind(this) 9 | } 10 | async create (req, res, next) { 11 | const params = req.body, 12 | arr = [ 13 | {label: '文章ID', value: params.article_id, rules: ['notnull']}, 14 | {label: 'pid', value: params.pid, rules: ['notnull']}, 15 | {label: 'p_user_id', value: params.p_user_id, rules: ['notnull']}, 16 | {label: '内容', value: params.content, rules: ['notnull']} 17 | ], 18 | result = this.check(arr) 19 | if (!result.success) { 20 | res.json({ 21 | code: 20301, 22 | success: false, 23 | message: result.message 24 | }) 25 | return 26 | } 27 | next() 28 | } 29 | async delete (req, res, next) { 30 | const ID = req.params.id, 31 | arr = [ 32 | {label: 'ID', value: ID, rules: ['notnull']} 33 | ], 34 | result = this.check(arr) 35 | if (!result.success) { 36 | res.json({ 37 | code: 20301, 38 | success: false, 39 | message: result.message 40 | }) 41 | return 42 | } 43 | next() 44 | } 45 | async getAll (req, res, next) { 46 | const query = req.query, 47 | arr = [ 48 | {label: '文章ID', value: query.article_id, rules: ['notnull']}, 49 | // {label: 'pid', value: query.pid, rules: ['notnull']} 50 | ], 51 | result = this.check(arr) 52 | if (!result.success) { 53 | res.json({ 54 | code: 20301, 55 | success: false, 56 | message: result.message 57 | }) 58 | return 59 | } 60 | next() 61 | } 62 | } 63 | 64 | export default new ArticleComments() 65 | -------------------------------------------------------------------------------- /router/roleRelation.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import RoleRelation from '../controller/RoleRelation' 3 | import ValidateRoleRelation from '../validate/RoleRelation' 4 | const router = express.Router() 5 | 6 | /** 7 | * 设置角色权限 8 | * @api {POST} /api/RoleRelation/setPermissions 设置角色权限 9 | * @apiDescription 设置角色权限 10 | * @apiName setPermissions 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Object} Object 13 | * @apiSampleRequest /api/RoleRelation/setPermissions 14 | * @apiGroup RoleRelation 15 | * @apiVersion 0.0.1 16 | */ 17 | router.post('/setPermissions', ValidateRoleRelation.setPermissions, RoleRelation.setPermissions) 18 | /** 19 | * 获取角色权限 20 | * @api {put} /api/RoleRelation/getPermissions 获取角色权限 21 | * @apiDescription 获取角色权限 22 | * @apiName getPermissions 23 | * @apiHeader {String} Authorization token 24 | * @apiSampleRequest /api/RoleRelation/getPermissions 25 | * @apiGroup RoleRelation 26 | * @apiVersion 0.0.1 27 | */ 28 | router.get('/getPermissions', ValidateRoleRelation.getPermissions, RoleRelation.getPermissions) 29 | /** 30 | * 设置角色绑定用户 31 | * @api {POST} /api/RoleRelation/setBindUser 设置角色绑定用户 32 | * @apiDescription 设置角色绑定用户 33 | * @apiName setBindUser 34 | * @apiHeader {String} Authorization token 35 | * @apiParam (参数) {Object} Object 36 | * @apiSampleRequest /api/RoleRelation/setBindUser 37 | * @apiGroup RoleRelation 38 | * @apiVersion 0.0.1 39 | */ 40 | router.post('/setBindUser', ValidateRoleRelation.setBindUser, RoleRelation.setBindUser) 41 | /** 42 | * 获取角色绑定的用户 43 | * @api {delete} /api/RoleRelation/getBindUser 获取角色绑定的用户 44 | * @apiDescription 获取角色绑定的用户 45 | * @apiName getBindUser 46 | * @apiHeader {String} Authorization token 47 | * @apiSampleRequest /api/RoleRelation/getBindUser 48 | * @apiGroup RoleRelation 49 | * @apiVersion 0.0.1 50 | */ 51 | router.get('/getBindUser', ValidateRoleRelation.getBindUser, RoleRelation.getBindUser) 52 | 53 | export default router 54 | -------------------------------------------------------------------------------- /model/Token.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | import JWT from 'jsonwebtoken' 4 | 5 | class Token extends Base{ 6 | constructor () { 7 | super() 8 | this.getToken = this.getToken.bind(this) 9 | this.setToken = this.setToken.bind(this) 10 | } 11 | async getToken (obj) { 12 | let sql = `select * from bbs_token where 1 = 1 ${this.joinStr('get', obj.get)};` 13 | return query(sql) 14 | } 15 | async setToken (data, obj) { 16 | let search, sql, newUserInfo = JSON.parse(JSON.stringify(data)), oldUserInfo = {} 17 | try { 18 | search = await this.getToken({get: {user_id: data.id}}) 19 | } catch (e) { 20 | return e 21 | } 22 | // 用户不存在则创建一条数据,存在则将原来的token替换掉 23 | if (search.length === 0) { 24 | sql = `INSERT INTO bbs_token set ${this.joinStr('set', obj.set)};` 25 | } else { 26 | // 解析token和当前数据做对比 27 | JWT.verify(search[0][data.type + '_token'], 'BBS', (error, decoded) => { 28 | if (error) { 29 | return {} 30 | } 31 | oldUserInfo = decoded 32 | }) 33 | // 用户数据发生变化,重新设置数据信息,只修改token 34 | delete newUserInfo[data.type + '_expire_time'] 35 | delete oldUserInfo[data.type + '_expire_time'] 36 | delete oldUserInfo.iat 37 | if (JSON.stringify(newUserInfo) !== JSON.stringify(oldUserInfo)) { 38 | obj.set = { 39 | [data.type + '_token']: obj.set[data.type + '_token'] 40 | } 41 | sql = `UPDATE bbs_token set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 42 | } else if(+new Date(search[0][data.type + '_expire_time']) > +new Date()) { 43 | // 数据未过期,不处理 44 | sql = `` 45 | } else { 46 | sql = `UPDATE bbs_token set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 47 | } 48 | } 49 | return sql ? query(sql) : '' 50 | } 51 | } 52 | 53 | export default new Token() 54 | -------------------------------------------------------------------------------- /controller/Log.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import LogModel from '../model/Log' 3 | 4 | class Log extends Base { 5 | constructor () { 6 | super() 7 | this.writeLog = this.writeLog.bind(this) 8 | this.getList = this.getList.bind(this) 9 | } 10 | // 写入日志 11 | async writeLog (req, res, next) { 12 | let data = req.body, 13 | userInfo = await this.getUserInfo(req) 14 | try { 15 | // 写入登录日志 16 | await logModel.writeLog({ 17 | set: { 18 | origin: data.origin, 19 | type: data.type, 20 | title: data.title, 21 | desc: data.desc, 22 | ip: this.getClientIp(req), 23 | create_user: userInfo.id, 24 | create_time: new Date() 25 | } 26 | }) 27 | } catch (e) { 28 | this.handleException(req, res, e) 29 | return 30 | } 31 | res.json({ 32 | code: 20000, 33 | success: true, 34 | content: {}, 35 | message: '写入成功' 36 | }) 37 | } 38 | // 查询列表 39 | async getList (req, res, next) { 40 | let query = JSON.parse(JSON.stringify(req.query)), 41 | result, 42 | length, 43 | userInfo = await this.getUserInfo(req) 44 | // 设置非模糊查询字段 45 | for (let key in query) { 46 | if (['id', 'create_user', 'type', 'origin'].indexOf(key) === -1) { 47 | query.like = [...query.like || [], key] 48 | } 49 | } 50 | try { 51 | result = await LogModel.getList({get: query}) 52 | length = await LogModel.getTotals({get: query}) 53 | } catch (e) { 54 | this.handleException(req, res, e) 55 | return 56 | } 57 | res.json({ 58 | code: 20000, 59 | success: true, 60 | content: { 61 | result, 62 | curPage: +query.curPage, 63 | pageSize: +query.pageSize, 64 | totals: length ? length[0].count : 0 65 | }, 66 | message: '操作成功' 67 | }) 68 | } 69 | } 70 | 71 | export default new Log() 72 | -------------------------------------------------------------------------------- /model/TechSquare.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class TechSquare extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_tech_square set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_tech_square set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_tech_square where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_tech_square where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_tech_square 34 | where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_tech_square where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select a.*, b.icon as image, b.name as title from bbs_tech_square as a 43 | left join bbs_tag_type as b on a.tag_type_id = b.id 44 | where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 45 | // 处理表连接字段 46 | sql = sql.replace(/`status`/, 'a.status') 47 | sql = sql.replace(/`flag`/, 'a.flag') 48 | return query(sql) 49 | } 50 | } 51 | 52 | export default new TechSquare() 53 | -------------------------------------------------------------------------------- /model/TagRelation.js: -------------------------------------------------------------------------------- 1 | import mysql from 'mysql' 2 | import query from '../mysql' 3 | import Base from './Base' 4 | 5 | 6 | class TagRelation extends Base { 7 | constructor () { 8 | super() 9 | this.setBindTag = this.setBindTag.bind(this) 10 | this.getBindTag = this.getBindTag.bind(this) 11 | } 12 | // 设置标签类型绑定的标签 13 | async setBindTag (obj) { 14 | let dbTags, paramsTags = obj.data.tags || [], 15 | createTagList = [], deleteTagList = [], sql1, sql2, 16 | result1, result2 17 | // 先查询到当前标签类型下所有的标签 18 | dbTags = await query(`select a.tag_id from bbs_tag_type_tag as a where 1 = 1 ${this.joinStr('get', obj.get)};`) 19 | // 得到数据库的ID列表 20 | dbTags = dbTags.map(item => item.tag_id) 21 | // 数据库数据和传入数据做对比,数据库有而传入没有的数据删除,传入而数据库没有的数据添加 22 | dbTags.forEach(item => { 23 | // 需要删除菜单的数据 24 | if (!paramsTags.includes(item)) { 25 | deleteTagList.push(item) 26 | } 27 | }) 28 | paramsTags.forEach(item => { 29 | // 需要添加菜单的数据 30 | if (!dbTags.includes(item)) { 31 | createTagList.push([obj.get.tag_type_id, item]) 32 | } 33 | }) 34 | // 事务开始 35 | await query('begin') 36 | // 删除 37 | sql1 = `DELETE from bbs_tag_type_tag where tag_id in (${mysql.escape(deleteTagList)}) and tag_type_id = ${obj.get.tag_type_id};` 38 | // 添加 39 | sql2 = `INSERT INTO bbs_tag_type_tag (tag_type_id, tag_id) VALUES ${mysql.escape(createTagList)};` 40 | // 运行sql 41 | result1 = mysql.escape(deleteTagList) ? await query(sql1) : {affectedRows: true} 42 | result2 = mysql.escape(createTagList) ? await query(sql2) : {affectedRows: true} 43 | if (result1.affectedRows >= 0 && result2.affectedRows) { 44 | // 事务提交 45 | await query('commit') 46 | } else { 47 | // 事务回滚 48 | await query('rollback') 49 | } 50 | return result1.affectedRows >= 0 && result2.affectedRows 51 | } 52 | // 获取标签类型绑定的标签 53 | async getBindTag (obj) { 54 | let sql = `select tag_id from bbs_tag_type_tag where 1 = 1 ${this.joinStr('get', obj.get)};` 55 | return query(sql) 56 | } 57 | } 58 | 59 | export default new TagRelation() 60 | -------------------------------------------------------------------------------- /model/Column.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Column extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_column set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_column set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_column where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_column where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_column 34 | where 1 = 1 ${this.joinStr('get', obj.get)} ${this.joinStr('ORDER BY', {DESC: ['create_time', 'id']})} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_column where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select a.*, b.name as create_user_name, c.name as update_user_name from bbs_column as a 43 | left join bbs_user as b on a.create_user = b.id 44 | left join bbs_user as c on a.update_user = c.id 45 | where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 46 | // 处理表连接字段 47 | sql = sql.replace(/`flag`/, 'a.flag') 48 | sql = sql.replace(/`name`/, 'a.name') 49 | return query(sql) 50 | } 51 | } 52 | 53 | export default new Column() 54 | -------------------------------------------------------------------------------- /model/File.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class File extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_file set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_file set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_file where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_file where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_file 34 | where 1 = 1 ${this.joinStr('get', obj.get)} ${this.joinStr('ORDER BY', {DESC: ['create_time', 'id']})} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_file where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select a.*, b.name as create_user_name, c.name as update_user_name from bbs_file as a 43 | left join bbs_user as b on a.create_user = b.id 44 | left join bbs_user as c on a.update_user = c.id 45 | where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 46 | // 处理表连接字段 47 | sql = sql.replace(/`type`/, 'a.type') 48 | sql = sql.replace(/`name`/, 'a.name') 49 | sql = sql.replace(/`flag`/, 'a.flag') 50 | return query(sql) 51 | } 52 | } 53 | 54 | export default new File() 55 | -------------------------------------------------------------------------------- /model/Question.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Questions extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | async create (obj) { 16 | let sql = `INSERT INTO bbs_questions set ${this.joinStr('set', obj.set)};` 17 | return query(sql) 18 | } 19 | async update (obj) { 20 | let sql = `UPDATE bbs_questions set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 21 | return query(sql) 22 | } 23 | async delete (obj) { 24 | let sql = `DELETE from bbs_questions where 1 = 1 ${this.joinStr('get', obj.get)};` 25 | return query(sql) 26 | } 27 | async getRow (obj) { 28 | let sql = `select * from bbs_questions where 1 = 1 ${this.joinStr('get', obj.get)};` 29 | return query(sql) 30 | } 31 | async getList (obj) { 32 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 33 | let sql = `select * from bbs_questions 34 | where 1 = 1 ${this.joinStr('get', obj.get)} ${this.joinStr('ORDER BY', {DESC: ['create_time', 'id']})} limit ${(curPage - 1) * pageSize}, ${pageSize};` 35 | return query(sql) 36 | } 37 | async getTotals (obj) { 38 | let sql = `select COUNT(*) as count from bbs_questions where 1 = 1 ${this.joinStr('get', obj.get)};` 39 | return query(sql) 40 | } 41 | async getAll (obj) { 42 | let sql = `select a.*, b.name as create_user_name, c.name as update_user_name from bbs_questions as a 43 | left join bbs_user as b on a.create_user = b.id 44 | left join bbs_user as c on a.update_user = c.id 45 | where 1 = 1 ${this.joinStr('get', obj.get)}` 46 | // 处理表连接字段 47 | sql = sql.replace(/`flag`/, 'a.flag') 48 | sql = sql.replace(/`create_user`/, 'a.create_user') 49 | sql = sql.replace(/`name`/, 'a.name') 50 | return query(sql) 51 | } 52 | } 53 | 54 | export default new Questions() 55 | -------------------------------------------------------------------------------- /controller/Charts.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import LogModel from '../model/Log' 3 | 4 | class Charts extends Base { 5 | constructor () { 6 | super() 7 | this.getCharts = this.getCharts.bind(this) 8 | this.userLoginAnalyze = this.userLoginAnalyze.bind(this) 9 | } 10 | async getCharts (req, res, next) { 11 | const data = req.body.config 12 | } 13 | // 用户登陆分析 14 | async userLoginAnalyze (req, res, next) { 15 | let days = req.query.days - 1 || 6, 16 | now = this.utils.switchTime(new Date(), 'YYYY-MM-DD') + ' 00:00:00', 17 | result, lastDays = +new Date(now) - 1000 * 3600 * 24 * days 18 | try { 19 | result = await LogModel.getLoginLog({get: {larger: {create_time: this.utils.switchTime(lastDays, 'YYYY-MM-DD hh:mm:ss')}, type: 1}}) 20 | } catch (e) { 21 | this.handleException(req, res, e) 22 | return 23 | } 24 | // 对数据做处理 25 | const arr = [], daysList = [], timeList = [], dataList = [] 26 | result.forEach(item => { 27 | arr.push({ 28 | day: this.utils.switchTime(item.time, 'MM-DD'), 29 | time: this.utils.switchTime(item.time, 'hh:mm:ss'), 30 | hour: this.utils.switchTime(item.time, 'hh') 31 | }) 32 | // 得到天列表 33 | if (!daysList.includes(this.utils.switchTime(item.time, 'MM-DD'))) { 34 | daysList.push(this.utils.switchTime(item.time, 'MM-DD')) 35 | } 36 | }) 37 | // 初始化时间列表 38 | for (let i = 0, len = 24; i < len; i++) { 39 | timeList.push(i > 9 ? i + ':00' : '0' + i + ':00') 40 | } 41 | // 初始化数据列表 42 | for (let i = 0; i < days + 1; i++) { 43 | let arr1 = [] 44 | for (let i = 0, len = 24; i < len; i++) { 45 | arr1.push(0) 46 | } 47 | // 当天初始为当天的小时个数 48 | i === days ? dataList.push(arr1.slice(0, new Date().getHours() + 1)) : dataList.push(arr1) 49 | } 50 | arr.forEach(item => { 51 | // 得到每天每小时登陆的次数 52 | dataList[daysList.indexOf(item.day)][timeList.indexOf(item.hour + ':00')]++ 53 | }) 54 | res.json({ 55 | code: 20000, 56 | success: true, 57 | content: {timeList, daysList, dataList}, 58 | message: '操作成功' 59 | }) 60 | } 61 | // 用户注册分析 62 | async userRegisteredAnalyze (req, res, next) { 63 | } 64 | } 65 | 66 | export default new Charts() 67 | -------------------------------------------------------------------------------- /controller/ArticleComments.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import ArticleCommentsModel from '../model/ArticleComments' 3 | import mqttClient from '../mqtt/client' 4 | 5 | class ArticleComments extends Base { 6 | constructor () { 7 | super() 8 | this.create = this.create.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getAll = this.getAll.bind(this) 11 | } 12 | // 创建评论 13 | async create (req, res, next) { 14 | let data = JSON.parse(JSON.stringify(req.body)), 15 | userInfo = await this.getUserInfo(req), result 16 | try { 17 | // 参数处理 18 | data.create_user = userInfo.id, 19 | data.create_time = new Date() 20 | result = await ArticleCommentsModel.create({ 21 | set: data 22 | }) 23 | } catch (e) { 24 | this.handleException(req, res, e) 25 | return 26 | } 27 | // 推送mqtt消息 28 | mqttClient.publish(`/message/user/${data.p_user_id}`, JSON.stringify({ 29 | topic: `/message/user/${data.p_user_id}`, 30 | data: data 31 | })) 32 | res.json({ 33 | code: 20000, 34 | success: true, 35 | message: '创建成功' 36 | }) 37 | } 38 | // 删除评论 39 | async delete (req, res, next) { 40 | const userInfo = await this.getUserInfo(req), 41 | result = await ArticleCommentsModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 42 | if (result.affectedRows) { 43 | res.json({ 44 | code: 20000, 45 | success: true, 46 | message: '删除成功' 47 | }) 48 | } else { 49 | res.json({ 50 | code: 20001, 51 | success: true, 52 | message: '删除失败' 53 | }) 54 | } 55 | } 56 | // 获取评论 57 | async getAll (req, res, next) { 58 | let result, query = req.query, totals 59 | try { 60 | result = await ArticleCommentsModel.getAll({get: {...query, flag: 1}}) 61 | totals = await ArticleCommentsModel.getTotals({get: {...query, flag: 1}}) 62 | } catch (e) { 63 | this.handleException(req, res, e) 64 | return 65 | } 66 | res.json({ 67 | code: 20000, 68 | success: true, 69 | content: result, 70 | totals: totals[0].count, 71 | message: '操作成功' 72 | }) 73 | } 74 | } 75 | 76 | export default new ArticleComments() 77 | -------------------------------------------------------------------------------- /controller/Area.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import AreaModel from '../model/Area' 3 | 4 | class Area extends Base { 5 | constructor () { 6 | super() 7 | this.update = this.update.bind(this) 8 | this.getList = this.getList.bind(this) 9 | this.getAll = this.getAll.bind(this) 10 | } 11 | // 编辑 12 | async update (req, res, next) { 13 | let data = req.body, 14 | result, 15 | userInfo = await this.getUserInfo(req) 16 | try { 17 | result = await AreaModel.update({ 18 | set: { 19 | status: data.status 20 | }, 21 | get: { 22 | id: data.id 23 | } 24 | }) 25 | } catch (e) { 26 | this.handleException(req, res, e) 27 | return 28 | } 29 | if (result.affectedRows) { 30 | res.json({ 31 | code: 20000, 32 | success: true, 33 | message: '操作成功' 34 | }) 35 | } else { 36 | res.json({ 37 | code: 20001, 38 | success: false, 39 | message: '编辑失败' 40 | }) 41 | } 42 | } 43 | // 查询列表 44 | async getList (req, res, next) { 45 | let query = JSON.parse(JSON.stringify(req.query)), 46 | result, 47 | length, 48 | userInfo = await this.getUserInfo(req) 49 | // 设置非模糊查询字段 50 | for (let key in query) { 51 | if (['id', 'pid'].indexOf(key) === -1) { 52 | query.like = [...query.like || [], key] 53 | } 54 | } 55 | try { 56 | result = await AreaModel.getList({get: query}) 57 | length = await AreaModel.getTotals({get: query}) 58 | } catch (e) { 59 | this.handleException(req, res, e) 60 | return 61 | } 62 | res.json({ 63 | code: 20000, 64 | success: true, 65 | content: { 66 | result, 67 | curPage: +query.curPage, 68 | pageSize: +query.pageSize, 69 | totals: length ? length[0].count : 0 70 | }, 71 | message: '操作成功' 72 | }) 73 | } 74 | // 根据PID获取所有下级区域 75 | async getAll (req, res, next) { 76 | let pid = req.params.pid, result 77 | try { 78 | result = await AreaModel.getAll({get: {pid}}) 79 | } catch (e) { 80 | this.handleException(req, res, e) 81 | return 82 | } 83 | res.json({ 84 | code: 20000, 85 | success: true, 86 | content: result, 87 | message: '操作成功' 88 | }) 89 | } 90 | } 91 | 92 | export default new Area() 93 | -------------------------------------------------------------------------------- /model/DataPerms.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class DataPerms extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getTotals = this.getTotals.bind(this) 13 | this.getRoleDataPerms = this.getRoleDataPerms.bind(this) 14 | this.getAll = this.getAll.bind(this) 15 | } 16 | async create (obj) { 17 | let sql = `INSERT INTO bbs_data_perms set ${this.joinStr('set', obj.set)};` 18 | return query(sql) 19 | } 20 | async update (obj) { 21 | let sql = `UPDATE bbs_data_perms set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 22 | return query(sql) 23 | } 24 | async delete (obj) { 25 | let sql = `DELETE from bbs_data_perms where 1 = 1 ${this.joinStr('get', obj.get)};` 26 | return query(sql) 27 | } 28 | async getRow (obj) { 29 | let sql = `select * from bbs_data_perms where 1 = 1 ${this.joinStr('get', obj.get)};` 30 | return query(sql) 31 | } 32 | async getList (obj) { 33 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 34 | let sql = `select * from bbs_data_perms 35 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 36 | return query(sql) 37 | } 38 | async getTotals (obj) { 39 | let sql = `select COUNT(*) as count from bbs_data_perms where 1 = 1 ${this.joinStr('get', obj.get)};` 40 | return query(sql) 41 | } 42 | async getRoleDataPerms (obj) { 43 | let sql = `select a.* from bbs_data_perms as a 44 | LEFT JOIN bbs_role_data_perms as b 45 | ON a.id = b.data_perms_id where 1 = 1 ${this.joinStr('get', obj.get)};` 46 | return query(sql) 47 | } 48 | // 只获取code,前端页面做数据权限使用 49 | async getCodeByRoleDataPerms (obj) { 50 | let sql = `select a.code from bbs_data_perms as a 51 | LEFT JOIN bbs_role_data_perms as b 52 | ON a.id = b.data_perms_id where 1 = 1 ${this.joinStr('get', obj.get)};` 53 | return query(sql) 54 | } 55 | async getAll (obj) { 56 | let sql = `select * from bbs_data_perms where 1 = 1 ${this.joinStr('get', obj.get)};` 57 | return query(sql) 58 | } 59 | } 60 | 61 | export default new DataPerms() 62 | -------------------------------------------------------------------------------- /model/Menu.js: -------------------------------------------------------------------------------- 1 | import query from '../mysql' 2 | import Base from './Base' 3 | 4 | class Menu extends Base{ 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getRoleMenu = this.getRoleMenu.bind(this) 12 | this.getAll = this.getAll.bind(this) 13 | } 14 | async create (obj) { 15 | let sql = `INSERT INTO bbs_menu set ${this.joinStr('set', obj.set)};` 16 | return query(sql) 17 | } 18 | async update (obj) { 19 | let sql = `UPDATE bbs_menu set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 20 | return query(sql) 21 | } 22 | async delete (obj) { 23 | let sql = `DELETE from bbs_menu where 1 = 1 ${this.joinStr('get', obj.get)};` 24 | return query(sql) 25 | } 26 | async getRow (obj) { 27 | let sql = `select * from bbs_menu where 1 = 1 ${this.joinStr('get', obj.get)};` 28 | return query(sql) 29 | } 30 | async getList (obj) { 31 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 32 | let sql = `select * from bbs_menu 33 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 34 | return query(sql) 35 | } 36 | async getTotals (obj) { 37 | let sql = `select COUNT(*) as count from bbs_menu where 1 = 1 ${this.joinStr('get', obj.get)};` 38 | return query(sql) 39 | } 40 | async getRoleMenu (obj) { 41 | let sql = `select a.* from bbs_menu as a 42 | LEFT JOIN bbs_role_menu as b 43 | ON a.id = b.menu_id where 1 = 1 ${this.joinStr('get', obj.get)};` 44 | // admin则获取所有数据 45 | if (+obj.get.role_id === 1) { 46 | delete obj.get.role_id 47 | sql = `select * from bbs_menu where 1 = 1 ${this.joinStr('get', obj.get)};` 48 | } 49 | return query(sql) 50 | } 51 | async getAll (obj) { 52 | let sql = `select a.*, b.name as create_user_name, c.name as update_user_name from bbs_menu as a 53 | left join bbs_user as b on a.create_user = b.id 54 | left join bbs_user as c on a.update_user = c.id 55 | where 1 = 1 ${this.joinStr('get', obj.get)} ORDER BY sort;` 56 | // 处理表连接字段 57 | sql = sql.replace(/`type`/, 'a.type') 58 | sql = sql.replace(/`flag`/, 'a.flag') 59 | return query(sql) 60 | } 61 | } 62 | 63 | export default new Menu() 64 | -------------------------------------------------------------------------------- /validate/Tag.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Tag extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | ], 17 | result = this.check(arr) 18 | if (!result.success) { 19 | res.json({ 20 | code: 20301, 21 | success: false, 22 | message: result.message 23 | }) 24 | return 25 | } 26 | next() 27 | } 28 | async update (req, res, next) { 29 | const params = req.body, 30 | arr = [ 31 | ], 32 | result = this.check(arr) 33 | if (!result.success) { 34 | res.json({ 35 | code: 20301, 36 | success: false, 37 | message: result.message 38 | }) 39 | return 40 | } 41 | next() 42 | } 43 | async delete (req, res, next) { 44 | const ID = req.params.id, 45 | arr = [ 46 | {label: 'ID', value: ID, rules: ['notnull']} 47 | ], 48 | result = this.check(arr) 49 | if (!result.success) { 50 | res.json({ 51 | code: 20301, 52 | success: false, 53 | message: result.message 54 | }) 55 | return 56 | } 57 | next() 58 | } 59 | async getRow (req, res, next) { 60 | const ID = req.params.id, 61 | arr = [ 62 | {label: 'ID', value: ID, rules: ['notnull']} 63 | ], 64 | result = this.check(arr) 65 | if (!result.success) { 66 | res.json({ 67 | code: 20301, 68 | success: false, 69 | message: result.message 70 | }) 71 | return 72 | } 73 | next() 74 | } 75 | async getList (req, res, next) { 76 | const data = req.query, 77 | arr = [ 78 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 79 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 80 | ], 81 | result = this.check(arr) 82 | if (!result.success) { 83 | res.json({ 84 | code: 20301, 85 | success: false, 86 | message: result.message 87 | }) 88 | return 89 | } 90 | next() 91 | } 92 | async getAll (req, res, next) { 93 | next() 94 | } 95 | } 96 | 97 | export default new Tag() 98 | -------------------------------------------------------------------------------- /validate/Topic.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Topic extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | ], 17 | result = this.check(arr) 18 | if (!result.success) { 19 | res.json({ 20 | code: 20301, 21 | success: false, 22 | message: result.message 23 | }) 24 | return 25 | } 26 | next() 27 | } 28 | async update (req, res, next) { 29 | const params = req.body, 30 | arr = [ 31 | ], 32 | result = this.check(arr) 33 | if (!result.success) { 34 | res.json({ 35 | code: 20301, 36 | success: false, 37 | message: result.message 38 | }) 39 | return 40 | } 41 | next() 42 | } 43 | async delete (req, res, next) { 44 | const ID = req.params.id, 45 | arr = [ 46 | {label: 'ID', value: ID, rules: ['notnull']} 47 | ], 48 | result = this.check(arr) 49 | if (!result.success) { 50 | res.json({ 51 | code: 20301, 52 | success: false, 53 | message: result.message 54 | }) 55 | return 56 | } 57 | next() 58 | } 59 | async getRow (req, res, next) { 60 | const ID = req.params.id, 61 | arr = [ 62 | {label: 'ID', value: ID, rules: ['notnull']} 63 | ], 64 | result = this.check(arr) 65 | if (!result.success) { 66 | res.json({ 67 | code: 20301, 68 | success: false, 69 | message: result.message 70 | }) 71 | return 72 | } 73 | next() 74 | } 75 | async getList (req, res, next) { 76 | const data = req.query, 77 | arr = [ 78 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 79 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 80 | ], 81 | result = this.check(arr) 82 | if (!result.success) { 83 | res.json({ 84 | code: 20301, 85 | success: false, 86 | message: result.message 87 | }) 88 | return 89 | } 90 | next() 91 | } 92 | async getAll (req, res, next) { 93 | next() 94 | } 95 | } 96 | 97 | export default new Topic() 98 | -------------------------------------------------------------------------------- /validate/TagType.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class TagType extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | ], 17 | result = this.check(arr) 18 | if (!result.success) { 19 | res.json({ 20 | code: 20301, 21 | success: false, 22 | message: result.message 23 | }) 24 | return 25 | } 26 | next() 27 | } 28 | async update (req, res, next) { 29 | const params = req.body, 30 | arr = [ 31 | ], 32 | result = this.check(arr) 33 | if (!result.success) { 34 | res.json({ 35 | code: 20301, 36 | success: false, 37 | message: result.message 38 | }) 39 | return 40 | } 41 | next() 42 | } 43 | async delete (req, res, next) { 44 | const ID = req.params.id, 45 | arr = [ 46 | {label: 'ID', value: ID, rules: ['notnull']} 47 | ], 48 | result = this.check(arr) 49 | if (!result.success) { 50 | res.json({ 51 | code: 20301, 52 | success: false, 53 | message: result.message 54 | }) 55 | return 56 | } 57 | next() 58 | } 59 | async getRow (req, res, next) { 60 | const ID = req.params.id, 61 | arr = [ 62 | {label: 'ID', value: ID, rules: ['notnull']} 63 | ], 64 | result = this.check(arr) 65 | if (!result.success) { 66 | res.json({ 67 | code: 20301, 68 | success: false, 69 | message: result.message 70 | }) 71 | return 72 | } 73 | next() 74 | } 75 | async getList (req, res, next) { 76 | const data = req.query, 77 | arr = [ 78 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 79 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 80 | ], 81 | result = this.check(arr) 82 | if (!result.success) { 83 | res.json({ 84 | code: 20301, 85 | success: false, 86 | message: result.message 87 | }) 88 | return 89 | } 90 | next() 91 | } 92 | async getAll (req, res, next) { 93 | next() 94 | } 95 | } 96 | 97 | export default new TagType() 98 | -------------------------------------------------------------------------------- /router/tag.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Tag from '../controller/Tag' 3 | import ValidateTag from '../validate/Tag' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Tag/create 创建 9 | * @apiDescription 创建标签类型 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} type_id 类型ID 13 | * @apiParam (参数) {String} name 名称 14 | * @apiParam (参数) {String} sort 排序 15 | * @apiParam (参数) {String} desc 描述 16 | * @apiSampleRequest /api/Tag/create 17 | * @apiGroup Tag 18 | * @apiVersion 0.0.1 19 | */ 20 | router.post('/create', ValidateTag.create, Tag.create) 21 | /** 22 | * 编辑 23 | * @api {put} /api/Tag/update 编辑 24 | * @apiDescription 编辑 25 | * @apiName update 26 | * @apiHeader {String} Authorization token 27 | * @apiParam (参数) {Number} id 28 | * @apiParam (参数) {Number} type_id 类型ID 29 | * @apiParam (参数) {String} name 名称 30 | * @apiParam (参数) {String} sort 排序 31 | * @apiParam (参数) {String} desc 描述 32 | * @apiSampleRequest /api/Tag/update 33 | * @apiGroup Tag 34 | * @apiVersion 0.0.1 35 | */ 36 | router.put('/update', ValidateTag.update, Tag.update) 37 | /** 38 | * 删除 39 | * @api {delete} /api/Tag/delete/:id 删除 40 | * @apiDescription 删除 41 | * @apiName delete 42 | * @apiHeader {String} Authorization token 43 | * @apiParam {Number} id 44 | * @apiSampleRequest /api/Tag/delete 45 | * @apiGroup Tag 46 | * @apiVersion 0.0.1 47 | */ 48 | router.delete('/delete/:id', ValidateTag.delete, Tag.delete) 49 | 50 | /** 51 | * 获取标签类型信息 52 | * @api {get} /api/Tag/getRow 获取标签类型信息 53 | * @apiDescription 获取标签类型信息 54 | * @apiName getRow 55 | * @apiHeader {String} Authorization token 56 | * @apiParam {Number} id 57 | * @apiSampleRequest /api/Tag/getRow 58 | * @apiGroup Tag 59 | * @apiVersion 0.0.1 60 | */ 61 | router.get('/getRow/:id', ValidateTag.getRow, Tag.getRow) 62 | /** 63 | * 获取标签类型列表 64 | * @api {get} /api/Tag/getList 获取标签类型列表 65 | * @apiDescription 获取标签类型列表 66 | * @apiName getList 67 | * @apiHeader {String} Authorization token 68 | * @apiParam (path参数) {Number} curPage 69 | * @apiParam (path参数) {Number} pageSize 70 | * @apiSampleRequest /api/Tag/getList 71 | * @apiGroup Tag 72 | * @apiVersion 0.0.1 73 | */ 74 | router.get('/getList', ValidateTag.getList, Tag.getList) 75 | /** 76 | * 获取所有标签类型 77 | * @api {get} /api/Tag/getAll 获取所有标签类型 78 | * @apiDescription 获取所有标签类型 79 | * @apiName getAll 80 | * @apiParam {Number} type 81 | * @apiHeader {String} Authorization token 82 | * @apiSampleRequest /api/Tag/getAll 83 | * @apiGroup Tag 84 | * @apiVersion 0.0.1 85 | */ 86 | router.get('/getAll', ValidateTag.getAll, Tag.getAll) 87 | 88 | export default router 89 | -------------------------------------------------------------------------------- /router/file.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import File from '../controller/File' 3 | import ValidateFile from '../validate/File' 4 | import multipart from 'connect-multiparty' // 处理form-data数据中间件 5 | 6 | const router = express.Router() 7 | 8 | /** 9 | * 上传文件 10 | * @api {POST} /api/File/upload 创建 11 | * @apiDescription 上传文件 12 | * @apiName upload 13 | * @apiHeader {String} Authorization token 14 | * @apiParam (参数) {Number} id 目录ID 15 | * @apiSampleRequest /api/File/upload 16 | * @apiGroup File 17 | * @apiVersion 0.0.1 18 | */ 19 | router.post('/upload', multipart(), ValidateFile.upload, File.upload) 20 | /** 21 | * 编辑 22 | * @api {put} /api/File/update 编辑 23 | * @apiDescription 编辑 24 | * @apiName update 25 | * @apiHeader {String} Authorization token 26 | * @apiParam (参数) {Number} id 27 | * @apiParam (参数) {Number} f_id 文件目录ID 28 | * @apiParam (参数) {String} name 文件名称 29 | * @apiParam (参数) {String} desc 描述 30 | * @apiSampleRequest /api/File/update 31 | * @apiGroup File 32 | * @apiVersion 0.0.1 33 | */ 34 | router.put('/update', ValidateFile.update, File.update) 35 | /** 36 | * 删除 37 | * @api {delete} /api/File/delete/:id 删除 38 | * @apiDescription 删除 39 | * @apiName delete 40 | * @apiHeader {String} Authorization token 41 | * @apiParam {Number} id 42 | * @apiSampleRequest /api/File/delete 43 | * @apiGroup File 44 | * @apiVersion 0.0.1 45 | */ 46 | router.delete('/delete/:id', ValidateFile.delete, File.delete) 47 | 48 | /** 49 | * 获取文件信息 50 | * @api {get} /api/File/getRow 获取文件信息 51 | * @apiDescription 获取文件信息 52 | * @apiName getRow 53 | * @apiHeader {String} Authorization token 54 | * @apiParam {Number} id 55 | * @apiSampleRequest /api/File/getRow 56 | * @apiGroup File 57 | * @apiVersion 0.0.1 58 | */ 59 | router.get('/getRow/:id', ValidateFile.getRow, File.getRow) 60 | /** 61 | * 获取文件列表 62 | * @api {get} /api/File/getList 获取文件列表 63 | * @apiDescription 获取文件列表 64 | * @apiName getList 65 | * @apiHeader {String} Authorization token 66 | * @apiParam (path参数) {Number} curPage 67 | * @apiParam (path参数) {Number} pageSize 68 | * @apiParam (path参数) {Number} f_id 目录ID 69 | * @apiSampleRequest /api/File/getList 70 | * @apiGroup File 71 | * @apiVersion 0.0.1 72 | */ 73 | router.get('/getList', ValidateFile.getList, File.getList) 74 | /** 75 | * 获取所有文件 76 | * @api {get} /api/File/getAll 获取所有文件 77 | * @apiDescription 获取所有文件 78 | * @apiName getAll 79 | * @apiParam {Number} type 80 | * @apiHeader {String} Authorization token 81 | * @apiSampleRequest /api/File/getAll 82 | * @apiParam (path参数) {Number} f_id 目录ID 83 | * @apiGroup File 84 | * @apiVersion 0.0.1 85 | */ 86 | router.get('/getAll', ValidateFile.getAll, File.getAll) 87 | 88 | export default router 89 | -------------------------------------------------------------------------------- /router/topic.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Topic from '../controller/Topic' 3 | import ValidateTopic from '../validate/Topic' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Topic/create 创建 9 | * @apiDescription 创建标签类型 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} type_id 类型ID 13 | * @apiParam (参数) {String} name 名称 14 | * @apiParam (参数) {String} sort 排序 15 | * @apiParam (参数) {String} desc 描述 16 | * @apiSampleRequest /api/Topic/create 17 | * @apiGroup Topic 18 | * @apiVersion 0.0.1 19 | */ 20 | router.post('/create', ValidateTopic.create, Topic.create) 21 | /** 22 | * 编辑 23 | * @api {put} /api/Topic/update 编辑 24 | * @apiDescription 编辑 25 | * @apiName update 26 | * @apiHeader {String} Authorization token 27 | * @apiParam (参数) {Number} id 28 | * @apiParam (参数) {Number} type_id 类型ID 29 | * @apiParam (参数) {String} name 名称 30 | * @apiParam (参数) {String} sort 排序 31 | * @apiParam (参数) {String} desc 描述 32 | * @apiSampleRequest /api/Topic/update 33 | * @apiGroup Topic 34 | * @apiVersion 0.0.1 35 | */ 36 | router.put('/update', ValidateTopic.update, Topic.update) 37 | /** 38 | * 删除 39 | * @api {delete} /api/Topic/delete/:id 删除 40 | * @apiDescription 删除 41 | * @apiName delete 42 | * @apiHeader {String} Authorization token 43 | * @apiParam {Number} id 44 | * @apiSampleRequest /api/Topic/delete 45 | * @apiGroup Topic 46 | * @apiVersion 0.0.1 47 | */ 48 | router.delete('/delete/:id', ValidateTopic.delete, Topic.delete) 49 | 50 | /** 51 | * 获取订阅信息 52 | * @api {get} /api/Topic/getRow 获取标签类型信息 53 | * @apiDescription 获取标签类型信息 54 | * @apiName getRow 55 | * @apiHeader {String} Authorization token 56 | * @apiParam {Number} id 57 | * @apiSampleRequest /api/Topic/getRow 58 | * @apiGroup Topic 59 | * @apiVersion 0.0.1 60 | */ 61 | router.get('/getRow/:id', ValidateTopic.getRow, Topic.getRow) 62 | /** 63 | * 获取订阅列表 64 | * @api {get} /api/Topic/getList 获取标签类型列表 65 | * @apiDescription 获取标签类型列表 66 | * @apiName getList 67 | * @apiHeader {String} Authorization token 68 | * @apiParam (path参数) {Number} curPage 69 | * @apiParam (path参数) {Number} pageSize 70 | * @apiSampleRequest /api/Topic/getList 71 | * @apiGroup Topic 72 | * @apiVersion 0.0.1 73 | */ 74 | router.get('/getList', ValidateTopic.getList, Topic.getList) 75 | /** 76 | * 获取所有标签类型 77 | * @api {get} /api/Topic/getAll 获取所有标签类型 78 | * @apiDescription 获取所有标签类型 79 | * @apiName getAll 80 | * @apiParam {Number} type 81 | * @apiHeader {String} Authorization token 82 | * @apiSampleRequest /api/Topic/getAll 83 | * @apiGroup Topic 84 | * @apiVersion 0.0.1 85 | */ 86 | router.get('/getAll', ValidateTopic.getAll, Topic.getAll) 87 | 88 | export default router 89 | -------------------------------------------------------------------------------- /router/folder.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Folder from '../controller/Folder' 3 | import ValidateFolder from '../validate/Folder' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Folder/create 创建 9 | * @apiDescription 创建目录 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} pid 父ID 13 | * @apiParam (参数) {String} name 目录名称 14 | * @apiParam (参数) {String} sort 排序 15 | * @apiParam (参数) {String} desc 描述 16 | * @apiSampleRequest /api/Folder/create 17 | * @apiGroup Folder 18 | * @apiVersion 0.0.1 19 | */ 20 | router.post('/create', ValidateFolder.create, Folder.create) 21 | /** 22 | * 编辑 23 | * @api {put} /api/Folder/update 编辑 24 | * @apiDescription 编辑 25 | * @apiName update 26 | * @apiHeader {String} Authorization token 27 | * @apiParam (参数) {Number} id 28 | * @apiParam (参数) {Number} pid 父ID 29 | * @apiParam (参数) {String} name 目录名称 30 | * @apiParam (参数) {String} sort 排序 31 | * @apiParam (参数) {String} desc 描述 32 | * @apiSampleRequest /api/Folder/update 33 | * @apiGroup Folder 34 | * @apiVersion 0.0.1 35 | */ 36 | router.put('/update', ValidateFolder.update, Folder.update) 37 | /** 38 | * 删除 39 | * @api {delete} /api/Folder/delete/:id 删除 40 | * @apiDescription 删除 41 | * @apiName delete 42 | * @apiHeader {String} Authorization token 43 | * @apiParam {Number} id 44 | * @apiSampleRequest /api/Folder/delete 45 | * @apiGroup Folder 46 | * @apiVersion 0.0.1 47 | */ 48 | router.delete('/delete/:id', ValidateFolder.delete, Folder.delete) 49 | 50 | /** 51 | * 获取目录信息 52 | * @api {get} /api/Folder/getRow 获取目录信息 53 | * @apiDescription 获取目录信息 54 | * @apiName getRow 55 | * @apiHeader {String} Authorization token 56 | * @apiParam {Number} id 57 | * @apiSampleRequest /api/Folder/getRow 58 | * @apiGroup Folder 59 | * @apiVersion 0.0.1 60 | */ 61 | router.get('/getRow/:id', ValidateFolder.getRow, Folder.getRow) 62 | /** 63 | * 获取目录列表 64 | * @api {get} /api/Folder/getList 获取目录列表 65 | * @apiDescription 获取目录列表 66 | * @apiName getList 67 | * @apiHeader {String} Authorization token 68 | * @apiParam (path参数) {Number} curPage 69 | * @apiParam (path参数) {Number} pageSize 70 | * @apiSampleRequest /api/Folder/getList 71 | * @apiGroup Folder 72 | * @apiVersion 0.0.1 73 | */ 74 | router.get('/getList', ValidateFolder.getList, Folder.getList) 75 | /** 76 | * 获取所有目录 77 | * @api {get} /api/Folder/getAll 获取所有目录 78 | * @apiDescription 获取所有目录 79 | * @apiName getAll 80 | * @apiParam {Number} type 81 | * @apiHeader {String} Authorization token 82 | * @apiSampleRequest /api/Folder/getAll 83 | * @apiGroup Folder 84 | * @apiVersion 0.0.1 85 | */ 86 | router.get('/getAll', ValidateFolder.getAll, Folder.getAll) 87 | 88 | export default router 89 | -------------------------------------------------------------------------------- /model/Base.js: -------------------------------------------------------------------------------- 1 | import mysql from 'mysql' 2 | import utils from '../lib/js/utils' 3 | 4 | class Base{ 5 | constructor () { 6 | this.utils = utils 7 | } 8 | joinStr (type, obj) { 9 | let str = '' 10 | switch (type) { 11 | case 'set': 12 | for (let key in obj) { 13 | let separated = str ? ',' : '' 14 | // str += `${separated} ${key} = ${mysql.escape(obj[key])} ` 15 | str += separated + '`' + key + '` = ' + mysql.escape(obj[key]) 16 | } 17 | return str 18 | case 'get': 19 | // TODO: 暂时只对一般条件查询和模糊查询处理 20 | for (let key in obj) { 21 | // 参数跳过, and相关字符串拼接 22 | if (['curPage', 'pageSize', 'or', 'larger', 'lessThan'].indexOf(key) === -1) { 23 | // 开始拼接SQL 24 | if (obj['like'] && obj['like'].indexOf(key) !== -1) { 25 | // str += `and ${key} like ${mysql.escape('%' + obj[key] + '%')} ` 26 | str += ' and `' + key + '` like' + mysql.escape('%' + obj[key] + '%') 27 | } else if (key !== 'like') { 28 | // str += `and ${key} = ${mysql.escape(obj[key])} ` 29 | str += ' and `' + key + '` = ' + mysql.escape(obj[key]) 30 | } 31 | } 32 | // 或相关字符串拼接 33 | if (key === 'or') { 34 | let or = obj.or, keyWord = 'and', index = 0 35 | for (let key in or) { 36 | if (index > 0) { 37 | keyWord = 'or' 38 | } 39 | index++ 40 | str += ' ' + keyWord + ' `' + key + '` = ' + mysql.escape(or[key]) 41 | } 42 | } 43 | // 大于 44 | if (key === 'larger') { 45 | let larger = obj.larger, keyWord = 'and' 46 | for (let key in larger) { 47 | str += ' ' + keyWord + ' `' + key + '` > ' + mysql.escape(larger[key]) 48 | } 49 | } 50 | // 小于 51 | if (key === 'lessThan') { 52 | let lessThan = obj.lessThan, keyWord = 'and', index = 0 53 | for (let key in lessThan) { 54 | str += ' ' + keyWord + ' `' + key + '` < ' + mysql.escape(lessThan[key]) 55 | } 56 | } 57 | } 58 | return str 59 | case 'ORDER BY': 60 | if (obj.DESC.length > 0 || obj.other.length > 0) { 61 | str = 'ORDER BY ' 62 | } 63 | obj.DESC = obj.DESC || [] 64 | obj.other = obj.other || [] 65 | obj.DESC.forEach(val => { 66 | str += `${val} DESC,` 67 | }) 68 | obj.other.forEach(val => { 69 | str += `${val},` 70 | }) 71 | // 删除最后的逗号 72 | str = str.substr(0, str.length - 1) 73 | return str 74 | } 75 | } 76 | } 77 | 78 | export default Base 79 | -------------------------------------------------------------------------------- /router/tagType.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import TagType from '../controller/TagType' 3 | import ValidateTagType from '../validate/TagType' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/TagType/create 创建 9 | * @apiDescription 创建标签 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} type_id 类型ID 13 | * @apiParam (参数) {String} name 名称 14 | * @apiParam (参数) {String} wikipedia 标签百科 15 | * @apiParam (参数) {String} sort 排序 16 | * @apiParam (参数) {String} desc 描述 17 | * @apiSampleRequest /api/TagType/create 18 | * @apiGroup TagType 19 | * @apiVersion 0.0.1 20 | */ 21 | router.post('/create', ValidateTagType.create, TagType.create) 22 | /** 23 | * 编辑 24 | * @api {put} /api/TagType/update 编辑 25 | * @apiDescription 编辑 26 | * @apiName update 27 | * @apiHeader {String} Authorization token 28 | * @apiParam (参数) {Number} id 29 | * @apiParam (参数) {Number} type_id 类型ID 30 | * @apiParam (参数) {String} name 名称 31 | * @apiParam (参数) {String} wikipedia 标签百科 32 | * @apiParam (参数) {String} sort 排序 33 | * @apiParam (参数) {String} desc 描述 34 | * @apiSampleRequest /api/TagType/update 35 | * @apiGroup TagType 36 | * @apiVersion 0.0.1 37 | */ 38 | router.put('/update', ValidateTagType.update, TagType.update) 39 | /** 40 | * 删除 41 | * @api {delete} /api/TagType/delete/:id 删除 42 | * @apiDescription 删除 43 | * @apiName delete 44 | * @apiHeader {String} Authorization token 45 | * @apiParam {Number} id 46 | * @apiSampleRequest /api/TagType/delete 47 | * @apiGroup TagType 48 | * @apiVersion 0.0.1 49 | */ 50 | router.delete('/delete/:id', ValidateTagType.delete, TagType.delete) 51 | 52 | /** 53 | * 获取标签信息 54 | * @api {get} /api/TagType/getRow 获取标签信息 55 | * @apiDescription 获取标签信息 56 | * @apiName getRow 57 | * @apiHeader {String} Authorization token 58 | * @apiParam {Number} id 59 | * @apiSampleRequest /api/TagType/getRow 60 | * @apiGroup TagType 61 | * @apiVersion 0.0.1 62 | */ 63 | router.get('/getRow/:id', ValidateTagType.getRow, TagType.getRow) 64 | /** 65 | * 获取标签列表 66 | * @api {get} /api/TagType/getList 获取标签列表 67 | * @apiDescription 获取标签列表 68 | * @apiName getList 69 | * @apiHeader {String} Authorization token 70 | * @apiParam (path参数) {Number} curPage 71 | * @apiParam (path参数) {Number} pageSize 72 | * @apiSampleRequest /api/TagType/getList 73 | * @apiGroup TagType 74 | * @apiVersion 0.0.1 75 | */ 76 | router.get('/getList', ValidateTagType.getList, TagType.getList) 77 | /** 78 | * 获取所有标签 79 | * @api {get} /api/TagType/getAll 获取所有标签 80 | * @apiDescription 获取所有标签 81 | * @apiName getAll 82 | * @apiParam {Number} type 83 | * @apiHeader {String} Authorization token 84 | * @apiSampleRequest /api/TagType/getAll 85 | * @apiGroup TagType 86 | * @apiVersion 0.0.1 87 | */ 88 | router.get('/getAll', ValidateTagType.getAll, TagType.getAll) 89 | 90 | export default router 91 | -------------------------------------------------------------------------------- /controller/Base.js: -------------------------------------------------------------------------------- 1 | import TokenModel from '../model/Token' 2 | import UserModel from '../model/User' 3 | import JWT from 'jsonwebtoken' 4 | import utils from '../lib/js/utils' 5 | import path from 'path' 6 | import fs from 'fs' 7 | import NodeLog from '../log/index' 8 | 9 | class Base{ 10 | constructor () { 11 | this.utils = utils 12 | } 13 | // 获取到用户信息 14 | async getUserInfo (req) { 15 | let userInfo = {}, result 16 | JWT.verify(req.headers.authorization, 'BBS', (error, decoded) => { 17 | if (error) { 18 | return {} 19 | } 20 | userInfo = decoded 21 | }) 22 | // 直接从数据库获取,能保证用户最新的数据 23 | result = await UserModel.getRow({get: {id: userInfo.id, flag: 1}}) 24 | return result[0] 25 | } 26 | // 获取客户端IP 27 | getClientIp (req) { 28 | var ipAddress, forwardedIpsStr = req.header('x-forwarded-for') 29 | if (forwardedIpsStr) { 30 | var forwardedIps = forwardedIpsStr.split(',') 31 | ipAddress = forwardedIps[0] 32 | } 33 | if (!ipAddress) { 34 | ipAddress = req.connection.remoteAddress 35 | } 36 | return ipAddress 37 | } 38 | // 获取服务端地址 39 | getServiceAddr (req) { 40 | const headers = req.headers 41 | return req.protocol + '://' + headers.host 42 | } 43 | // 查询路径是否存在 44 | async getStat (path) { 45 | return new Promise((resolve, reject) => { 46 | fs.stat(path, (err, stats) => { 47 | if (err) { 48 | resolve(false) 49 | } else { 50 | resolve(stats) 51 | } 52 | }) 53 | }) 54 | } 55 | // 创建路径 56 | async mkdir(dir){ 57 | return new Promise((resolve, reject) => { 58 | fs.mkdir(dir, err => { 59 | if (err) { 60 | resolve(false) 61 | } else { 62 | resolve(true) 63 | } 64 | }) 65 | }) 66 | } 67 | // 路径是否存在,不存在则创建 68 | async dirExists (dir) { 69 | let isExists = await this.getStat(dir), tempDir, status, mkdirStatus 70 | // 如果该路径存在且不是文件,返回true 71 | if (isExists && isExists.isDirectory()) { 72 | return true 73 | } else if (isExists) { // 如果该路径存在但是文件,返回false 74 | return false 75 | } 76 | // 如果该路径不存在 77 | tempDir = path.parse(dir).dir // 拿到上级路径 78 | // 递归判断,如果上级目录也不存在,则会代码会在此处继续循环执行,直到目录存在 79 | status = await this.dirExists(tempDir) 80 | if (status) { 81 | mkdirStatus = await this.mkdir(dir) 82 | } 83 | return mkdirStatus 84 | } 85 | // TODO: 异常处理, 有时间扩展, 从这里转发到异常处理模块处理 86 | handleException (req, res, e) { 87 | // 写入日志 88 | NodeLog.writeLog(`\n异常发生时间${new Date()}: \n${e}`) 89 | 90 | res.json({ 91 | code: e.errno || 20501, 92 | success: false, 93 | content: e, 94 | message: '服务器内部错误' 95 | }) 96 | } 97 | } 98 | 99 | export default Base 100 | -------------------------------------------------------------------------------- /router/role.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Role from '../controller/Role' 3 | import ValidateRole from '../validate/Role' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Role/create 创建 9 | * @apiDescription 创建角色 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} pid 父ID 13 | * @apiParam (参数) {String} name 角色名称 14 | * @apiParam (参数) {String} columns 专栏数量 15 | * @apiParam (参数) {Number} users 可创建用户数 16 | * @apiParam (参数) {Number} desc 描述 17 | * @apiParam (参数) {String} status 状态: 0:停用,1:启用(默认为1) 18 | * @apiSampleRequest /api/Role/create 19 | * @apiGroup Role 20 | * @apiVersion 0.0.1 21 | */ 22 | router.post('/create', ValidateRole.create, Role.create) 23 | /** 24 | * 编辑 25 | * @api {put} /api/Role/update 编辑 26 | * @apiDescription 编辑 27 | * @apiName update 28 | * @apiHeader {String} Authorization token 29 | * @apiParam (参数) {Number} id 30 | * @apiParam (参数) {Number} pid 父ID 31 | * @apiParam (参数) {String} name 角色名称 32 | * @apiParam (参数) {String} columns 专栏数量 33 | * @apiParam (参数) {Number} users 可创建用户数 34 | * @apiParam (参数) {Number} desc 描述 35 | * @apiParam (参数) {String} status 状态: 0:停用,1:启用(默认为1) 36 | * @apiSampleRequest /api/Role/update 37 | * @apiGroup Role 38 | * @apiVersion 0.0.1 39 | */ 40 | router.put('/update', ValidateRole.update, Role.update) 41 | /** 42 | * 删除 43 | * @api {delete} /api/Role/delete/:id 删除 44 | * @apiDescription 删除 45 | * @apiName delete 46 | * @apiHeader {String} Authorization token 47 | * @apiParam {Number} id 48 | * @apiSampleRequest /api/Role/delete 49 | * @apiGroup Role 50 | * @apiVersion 0.0.1 51 | */ 52 | router.delete('/delete/:id', ValidateRole.delete, Role.delete) 53 | 54 | /** 55 | * 获取角色信息 56 | * @api {get} /api/Role/getRow 获取角色信息 57 | * @apiDescription 获取角色信息 58 | * @apiName getRow 59 | * @apiHeader {String} Authorization token 60 | * @apiParam {Number} id 61 | * @apiSampleRequest /api/Role/getRow 62 | * @apiGroup Role 63 | * @apiVersion 0.0.1 64 | */ 65 | router.get('/getRow/:id', ValidateRole.getRow, Role.getRow) 66 | /** 67 | * 获取角色列表 68 | * @api {get} /api/Role/getList 获取角色列表 69 | * @apiDescription 获取角色列表 70 | * @apiName getList 71 | * @apiHeader {String} Authorization token 72 | * @apiParam (path参数) {Number} curPage 73 | * @apiParam (path参数) {Number} pageSize 74 | * @apiParam (path参数) {String} name 角色名称 75 | * @apiSampleRequest /api/Role/getList 76 | * @apiGroup Role 77 | * @apiVersion 0.0.1 78 | */ 79 | router.get('/getList', ValidateRole.getList, Role.getList) 80 | /** 81 | * 获取所有角色 82 | * @api {get} /api/Role/getAll 获取所有角色 83 | * @apiDescription 获取所有角色 84 | * @apiName getAll 85 | * @apiHeader {String} Authorization token 86 | * @apiSampleRequest /api/Role/getAll 87 | * @apiGroup Role 88 | * @apiVersion 0.0.1 89 | */ 90 | router.get('/getAll', ValidateRole.getAll, Role.getAll) 91 | 92 | export default router 93 | -------------------------------------------------------------------------------- /router/index.js: -------------------------------------------------------------------------------- 1 | import Authority from '../controller/Authority' 2 | import user from './user' 3 | import area from './area' 4 | import role from './role' 5 | import menu from './menu' 6 | import dataPerms from './dataPerms' 7 | import roleRelation from './roleRelation' 8 | import log from './log' 9 | import folder from './folder' 10 | import file from './file' 11 | import tag from './tag' 12 | import tagType from './tagType' 13 | import tagRelation from './tagRelation' 14 | import carousel from './carousel' 15 | import techSquare from './techSquare' 16 | import notices from './notices' 17 | import question from './question' 18 | import column from './column' 19 | import article from './article' 20 | import articleComments from './articleComments' 21 | import draft from './draft' 22 | import count from './count' 23 | import charts from './charts' 24 | import topic from './topic' 25 | 26 | /** 27 | * 路由中间件 28 | * 第一层验证Token 29 | * 第二层验证用户是否有操作权限 30 | * 第三层验证参数, 验证成功后再进行事件处理 31 | */ 32 | export default app => { 33 | // 图表数据 34 | app.use('/api/charts', Authority.checkToken, Authority.permissions, charts) 35 | // 数据统计 36 | app.use('/api/count', Authority.checkToken, Authority.permissions, count) 37 | // 运维中心 38 | app.use('/api/question', Authority.checkToken, Authority.permissions, question) 39 | app.use('/api/column', Authority.checkToken, Authority.permissions, column) 40 | app.use('/api/article', Authority.checkToken, Authority.permissions, article) 41 | app.use('/api/articleComments', Authority.checkToken, Authority.permissions, articleComments) 42 | app.use('/api/draft', Authority.checkToken, Authority.permissions, draft) 43 | // 论坛配置 44 | app.use('/api/carousel', Authority.checkToken, Authority.permissions, carousel) 45 | app.use('/api/techSquare', Authority.checkToken, Authority.permissions, techSquare) 46 | app.use('/api/notices', Authority.checkToken, Authority.permissions, notices) 47 | app.use('/api/tagRelation', Authority.checkToken, Authority.permissions, tagRelation) 48 | app.use('/api/tagType', Authority.checkToken, Authority.permissions, tagType) 49 | app.use('/api/tag', Authority.checkToken, Authority.permissions, tag) 50 | // 文件库 51 | app.use('/api/folder', Authority.checkToken, Authority.permissions, folder) 52 | app.use('/api/file', Authority.checkToken, Authority.permissions, file) 53 | // 系统设置 54 | app.use('/api/user', Authority.checkToken, Authority.permissions, user) 55 | app.use('/api/area', Authority.checkToken, Authority.permissions, area) 56 | app.use('/api/role', Authority.checkToken, Authority.permissions, role) 57 | app.use('/api/menu', Authority.checkToken, Authority.permissions, menu) 58 | app.use('/api/dataPerms', Authority.checkToken, Authority.permissions, dataPerms) 59 | app.use('/api/roleRelation', Authority.checkToken, Authority.permissions, roleRelation) 60 | app.use('/api/log', Authority.checkToken, Authority.permissions, log) 61 | app.use('/api/topic', Authority.checkToken, Authority.permissions, topic) 62 | } 63 | -------------------------------------------------------------------------------- /router/column.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Column from '../controller/Column' 3 | import ValidateColumn from '../validate/Column' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Column/create 创建 9 | * @apiDescription 创建专栏 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {String} title 标题 13 | * @apiParam (参数) {String} image 图片地址 14 | * @apiParam (参数) {Number} click 点击触发类型 15 | * @apiParam (参数) {String} href 跳转地址 16 | * @apiParam (参数) {Number} sort 排序 17 | * @apiParam (参数) {String} desc 描述 18 | * @apiParam (参数) {Number} status 状态 19 | * @apiSampleRequest /api/Column/create 20 | * @apiGroup Column 21 | * @apiVersion 0.0.1 22 | */ 23 | router.post('/create', ValidateColumn.create, Column.create) 24 | /** 25 | * 编辑 26 | * @api {put} /api/Column/update 编辑 27 | * @apiDescription 编辑 28 | * @apiName update 29 | * @apiHeader {String} Authorization token 30 | * @apiParam (参数) {Number} id 31 | * @apiParam (参数) {String} title 标题 32 | * @apiParam (参数) {String} image 图片地址 33 | * @apiParam (参数) {Number} click 点击触发类型 34 | * @apiParam (参数) {String} href 跳转地址 35 | * @apiParam (参数) {Number} sort 排序 36 | * @apiParam (参数) {String} desc 描述 37 | * @apiParam (参数) {Number} status 状态 38 | * @apiSampleRequest /api/Column/update 39 | * @apiGroup Column 40 | * @apiVersion 0.0.1 41 | */ 42 | router.put('/update', ValidateColumn.update, Column.update) 43 | /** 44 | * 删除 45 | * @api {delete} /api/Column/delete/:id 删除 46 | * @apiDescription 删除 47 | * @apiName delete 48 | * @apiHeader {String} Authorization token 49 | * @apiParam {Number} id 50 | * @apiSampleRequest /api/Column/delete 51 | * @apiGroup Column 52 | * @apiVersion 0.0.1 53 | */ 54 | router.delete('/delete/:id', ValidateColumn.delete, Column.delete) 55 | 56 | /** 57 | * 获取专栏信息 58 | * @api {get} /api/Column/getRow 获取专栏信息 59 | * @apiDescription 获取专栏信息 60 | * @apiName getRow 61 | * @apiHeader {String} Authorization token 62 | * @apiParam {Number} id 63 | * @apiSampleRequest /api/Column/getRow 64 | * @apiGroup Column 65 | * @apiVersion 0.0.1 66 | */ 67 | router.get('/getRow/:id', ValidateColumn.getRow, Column.getRow) 68 | /** 69 | * 获取专栏列表 70 | * @api {get} /api/Column/getList 获取专栏列表 71 | * @apiDescription 获取专栏列表 72 | * @apiName getList 73 | * @apiHeader {String} Authorization token 74 | * @apiParam (path参数) {Number} curPage 75 | * @apiParam (path参数) {Number} pageSize 76 | * @apiSampleRequest /api/Column/getList 77 | * @apiGroup Column 78 | * @apiVersion 0.0.1 79 | */ 80 | router.get('/getList', ValidateColumn.getList, Column.getList) 81 | /** 82 | * 获取所有专栏 83 | * @api {get} /api/Column/getAll 获取所有专栏 84 | * @apiDescription 获取所有专栏 85 | * @apiName getAll 86 | * @apiParam {Number} type 87 | * @apiHeader {String} Authorization token 88 | * @apiSampleRequest /api/Column/getAll 89 | * @apiGroup Column 90 | * @apiVersion 0.0.1 91 | */ 92 | router.get('/getAll', ValidateColumn.getAll, Column.getAll) 93 | 94 | export default router 95 | -------------------------------------------------------------------------------- /validate/File.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Menu extends Base{ 4 | constructor () { 5 | super() 6 | this.upload = this.upload.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async upload (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: '目录ID', value: params.fid, rules: ['notnull', 'number']}, 17 | ], 18 | result = this.check(arr) 19 | if (!result.success) { 20 | res.json({ 21 | code: 20301, 22 | success: false, 23 | message: result.message 24 | }) 25 | return 26 | } 27 | next() 28 | } 29 | async update (req, res, next) { 30 | const params = req.body, 31 | arr = [ 32 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 33 | {label: '目录ID', value: params.f_id, rules: ['notnull', 'number']} 34 | ], 35 | result = this.check(arr) 36 | if (!result.success) { 37 | res.json({ 38 | code: 20301, 39 | success: false, 40 | message: result.message 41 | }) 42 | return 43 | } 44 | next() 45 | } 46 | async delete (req, res, next) { 47 | const ID = req.params.id, 48 | arr = [ 49 | {label: 'ID', value: ID, rules: ['notnull']} 50 | ], 51 | result = this.check(arr) 52 | if (!result.success) { 53 | res.json({ 54 | code: 20301, 55 | success: false, 56 | message: result.message 57 | }) 58 | return 59 | } 60 | next() 61 | } 62 | async getRow (req, res, next) { 63 | const ID = req.params.id, 64 | arr = [ 65 | {label: 'ID', value: ID, rules: ['notnull']} 66 | ], 67 | result = this.check(arr) 68 | if (!result.success) { 69 | res.json({ 70 | code: 20301, 71 | success: false, 72 | message: result.message 73 | }) 74 | return 75 | } 76 | next() 77 | } 78 | async getList (req, res, next) { 79 | const data = req.query, 80 | arr = [ 81 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 82 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 83 | ], 84 | result = this.check(arr) 85 | if (!result.success) { 86 | res.json({ 87 | code: 20301, 88 | success: false, 89 | message: result.message 90 | }) 91 | return 92 | } 93 | next() 94 | } 95 | async getRoleMenu (req, res, next) { 96 | next() 97 | } 98 | async getAll (req, res, next) { 99 | next() 100 | } 101 | } 102 | 103 | export default new Menu() 104 | -------------------------------------------------------------------------------- /router/article.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Article from '../controller/Article' 3 | import ValidateArticle from '../validate/Article' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Article/create 创建 9 | * @apiDescription 创建文章 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {String} title 标题 13 | * @apiParam (参数) {String} image 图片地址 14 | * @apiParam (参数) {Number} click 点击触发类型 15 | * @apiParam (参数) {String} href 跳转地址 16 | * @apiParam (参数) {Number} sort 排序 17 | * @apiParam (参数) {String} desc 描述 18 | * @apiParam (参数) {Number} status 状态 19 | * @apiSampleRequest /api/Article/create 20 | * @apiGroup Article 21 | * @apiVersion 0.0.1 22 | */ 23 | router.post('/create', ValidateArticle.create, Article.create) 24 | /** 25 | * 编辑 26 | * @api {put} /api/Article/update 编辑 27 | * @apiDescription 编辑 28 | * @apiName update 29 | * @apiHeader {String} Authorization token 30 | * @apiParam (参数) {Number} id 31 | * @apiParam (参数) {String} title 标题 32 | * @apiParam (参数) {String} image 图片地址 33 | * @apiParam (参数) {Number} click 点击触发类型 34 | * @apiParam (参数) {String} href 跳转地址 35 | * @apiParam (参数) {Number} sort 排序 36 | * @apiParam (参数) {String} desc 描述 37 | * @apiParam (参数) {Number} status 状态 38 | * @apiSampleRequest /api/Article/update 39 | * @apiGroup Article 40 | * @apiVersion 0.0.1 41 | */ 42 | router.put('/update', ValidateArticle.update, Article.update) 43 | /** 44 | * 删除 45 | * @api {delete} /api/Article/delete/:id 删除 46 | * @apiDescription 删除 47 | * @apiName delete 48 | * @apiHeader {String} Authorization token 49 | * @apiParam {Number} id 50 | * @apiSampleRequest /api/Article/delete 51 | * @apiGroup Article 52 | * @apiVersion 0.0.1 53 | */ 54 | router.delete('/delete/:id', ValidateArticle.delete, Article.delete) 55 | 56 | /** 57 | * 获取文章信息 58 | * @api {get} /api/Article/getRow 获取文章信息 59 | * @apiDescription 获取文章信息 60 | * @apiName getRow 61 | * @apiHeader {String} Authorization token 62 | * @apiParam {Number} id 63 | * @apiSampleRequest /api/Article/getRow 64 | * @apiGroup Article 65 | * @apiVersion 0.0.1 66 | */ 67 | router.get('/getRow/:id', ValidateArticle.getRow, Article.getRow) 68 | /** 69 | * 获取文章列表 70 | * @api {get} /api/Article/getList 获取文章列表 71 | * @apiDescription 获取文章列表 72 | * @apiName getList 73 | * @apiHeader {String} Authorization token 74 | * @apiParam (path参数) {Number} curPage 75 | * @apiParam (path参数) {Number} pageSize 76 | * @apiSampleRequest /api/Article/getList 77 | * @apiGroup Article 78 | * @apiVersion 0.0.1 79 | */ 80 | router.get('/getList', ValidateArticle.getList, Article.getList) 81 | /** 82 | * 获取所有文章 83 | * @api {get} /api/Article/getAll 获取所有文章 84 | * @apiDescription 获取所有文章 85 | * @apiName getAll 86 | * @apiParam {Number} type 87 | * @apiHeader {String} Authorization token 88 | * @apiSampleRequest /api/Article/getAll 89 | * @apiGroup Article 90 | * @apiVersion 0.0.1 91 | */ 92 | router.get('/getAll', ValidateArticle.getAll, Article.getAll) 93 | 94 | export default router 95 | -------------------------------------------------------------------------------- /router/question.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Question from '../controller/Question' 3 | import ValidateQuestion from '../validate/Question' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Question/create 创建 9 | * @apiDescription 创建问题 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} pid 父ID 13 | * @apiParam (参数) {String} name 问题名称 14 | * @apiParam (参数) {String} columns 专栏数量 15 | * @apiParam (参数) {Number} users 可创建用户数 16 | * @apiParam (参数) {Number} desc 描述 17 | * @apiParam (参数) {String} status 状态: 0:停用,1:启用(默认为1) 18 | * @apiSampleRequest /api/Question/create 19 | * @apiGroup Question 20 | * @apiVersion 0.0.1 21 | */ 22 | router.post('/create', ValidateQuestion.create, Question.create) 23 | /** 24 | * 编辑 25 | * @api {put} /api/Question/update 编辑 26 | * @apiDescription 编辑 27 | * @apiName update 28 | * @apiHeader {String} Authorization token 29 | * @apiParam (参数) {Number} id 30 | * @apiParam (参数) {Number} pid 父ID 31 | * @apiParam (参数) {String} name 问题名称 32 | * @apiParam (参数) {String} columns 专栏数量 33 | * @apiParam (参数) {Number} users 可创建用户数 34 | * @apiParam (参数) {Number} desc 描述 35 | * @apiParam (参数) {String} status 状态: 0:停用,1:启用(默认为1) 36 | * @apiSampleRequest /api/Question/update 37 | * @apiGroup Question 38 | * @apiVersion 0.0.1 39 | */ 40 | router.put('/update', ValidateQuestion.update, Question.update) 41 | /** 42 | * 删除 43 | * @api {delete} /api/Question/delete/:id 删除 44 | * @apiDescription 删除 45 | * @apiName delete 46 | * @apiHeader {String} Authorization token 47 | * @apiParam {Number} id 48 | * @apiSampleRequest /api/Question/delete 49 | * @apiGroup Question 50 | * @apiVersion 0.0.1 51 | */ 52 | router.delete('/delete/:id', ValidateQuestion.delete, Question.delete) 53 | 54 | /** 55 | * 获取问题信息 56 | * @api {get} /api/Question/getRow 获取问题信息 57 | * @apiDescription 获取问题信息 58 | * @apiName getRow 59 | * @apiHeader {String} Authorization token 60 | * @apiParam {Number} id 61 | * @apiSampleRequest /api/Question/getRow 62 | * @apiGroup Question 63 | * @apiVersion 0.0.1 64 | */ 65 | router.get('/getRow/:id', ValidateQuestion.getRow, Question.getRow) 66 | /** 67 | * 获取问题列表 68 | * @api {get} /api/Question/getList 获取问题列表 69 | * @apiDescription 获取问题列表 70 | * @apiName getList 71 | * @apiHeader {String} Authorization token 72 | * @apiParam (path参数) {Number} curPage 73 | * @apiParam (path参数) {Number} pageSize 74 | * @apiParam (path参数) {String} name 问题名称 75 | * @apiSampleRequest /api/Question/getList 76 | * @apiGroup Question 77 | * @apiVersion 0.0.1 78 | */ 79 | router.get('/getList', ValidateQuestion.getList, Question.getList) 80 | /** 81 | * 获取所有问题 82 | * @api {get} /api/Question/getAll 获取所有问题 83 | * @apiDescription 获取所有问题 84 | * @apiName getAll 85 | * @apiHeader {String} Authorization token 86 | * @apiSampleRequest /api/Question/getAll 87 | * @apiGroup Question 88 | * @apiVersion 0.0.1 89 | */ 90 | router.get('/getAll', ValidateQuestion.getAll, Question.getAll) 91 | 92 | export default router 93 | -------------------------------------------------------------------------------- /router/carousel.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Carousel from '../controller/Carousel' 3 | import ValidateCarousel from '../validate/Carousel' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Carousel/create 创建 9 | * @apiDescription 创建轮播 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {String} title 标题 13 | * @apiParam (参数) {String} image 图片地址 14 | * @apiParam (参数) {Number} click 点击触发类型 15 | * @apiParam (参数) {String} href 跳转地址 16 | * @apiParam (参数) {Number} sort 排序 17 | * @apiParam (参数) {String} desc 描述 18 | * @apiParam (参数) {Number} status 状态 19 | * @apiSampleRequest /api/Carousel/create 20 | * @apiGroup Carousel 21 | * @apiVersion 0.0.1 22 | */ 23 | router.post('/create', ValidateCarousel.create, Carousel.create) 24 | /** 25 | * 编辑 26 | * @api {put} /api/Carousel/update 编辑 27 | * @apiDescription 编辑 28 | * @apiName update 29 | * @apiHeader {String} Authorization token 30 | * @apiParam (参数) {Number} id 31 | * @apiParam (参数) {String} title 标题 32 | * @apiParam (参数) {String} image 图片地址 33 | * @apiParam (参数) {Number} click 点击触发类型 34 | * @apiParam (参数) {String} href 跳转地址 35 | * @apiParam (参数) {Number} sort 排序 36 | * @apiParam (参数) {String} desc 描述 37 | * @apiParam (参数) {Number} status 状态 38 | * @apiSampleRequest /api/Carousel/update 39 | * @apiGroup Carousel 40 | * @apiVersion 0.0.1 41 | */ 42 | router.put('/update', ValidateCarousel.update, Carousel.update) 43 | /** 44 | * 删除 45 | * @api {delete} /api/Carousel/delete/:id 删除 46 | * @apiDescription 删除 47 | * @apiName delete 48 | * @apiHeader {String} Authorization token 49 | * @apiParam {Number} id 50 | * @apiSampleRequest /api/Carousel/delete 51 | * @apiGroup Carousel 52 | * @apiVersion 0.0.1 53 | */ 54 | router.delete('/delete/:id', ValidateCarousel.delete, Carousel.delete) 55 | 56 | /** 57 | * 获取轮播信息 58 | * @api {get} /api/Carousel/getRow 获取轮播信息 59 | * @apiDescription 获取轮播信息 60 | * @apiName getRow 61 | * @apiHeader {String} Authorization token 62 | * @apiParam {Number} id 63 | * @apiSampleRequest /api/Carousel/getRow 64 | * @apiGroup Carousel 65 | * @apiVersion 0.0.1 66 | */ 67 | router.get('/getRow/:id', ValidateCarousel.getRow, Carousel.getRow) 68 | /** 69 | * 获取轮播列表 70 | * @api {get} /api/Carousel/getList 获取轮播列表 71 | * @apiDescription 获取轮播列表 72 | * @apiName getList 73 | * @apiHeader {String} Authorization token 74 | * @apiParam (path参数) {Number} curPage 75 | * @apiParam (path参数) {Number} pageSize 76 | * @apiSampleRequest /api/Carousel/getList 77 | * @apiGroup Carousel 78 | * @apiVersion 0.0.1 79 | */ 80 | router.get('/getList', ValidateCarousel.getList, Carousel.getList) 81 | /** 82 | * 获取所有轮播 83 | * @api {get} /api/Carousel/getAll 获取所有轮播 84 | * @apiDescription 获取所有轮播 85 | * @apiName getAll 86 | * @apiParam {Number} type 87 | * @apiHeader {String} Authorization token 88 | * @apiSampleRequest /api/Carousel/getAll 89 | * @apiGroup Carousel 90 | * @apiVersion 0.0.1 91 | */ 92 | router.get('/getAll', ValidateCarousel.getAll, Carousel.getAll) 93 | 94 | export default router 95 | -------------------------------------------------------------------------------- /model/Role.js: -------------------------------------------------------------------------------- 1 | import mysql from 'mysql' 2 | import query from '../mysql' 3 | import Base from './Base' 4 | import utils from '../lib/js/utils' 5 | 6 | class Role extends Base{ 7 | constructor () { 8 | super() 9 | this.create = this.create.bind(this) 10 | this.update = this.update.bind(this) 11 | this.delete = this.delete.bind(this) 12 | this.getRow = this.getRow.bind(this) 13 | this.getList = this.getList.bind(this) 14 | this.getTotals = this.getTotals.bind(this) 15 | this.getAll = this.getAll.bind(this) 16 | } 17 | async create (obj) { 18 | let sql = `INSERT INTO bbs_role set ${this.joinStr('set', obj.set)};` 19 | return query(sql) 20 | } 21 | async update (obj) { 22 | let sql = `UPDATE bbs_role set ${this.joinStr('set', obj.set)} where 1 = 1 ${this.joinStr('get', obj.get)};` 23 | return query(sql) 24 | } 25 | async delete (obj) { 26 | let sql = `DELETE from bbs_role where 1 = 1 ${this.joinStr('get', obj.get)};` 27 | return query(sql) 28 | } 29 | async getRow (obj) { 30 | let sql = `select * from bbs_role where 1 = 1 ${this.joinStr('get', obj.get)};` 31 | return query(sql) 32 | } 33 | async getList (obj) { 34 | let curPage = obj.get.curPage, pageSize = obj.get.pageSize 35 | let sql = `select a.*, b.name as create_user_name, c.name as update_user_name from bbs_role as a 36 | left join bbs_user as b on a.create_user = b.id 37 | left join bbs_user as c on a.update_user = c.id 38 | where 1 = 1 ${this.joinStr('get', obj.get)} limit ${(curPage - 1) * pageSize}, ${pageSize};` 39 | return query(sql) 40 | } 41 | async getTotals (obj) { 42 | let sql = `select COUNT(*) as count from bbs_role where 1 = 1 ${this.joinStr('get', obj.get)};` 43 | return query(sql) 44 | } 45 | async getAll (obj) { 46 | // 查询到当前角色和当前角色的所有下级角色 47 | let sql, createRoleList = await this.getCreateRole(obj.get.id) 48 | try { 49 | sql = `select a.*, b.name as create_user_name, c.name as update_user_name, d.name as pName from bbs_role as a 50 | left join bbs_user as b on a.create_user = b.id 51 | left join bbs_user as c on a.update_user = c.id 52 | left join bbs_role as d on a.pid = d.id 53 | where 1 = 1 and a.id in (${mysql.escape([obj.get.id, ...createRoleList])}) and a.flag = 1;` 54 | } catch (e) { 55 | return e 56 | } 57 | return query(sql) 58 | } 59 | async getCreateRole (rootPValue) { 60 | let roleList, roleTree, createRoleList = [] 61 | // 获取到所有的角色数据 62 | roleList = await query(`select id, pid from bbs_role;`) 63 | // 通过建立树状数据,得到当前用户创建的角色树 64 | roleTree = utils.getTreeArr({key: 'id', pKey: 'pid', data: roleList, rootPValue: +rootPValue}) 65 | // 递归得到所有创建的角色 66 | getRole(roleTree) 67 | function getRole (arr) { 68 | for (let val of arr) { 69 | createRoleList.push(val.id) 70 | if (val.children.length) { 71 | getRole(val.children) 72 | } 73 | } 74 | } 75 | return createRoleList 76 | } 77 | } 78 | 79 | export default new Role() 80 | -------------------------------------------------------------------------------- /router/techSquare.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import TechSquare from '../controller/TechSquare' 3 | import ValidateTechSquare from '../validate/TechSquare' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/TechSquare/create 创建 9 | * @apiDescription 创建技术频道 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {String} title 标题 13 | * @apiParam (参数) {String} image 图片地址 14 | * @apiParam (参数) {Number} click 点击触发类型 15 | * @apiParam (参数) {String} href 跳转地址 16 | * @apiParam (参数) {Number} sort 排序 17 | * @apiParam (参数) {String} desc 描述 18 | * @apiParam (参数) {Number} status 状态 19 | * @apiSampleRequest /api/TechSquare/create 20 | * @apiGroup TechSquare 21 | * @apiVersion 0.0.1 22 | */ 23 | router.post('/create', ValidateTechSquare.create, TechSquare.create) 24 | /** 25 | * 编辑 26 | * @api {put} /api/TechSquare/update 编辑 27 | * @apiDescription 编辑 28 | * @apiName update 29 | * @apiHeader {String} Authorization token 30 | * @apiParam (参数) {Number} id 31 | * @apiParam (参数) {String} title 标题 32 | * @apiParam (参数) {String} image 图片地址 33 | * @apiParam (参数) {Number} click 点击触发类型 34 | * @apiParam (参数) {String} href 跳转地址 35 | * @apiParam (参数) {Number} sort 排序 36 | * @apiParam (参数) {String} desc 描述 37 | * @apiParam (参数) {Number} status 状态 38 | * @apiSampleRequest /api/TechSquare/update 39 | * @apiGroup TechSquare 40 | * @apiVersion 0.0.1 41 | */ 42 | router.put('/update', ValidateTechSquare.update, TechSquare.update) 43 | /** 44 | * 删除 45 | * @api {delete} /api/TechSquare/delete/:id 删除 46 | * @apiDescription 删除 47 | * @apiName delete 48 | * @apiHeader {String} Authorization token 49 | * @apiParam {Number} id 50 | * @apiSampleRequest /api/TechSquare/delete 51 | * @apiGroup TechSquare 52 | * @apiVersion 0.0.1 53 | */ 54 | router.delete('/delete/:id', ValidateTechSquare.delete, TechSquare.delete) 55 | 56 | /** 57 | * 获取技术频道信息 58 | * @api {get} /api/TechSquare/getRow 获取技术频道信息 59 | * @apiDescription 获取技术频道信息 60 | * @apiName getRow 61 | * @apiHeader {String} Authorization token 62 | * @apiParam {Number} id 63 | * @apiSampleRequest /api/TechSquare/getRow 64 | * @apiGroup TechSquare 65 | * @apiVersion 0.0.1 66 | */ 67 | router.get('/getRow/:id', ValidateTechSquare.getRow, TechSquare.getRow) 68 | /** 69 | * 获取技术频道列表 70 | * @api {get} /api/TechSquare/getList 获取技术频道列表 71 | * @apiDescription 获取技术频道列表 72 | * @apiName getList 73 | * @apiHeader {String} Authorization token 74 | * @apiParam (path参数) {Number} curPage 75 | * @apiParam (path参数) {Number} pageSize 76 | * @apiSampleRequest /api/TechSquare/getList 77 | * @apiGroup TechSquare 78 | * @apiVersion 0.0.1 79 | */ 80 | router.get('/getList', ValidateTechSquare.getList, TechSquare.getList) 81 | /** 82 | * 获取所有技术频道 83 | * @api {get} /api/TechSquare/getAll 获取所有技术频道 84 | * @apiDescription 获取所有技术频道 85 | * @apiName getAll 86 | * @apiParam {Number} type 87 | * @apiHeader {String} Authorization token 88 | * @apiSampleRequest /api/TechSquare/getAll 89 | * @apiGroup TechSquare 90 | * @apiVersion 0.0.1 91 | */ 92 | router.get('/getAll', ValidateTechSquare.getAll, TechSquare.getAll) 93 | 94 | export default router 95 | -------------------------------------------------------------------------------- /validate/Column.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Column extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: '标题', value: params.title, rules: ['notnull']}, 17 | {label: '内容', value: params.content, rules: ['notnull']}, 18 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 19 | ], 20 | result = this.check(arr) 21 | if (!result.success) { 22 | res.json({ 23 | code: 20301, 24 | success: false, 25 | message: result.message 26 | }) 27 | return 28 | } 29 | next() 30 | } 31 | async update (req, res, next) { 32 | const params = req.body, 33 | arr = [ 34 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 35 | {label: '标题', value: params.title, rules: ['notnull']}, 36 | {label: '内容', value: params.content, rules: ['notnull']}, 37 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 38 | ], 39 | result = this.check(arr) 40 | if (!result.success) { 41 | res.json({ 42 | code: 20301, 43 | success: false, 44 | message: result.message 45 | }) 46 | return 47 | } 48 | next() 49 | } 50 | async delete (req, res, next) { 51 | const ID = req.params.id, 52 | arr = [ 53 | {label: 'ID', value: ID, rules: ['notnull']} 54 | ], 55 | result = this.check(arr) 56 | if (!result.success) { 57 | res.json({ 58 | code: 20301, 59 | success: false, 60 | message: result.message 61 | }) 62 | return 63 | } 64 | next() 65 | } 66 | async getRow (req, res, next) { 67 | const ID = req.params.id, 68 | arr = [ 69 | {label: 'ID', value: ID, rules: ['notnull']} 70 | ], 71 | result = this.check(arr) 72 | if (!result.success) { 73 | res.json({ 74 | code: 20301, 75 | success: false, 76 | message: result.message 77 | }) 78 | return 79 | } 80 | next() 81 | } 82 | async getList (req, res, next) { 83 | const data = req.query, 84 | arr = [ 85 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 86 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 87 | ], 88 | result = this.check(arr) 89 | if (!result.success) { 90 | res.json({ 91 | code: 20301, 92 | success: false, 93 | message: result.message 94 | }) 95 | return 96 | } 97 | next() 98 | } 99 | async getAll (req, res, next) { 100 | next() 101 | } 102 | } 103 | 104 | export default new Column() 105 | -------------------------------------------------------------------------------- /validate/Question.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Question extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: '标题', value: params.title, rules: ['notnull']}, 17 | {label: '内容', value: params.content, rules: ['notnull']}, 18 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 19 | ], 20 | result = this.check(arr) 21 | if (!result.success) { 22 | res.json({ 23 | code: 20301, 24 | success: false, 25 | message: result.message 26 | }) 27 | return 28 | } 29 | next() 30 | } 31 | async update (req, res, next) { 32 | const params = req.body, 33 | arr = [ 34 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 35 | {label: '标题', value: params.title, rules: ['notnull']}, 36 | {label: '内容', value: params.content, rules: ['notnull']}, 37 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 38 | ], 39 | result = this.check(arr) 40 | if (!result.success) { 41 | res.json({ 42 | code: 20301, 43 | success: false, 44 | message: result.message 45 | }) 46 | return 47 | } 48 | next() 49 | } 50 | async delete (req, res, next) { 51 | const ID = req.params.id, 52 | arr = [ 53 | {label: 'ID', value: ID, rules: ['notnull']} 54 | ], 55 | result = this.check(arr) 56 | if (!result.success) { 57 | res.json({ 58 | code: 20301, 59 | success: false, 60 | message: result.message 61 | }) 62 | return 63 | } 64 | next() 65 | } 66 | async getRow (req, res, next) { 67 | const ID = req.params.id, 68 | arr = [ 69 | {label: 'ID', value: ID, rules: ['notnull']} 70 | ], 71 | result = this.check(arr) 72 | if (!result.success) { 73 | res.json({ 74 | code: 20301, 75 | success: false, 76 | message: result.message 77 | }) 78 | return 79 | } 80 | next() 81 | } 82 | async getList (req, res, next) { 83 | const data = req.query, 84 | arr = [ 85 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 86 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 87 | ], 88 | result = this.check(arr) 89 | if (!result.success) { 90 | res.json({ 91 | code: 20301, 92 | success: false, 93 | message: result.message 94 | }) 95 | return 96 | } 97 | next() 98 | } 99 | async getAll (req, res, next) { 100 | next() 101 | } 102 | } 103 | 104 | export default new Question() 105 | -------------------------------------------------------------------------------- /validate/Article.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Article extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: '标题', value: params.title, rules: ['notnull']} 17 | // {label: '内容', value: params.content, rules: ['notnull']}, 18 | // {label: '状态', value: params.status, rules: ['notnull', 'number']} 19 | ], 20 | result = this.check(arr) 21 | if (!result.success) { 22 | res.json({ 23 | code: 20301, 24 | success: false, 25 | message: result.message 26 | }) 27 | return 28 | } 29 | next() 30 | } 31 | async update (req, res, next) { 32 | const params = req.body, 33 | arr = [ 34 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 35 | {label: '标题', value: params.title, rules: ['notnull']} 36 | // {label: '内容', value: params.content, rules: ['notnull']}, 37 | // {label: '状态', value: params.status, rules: ['notnull', 'number']} 38 | ], 39 | result = this.check(arr) 40 | if (!result.success) { 41 | res.json({ 42 | code: 20301, 43 | success: false, 44 | message: result.message 45 | }) 46 | return 47 | } 48 | next() 49 | } 50 | async delete (req, res, next) { 51 | const ID = req.params.id, 52 | arr = [ 53 | {label: 'ID', value: ID, rules: ['notnull']} 54 | ], 55 | result = this.check(arr) 56 | if (!result.success) { 57 | res.json({ 58 | code: 20301, 59 | success: false, 60 | message: result.message 61 | }) 62 | return 63 | } 64 | next() 65 | } 66 | async getRow (req, res, next) { 67 | const ID = req.params.id, 68 | arr = [ 69 | {label: 'ID', value: ID, rules: ['notnull']} 70 | ], 71 | result = this.check(arr) 72 | if (!result.success) { 73 | res.json({ 74 | code: 20301, 75 | success: false, 76 | message: result.message 77 | }) 78 | return 79 | } 80 | next() 81 | } 82 | async getList (req, res, next) { 83 | const data = req.query, 84 | arr = [ 85 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 86 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 87 | ], 88 | result = this.check(arr) 89 | if (!result.success) { 90 | res.json({ 91 | code: 20301, 92 | success: false, 93 | message: result.message 94 | }) 95 | return 96 | } 97 | next() 98 | } 99 | async getAll (req, res, next) { 100 | next() 101 | } 102 | } 103 | 104 | export default new Article() 105 | -------------------------------------------------------------------------------- /validate/Folder.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Menu extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: 'pid', value: params.pid, rules: ['notnull', 'number']}, 17 | {label: '目录名称', value: params.name, rules: ['notnull']}, 18 | {label: '排序', value: params.sort, rules: ['notnull', 'number']} 19 | ], 20 | result = this.check(arr) 21 | if (!result.success) { 22 | res.json({ 23 | code: 20301, 24 | success: false, 25 | message: result.message 26 | }) 27 | return 28 | } 29 | next() 30 | } 31 | async update (req, res, next) { 32 | const params = req.body, 33 | arr = [ 34 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 35 | {label: 'pid', value: params.pid, rules: ['notnull', 'number']}, 36 | {label: '目录名称', value: params.name, rules: ['notnull']}, 37 | {label: '排序', value: params.sort, rules: ['notnull', 'number']} 38 | ], 39 | result = this.check(arr) 40 | if (!result.success) { 41 | res.json({ 42 | code: 20301, 43 | success: false, 44 | message: result.message 45 | }) 46 | return 47 | } 48 | next() 49 | } 50 | async delete (req, res, next) { 51 | const ID = req.params.id, 52 | arr = [ 53 | {label: 'ID', value: ID, rules: ['notnull']} 54 | ], 55 | result = this.check(arr) 56 | if (!result.success) { 57 | res.json({ 58 | code: 20301, 59 | success: false, 60 | message: result.message 61 | }) 62 | return 63 | } 64 | next() 65 | } 66 | async getRow (req, res, next) { 67 | const ID = req.params.id, 68 | arr = [ 69 | {label: 'ID', value: ID, rules: ['notnull']} 70 | ], 71 | result = this.check(arr) 72 | if (!result.success) { 73 | res.json({ 74 | code: 20301, 75 | success: false, 76 | message: result.message 77 | }) 78 | return 79 | } 80 | next() 81 | } 82 | async getList (req, res, next) { 83 | const data = req.query, 84 | arr = [ 85 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 86 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 87 | ], 88 | result = this.check(arr) 89 | if (!result.success) { 90 | res.json({ 91 | code: 20301, 92 | success: false, 93 | message: result.message 94 | }) 95 | return 96 | } 97 | next() 98 | } 99 | async getRoleMenu (req, res, next) { 100 | next() 101 | } 102 | async getAll (req, res, next) { 103 | next() 104 | } 105 | } 106 | 107 | export default new Menu() 108 | -------------------------------------------------------------------------------- /validate/Carousel.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Carousel extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: '标题', value: params.title, rules: ['notnull']}, 17 | {label: '轮播图片', value: params.image, rules: ['notnull']}, 18 | {label: '点击触发', value: params.click, rules: ['notnull', 'number']}, 19 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 20 | ], 21 | result = this.check(arr) 22 | if (!result.success) { 23 | res.json({ 24 | code: 20301, 25 | success: false, 26 | message: result.message 27 | }) 28 | return 29 | } 30 | next() 31 | } 32 | async update (req, res, next) { 33 | const params = req.body, 34 | arr = [ 35 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 36 | {label: '标题', value: params.title, rules: ['notnull']}, 37 | {label: '轮播图片', value: params.image, rules: ['notnull']}, 38 | {label: '点击触发', value: params.click, rules: ['notnull', 'number']}, 39 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 40 | ], 41 | result = this.check(arr) 42 | if (!result.success) { 43 | res.json({ 44 | code: 20301, 45 | success: false, 46 | message: result.message 47 | }) 48 | return 49 | } 50 | next() 51 | } 52 | async delete (req, res, next) { 53 | const ID = req.params.id, 54 | arr = [ 55 | {label: 'ID', value: ID, rules: ['notnull']} 56 | ], 57 | result = this.check(arr) 58 | if (!result.success) { 59 | res.json({ 60 | code: 20301, 61 | success: false, 62 | message: result.message 63 | }) 64 | return 65 | } 66 | next() 67 | } 68 | async getRow (req, res, next) { 69 | const ID = req.params.id, 70 | arr = [ 71 | {label: 'ID', value: ID, rules: ['notnull']} 72 | ], 73 | result = this.check(arr) 74 | if (!result.success) { 75 | res.json({ 76 | code: 20301, 77 | success: false, 78 | message: result.message 79 | }) 80 | return 81 | } 82 | next() 83 | } 84 | async getList (req, res, next) { 85 | const data = req.query, 86 | arr = [ 87 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 88 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 89 | ], 90 | result = this.check(arr) 91 | if (!result.success) { 92 | res.json({ 93 | code: 20301, 94 | success: false, 95 | message: result.message 96 | }) 97 | return 98 | } 99 | next() 100 | } 101 | async getAll (req, res, next) { 102 | next() 103 | } 104 | } 105 | 106 | export default new Carousel() 107 | -------------------------------------------------------------------------------- /validate/Role.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Role extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: 'pid', value: params.pid, rules: ['notnull', 'number']}, 17 | {label: '角色名称', value: params.name, rules: ['notnull']}, 18 | {label: '状态', value: params.status, rules: ['notnull']} 19 | ], 20 | result = this.check(arr) 21 | if (!result.success) { 22 | res.json({ 23 | code: 20301, 24 | success: false, 25 | message: result.message 26 | }) 27 | return 28 | } 29 | next() 30 | } 31 | async update (req, res, next) { 32 | const params = req.body, 33 | arr = [ 34 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 35 | {label: 'pid', value: params.pid, rules: ['notnull', 'number']}, 36 | {label: '角色名称', value: params.name, rules: ['notnull']}, 37 | {label: '状态', value: params.status, rules: ['notnull']} 38 | ], 39 | result = this.check(arr) 40 | if (!result.success) { 41 | res.json({ 42 | code: 20301, 43 | success: false, 44 | message: result.message 45 | }) 46 | return 47 | } 48 | next() 49 | } 50 | async delete (req, res, next) { 51 | const ID = req.params.id, 52 | arr = [ 53 | {label: 'ID', value: ID, rules: ['notnull']} 54 | ], 55 | result = this.check(arr) 56 | // 不能删除管理员 57 | if (ID === 1 || ID === '1') { 58 | res.json({ 59 | code: 20202, 60 | success: false, 61 | message: '无法删除管理员' 62 | }) 63 | return 64 | } 65 | if (!result.success) { 66 | res.json({ 67 | code: 20301, 68 | success: false, 69 | message: result.message 70 | }) 71 | return 72 | } 73 | next() 74 | } 75 | async getRow (req, res, next) { 76 | const ID = req.params.id, 77 | arr = [ 78 | {label: 'ID', value: ID, rules: ['notnull']} 79 | ], 80 | result = this.check(arr) 81 | if (!result.success) { 82 | res.json({ 83 | code: 20301, 84 | success: false, 85 | message: result.message 86 | }) 87 | return 88 | } 89 | next() 90 | } 91 | async getList (req, res, next) { 92 | const data = req.query, 93 | arr = [ 94 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 95 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 96 | ], 97 | result = this.check(arr) 98 | if (!result.success) { 99 | res.json({ 100 | code: 20301, 101 | success: false, 102 | message: result.message 103 | }) 104 | return 105 | } 106 | next() 107 | } 108 | async getAll (req, res, next) { 109 | next() 110 | } 111 | } 112 | 113 | export default new Role() 114 | -------------------------------------------------------------------------------- /validate/TechSquare.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class TechSquare extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | // {label: '标题', value: params.title, rules: ['notnull']}, 17 | // {label: '轮播图片', value: params.image, rules: ['notnull']}, 18 | // {label: '点击触发', value: params.click, rules: ['notnull', 'number']}, 19 | // {label: '状态', value: params.status, rules: ['notnull', 'number']} 20 | ], 21 | result = this.check(arr) 22 | if (!result.success) { 23 | res.json({ 24 | code: 20301, 25 | success: false, 26 | message: result.message 27 | }) 28 | return 29 | } 30 | next() 31 | } 32 | async update (req, res, next) { 33 | const params = req.body, 34 | arr = [ 35 | // {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 36 | // {label: '标题', value: params.title, rules: ['notnull']}, 37 | // {label: '轮播图片', value: params.image, rules: ['notnull']}, 38 | // {label: '点击触发', value: params.click, rules: ['notnull', 'number']}, 39 | // {label: '状态', value: params.status, rules: ['notnull', 'number']} 40 | ], 41 | result = this.check(arr) 42 | if (!result.success) { 43 | res.json({ 44 | code: 20301, 45 | success: false, 46 | message: result.message 47 | }) 48 | return 49 | } 50 | next() 51 | } 52 | async delete (req, res, next) { 53 | const ID = req.params.id, 54 | arr = [ 55 | {label: 'ID', value: ID, rules: ['notnull']} 56 | ], 57 | result = this.check(arr) 58 | if (!result.success) { 59 | res.json({ 60 | code: 20301, 61 | success: false, 62 | message: result.message 63 | }) 64 | return 65 | } 66 | next() 67 | } 68 | async getRow (req, res, next) { 69 | const ID = req.params.id, 70 | arr = [ 71 | {label: 'ID', value: ID, rules: ['notnull']} 72 | ], 73 | result = this.check(arr) 74 | if (!result.success) { 75 | res.json({ 76 | code: 20301, 77 | success: false, 78 | message: result.message 79 | }) 80 | return 81 | } 82 | next() 83 | } 84 | async getList (req, res, next) { 85 | const data = req.query, 86 | arr = [ 87 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 88 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 89 | ], 90 | result = this.check(arr) 91 | if (!result.success) { 92 | res.json({ 93 | code: 20301, 94 | success: false, 95 | message: result.message 96 | }) 97 | return 98 | } 99 | next() 100 | } 101 | async getAll (req, res, next) { 102 | next() 103 | } 104 | } 105 | 106 | export default new TechSquare() 107 | -------------------------------------------------------------------------------- /controller/Draft.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import ArticleModel from '../model/Article' 3 | import QuestionModel from '../model/Question' 4 | 5 | class Draft extends Base { 6 | constructor () { 7 | super() 8 | this.getTotals = this.getTotals.bind(this) 9 | this.getAll = this.getAll.bind(this) 10 | this.giveUp = this.giveUp.bind(this) 11 | this.giveUpAll = this.giveUpAll.bind(this) 12 | } 13 | // 查询草稿数量 14 | async getTotals (req, res, next) { 15 | const userInfo = await this.getUserInfo(req) 16 | let question, article 17 | try { 18 | question = await QuestionModel.getTotals({get: {create_user: userInfo.id, flag: 1}}) 19 | article = await ArticleModel.getTotals({get: {create_user: userInfo.id, flag: 1}}) 20 | } catch (e) { 21 | this.handleException(req, res, e) 22 | return 23 | } 24 | res.json({ 25 | code: 20000, 26 | success: true, 27 | content: { 28 | totals: question[0].count + article[0].count 29 | }, 30 | message: '操作成功' 31 | }) 32 | } 33 | // 查询所有的草稿 34 | async getAll (req, res, next) { 35 | const userInfo = await this.getUserInfo(req) 36 | let question, article, result 37 | try { 38 | question = await QuestionModel.getAll({get: {create_user: userInfo.id, flag: 1}}) 39 | article = await ArticleModel.getAll({get: {create_user: userInfo.id, flag: 1}}) 40 | } catch (e) { 41 | this.handleException(req, res, e) 42 | return 43 | } 44 | // 排序,处理 45 | result = [...question.map(item => { 46 | item.dataType = 1 47 | return item 48 | }), ...article.map(item => { 49 | item.dataType = 2 50 | return item 51 | })].sort((a, b) => b.id - a.id) 52 | res.json({ 53 | code: 20000, 54 | success: true, 55 | content: result, 56 | message: '操作成功' 57 | }) 58 | } 59 | // 舍弃草稿 60 | async giveUp (req, res, next) { 61 | let data = JSON.parse(JSON.stringify(req.body)), 62 | userInfo = await this.getUserInfo(req), 63 | result 64 | // dataType 1 问题 2 文章 65 | if (data.dataType === 1) { 66 | result = await QuestionModel.update({get: {id: data.id, create_user: userInfo.id}, set: {flag: 0}}) 67 | } else if (data.dataType === 2) { 68 | result = await ArticleModel.update({get: {id: data.id, create_user: userInfo.id}, set: {flag: 0}}) 69 | } else { 70 | return 71 | } 72 | if (!result) { 73 | res.json({ 74 | code: 20001, 75 | success: false, 76 | content: '操作人和操作数据不匹配', 77 | message: '操作失败' 78 | }) 79 | return 80 | } 81 | res.json({ 82 | code: 20000, 83 | success: true, 84 | content: result, 85 | message: '操作成功' 86 | }) 87 | } 88 | // 舍弃全部草稿 89 | async giveUpAll (req, res, next) { 90 | const userInfo = await this.getUserInfo(req) 91 | try { 92 | await QuestionModel.update({get: {create_user: userInfo.id, flag: 1}, set: {flag: 0}}) 93 | await ArticleModel.update({get: {create_user: userInfo.id, flag: 1}, set: {flag: 0}}) 94 | } catch (e) { 95 | this.handleException(req, res, e) 96 | return 97 | } 98 | res.json({ 99 | code: 20000, 100 | success: true, 101 | message: '操作成功' 102 | }) 103 | } 104 | } 105 | 106 | export default new Draft() 107 | -------------------------------------------------------------------------------- /router/dataPerms.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import DataPerms from '../controller/DataPerms' 3 | import ValidateDataPerms from '../validate/DataPerms' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/DataPerms/create 创建 9 | * @apiDescription 创建模块权限 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} menu_id 模块ID 13 | * @apiParam (参数) {String} name 名称 14 | * @apiParam (参数) {String} code 编码 15 | * @apiParam (参数) {String} type 类型 按钮或者其他 16 | * @apiParam (参数) {String} method 请求方式 17 | * @apiSampleRequest /api/DataPerms/create 18 | * @apiGroup DataPerms 19 | * @apiVersion 0.0.1 20 | */ 21 | router.post('/create', ValidateDataPerms.create, DataPerms.create) 22 | /** 23 | * 编辑 24 | * @api {put} /api/DataPerms/update 编辑 25 | * @apiDescription 编辑 26 | * @apiName update 27 | * @apiHeader {String} Authorization token 28 | * @apiParam (参数) {Number} id 29 | * @apiParam (参数) {Number} menu_id 模块ID 30 | * @apiParam (参数) {String} name 名称 31 | * @apiParam (参数) {String} code 编码 32 | * @apiParam (参数) {String} type 类型 按钮或者其他 33 | * @apiParam (参数) {String} method 请求方式 34 | * @apiSampleRequest /api/DataPerms/update 35 | * @apiGroup DataPerms 36 | * @apiVersion 0.0.1 37 | */ 38 | router.put('/update', ValidateDataPerms.update, DataPerms.update) 39 | /** 40 | * 删除 41 | * @api {delete} /api/DataPerms/delete/:id 删除 42 | * @apiDescription 删除 43 | * @apiName delete 44 | * @apiHeader {String} Authorization token 45 | * @apiParam {Number} id 46 | * @apiSampleRequest /api/DataPerms/delete 47 | * @apiGroup DataPerms 48 | * @apiVersion 0.0.1 49 | */ 50 | router.delete('/delete/:id', ValidateDataPerms.delete, DataPerms.delete) 51 | 52 | /** 53 | * 获取模块信息 54 | * @api {get} /api/DataPerms/getRow 获取模块信息 55 | * @apiDescription 获取模块权限信息 56 | * @apiName getRow 57 | * @apiHeader {String} Authorization token 58 | * @apiParam {Number} id 59 | * @apiSampleRequest /api/DataPerms/getRow 60 | * @apiGroup DataPerms 61 | * @apiVersion 0.0.1 62 | */ 63 | router.get('/getRow/:id', ValidateDataPerms.getRow, DataPerms.getRow) 64 | /** 65 | * 获取模块列表 66 | * @api {get} /api/DataPerms/getList 获取模块列表 67 | * @apiDescription 获取模块权限列表 68 | * @apiName getList 69 | * @apiHeader {String} Authorization token 70 | * @apiParam (path参数) {Number} menu_id 71 | * @apiSampleRequest /api/DataPerms/getList 72 | * @apiGroup DataPerms 73 | * @apiVersion 0.0.1 74 | */ 75 | router.get('/getList', ValidateDataPerms.getList, DataPerms.getList) 76 | /** 77 | * 获取用户拥有模块权限 78 | * @api {get} /api/DataPerms/getRoleDataPerms 获取用户拥有模块权限 79 | * @apiDescription 获取用户拥有模块权限 80 | * @apiName getRoleDataPerms 81 | * @apiHeader {String} Authorization token 82 | * @apiParam {Number} modId 83 | * @apiSampleRequest /api/DataPerms/getRoleDataPerms 84 | * @apiGroup DataPerms 85 | * @apiVersion 0.0.1 86 | */ 87 | router.get('/getRoleDataPerms', ValidateDataPerms.getRoleDataPerms, DataPerms.getRoleDataPerms) 88 | /** 89 | * 获取所有模块权限 90 | * @api {get} /api/DataPerms/getAll 获取所有模块权限 91 | * @apiDescription 获取所有模块权限 92 | * @apiName getAll 93 | * @apiHeader {String} Authorization token 94 | * @apiParam {Number} modId 95 | * @apiSampleRequest /api/DataPerms/getAll 96 | * @apiGroup DataPerms 97 | * @apiVersion 0.0.1 98 | */ 99 | router.get('/getAll', ValidateDataPerms.getAll, DataPerms.getAll) 100 | 101 | export default router 102 | -------------------------------------------------------------------------------- /log/index.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | import utils from '../lib/js/utils' 4 | import schedule from 'node-schedule' 5 | 6 | class Log { 7 | constructor () { 8 | this.clearLog(7) 9 | } 10 | /** 11 | * 写入日志 12 | * @param {String} type // 日志类型 err 错误日志 sql sql日志 13 | * @param {String} content 14 | */ 15 | async writeLog (content, type = 'err') { 16 | // 创建不存在的文件夹 17 | await this.dirExists(`log/file/${type}`) 18 | // 获取到文件files 19 | // fs.readFile(`log/file/${type}/${utils.switchTime(new Date(), 'YYYY-MM-DD')}.log`, (err, data) => { 20 | // if (err) { 21 | // console.log(err) 22 | // } 23 | // // 写入文件 24 | // fs.writeFile(`log/file/${type}/${utils.switchTime(new Date(), 'YYYY-MM-DD')}.log`, `${data || ''}\n${content}`, async (err) => { 25 | // if (err) { 26 | // console.log(err) 27 | // } 28 | // }) 29 | // }) 30 | // 写入文件 31 | fs.appendFile(`log/file/${type}/${utils.switchTime(new Date(), 'YYYY-MM-DD')}.log`, `\n${content}`, async (err) => { 32 | if (err) { 33 | console.log(err) 34 | } 35 | }) 36 | } 37 | // 定时清除日志 38 | async clearLog (day) { 39 | // 创建不存在的文件夹 40 | await this.dirExists(`log/file/sql`) 41 | await this.dirExists(`log/file/err`) 42 | const rule = new schedule.RecurrenceRule() 43 |   rule.dayOfWeek = [0, new schedule.Range(1, 6)] 44 |   rule.hour = 11; 45 |   rule.minute = 54; 46 |   schedule.scheduleJob(rule, () => { 47 | const sqlLogList = fs.readdirSync('log/file/sql') 48 | const errLogList = fs.readdirSync('log/file/err') 49 | const NOW = +new Date() 50 | sqlLogList.forEach(item => { 51 | const logDate = +new Date(item.replace('.log', '')) 52 | if (NOW - day * 24 * 3600 * 1000 > logDate) { 53 | fs.unlinkSync('log/file/sql/' + item) 54 | } 55 | }) 56 | errLogList.forEach(item => { 57 | const logDate = +new Date(item.replace('.log', '')) 58 | if (NOW - day * 24 * 3600 * 1000 > logDate) { 59 | fs.unlinkSync('log/file/err/' + item) 60 | } 61 | }) 62 |    console.log('每天定时删除不符合条件的文件') 63 |   }) 64 | } 65 | // 查询路径是否存在 66 | async getStat (path) { 67 | return new Promise((resolve, reject) => { 68 | fs.stat(path, (err, stats) => { 69 | if (err) { 70 | resolve(false) 71 | } else { 72 | resolve(stats) 73 | } 74 | }) 75 | }) 76 | } 77 | // 创建路径 78 | async mkdir(dir){ 79 | return new Promise((resolve, reject) => { 80 | fs.mkdir(dir, err => { 81 | if (err) { 82 | resolve(false) 83 | } else { 84 | resolve(true) 85 | } 86 | }) 87 | }) 88 | } 89 | // 路径是否存在,不存在则创建 90 | async dirExists (dir) { 91 | let isExists = await this.getStat(dir), tempDir, status, mkdirStatus 92 | // 如果该路径存在且不是文件,返回true 93 | if (isExists && isExists.isDirectory()) { 94 | return true 95 | } else if (isExists) { // 如果该路径存在但是文件,返回false 96 | return false 97 | } 98 | // 如果该路径不存在 99 | tempDir = path.parse(dir).dir // 拿到上级路径 100 | // 递归判断,如果上级目录也不存在,则会代码会在此处继续循环执行,直到目录存在 101 | status = await this.dirExists(tempDir) 102 | if (status) { 103 | mkdirStatus = await this.mkdir(dir) 104 | } 105 | return mkdirStatus 106 | } 107 | } 108 | 109 | export default new Log() 110 | -------------------------------------------------------------------------------- /validate/DataPerms.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class DataPerms extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: 'menu_id', value: params.menu_id, rules: ['notnull', 'number']}, 17 | {label: '类型', value: params.type, rules: ['notnull', 'number']}, 18 | {label: '编码', value: params.code, rules: ['notnull', 'noChinese']}, 19 | {label: '名称', value: params.name, rules: ['notnull']}, 20 | {label: '请求方式', value: params.method, rules: ['notnull', 'string']} 21 | ], 22 | result = this.check(arr) 23 | if (!result.success) { 24 | res.json({ 25 | code: 20301, 26 | success: false, 27 | message: result.message 28 | }) 29 | return 30 | } 31 | next() 32 | } 33 | async update (req, res, next) { 34 | const params = req.body, 35 | arr = [ 36 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 37 | {label: 'menu_id', value: params.menu_id, rules: ['notnull', 'number']}, 38 | {label: '类型', value: params.type, rules: ['notnull', 'number']}, 39 | {label: '编码', value: params.code, rules: ['notnull', 'noChinese']}, 40 | {label: '名称', value: params.name, rules: ['notnull']}, 41 | {label: '请求方式', value: params.method, rules: ['notnull', 'string']} 42 | ], 43 | result = this.check(arr) 44 | if (!result.success) { 45 | res.json({ 46 | code: 20301, 47 | success: false, 48 | message: result.message 49 | }) 50 | return 51 | } 52 | next() 53 | } 54 | async delete (req, res, next) { 55 | const ID = req.params.id, 56 | arr = [ 57 | {label: 'ID', value: ID, rules: ['notnull']} 58 | ], 59 | result = this.check(arr) 60 | if (!result.success) { 61 | res.json({ 62 | code: 20301, 63 | success: false, 64 | message: result.message 65 | }) 66 | return 67 | } 68 | next() 69 | } 70 | async getRow (req, res, next) { 71 | const ID = req.params.id, 72 | arr = [ 73 | {label: 'ID', value: ID, rules: ['notnull']} 74 | ], 75 | result = this.check(arr) 76 | if (!result.success) { 77 | res.json({ 78 | code: 20301, 79 | success: false, 80 | message: result.message 81 | }) 82 | return 83 | } 84 | next() 85 | } 86 | async getList (req, res, next) { 87 | const data = req.query, 88 | arr = [ 89 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 90 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 91 | ], 92 | result = this.check(arr) 93 | if (!result.success) { 94 | res.json({ 95 | code: 20301, 96 | success: false, 97 | message: result.message 98 | }) 99 | return 100 | } 101 | next() 102 | } 103 | async getRoleDataPerms (req, res, next) { 104 | next() 105 | } 106 | async getAll (req, res, next) { 107 | next() 108 | } 109 | } 110 | 111 | export default new DataPerms() 112 | -------------------------------------------------------------------------------- /validate/Menu.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | 3 | class Menu extends Base{ 4 | constructor () { 5 | super() 6 | this.create = this.create.bind(this) 7 | this.update = this.update.bind(this) 8 | this.delete = this.delete.bind(this) 9 | this.getRow = this.getRow.bind(this) 10 | this.getList = this.getList.bind(this) 11 | this.getAll = this.getAll.bind(this) 12 | } 13 | async create (req, res, next) { 14 | const params = req.body, 15 | arr = [ 16 | {label: 'pid', value: params.pid, rules: ['notnull', 'number']}, 17 | {label: '菜单类型', value: params.type, rules: ['notnull', 'number']}, 18 | {label: '菜单编码', value: params.code, rules: ['notnull', 'noChinese']}, 19 | {label: '菜单名称', value: params.name, rules: ['notnull']}, 20 | {label: '排序', value: params.sort, rules: ['notnull', 'number']}, 21 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 22 | ], 23 | result = this.check(arr) 24 | if (!result.success) { 25 | res.json({ 26 | code: 20301, 27 | success: false, 28 | message: result.message 29 | }) 30 | return 31 | } 32 | next() 33 | } 34 | async update (req, res, next) { 35 | const params = req.body, 36 | arr = [ 37 | {label: 'ID', value: params.id, rules: ['notnull', 'number']}, 38 | {label: 'pid', value: params.pid, rules: ['notnull', 'number']}, 39 | {label: '菜单类型', value: params.type, rules: ['notnull', 'number']}, 40 | {label: '菜单编码', value: params.code, rules: ['notnull', 'noChinese']}, 41 | {label: '菜单名称', value: params.name, rules: ['notnull']}, 42 | {label: '排序', value: params.sort, rules: ['notnull', 'number']}, 43 | {label: '状态', value: params.status, rules: ['notnull', 'number']} 44 | ], 45 | result = this.check(arr) 46 | if (!result.success) { 47 | res.json({ 48 | code: 20301, 49 | success: false, 50 | message: result.message 51 | }) 52 | return 53 | } 54 | next() 55 | } 56 | async delete (req, res, next) { 57 | const ID = req.params.id, 58 | arr = [ 59 | {label: 'ID', value: ID, rules: ['notnull']} 60 | ], 61 | result = this.check(arr) 62 | if (!result.success) { 63 | res.json({ 64 | code: 20301, 65 | success: false, 66 | message: result.message 67 | }) 68 | return 69 | } 70 | next() 71 | } 72 | async getRow (req, res, next) { 73 | const ID = req.params.id, 74 | arr = [ 75 | {label: 'ID', value: ID, rules: ['notnull']} 76 | ], 77 | result = this.check(arr) 78 | if (!result.success) { 79 | res.json({ 80 | code: 20301, 81 | success: false, 82 | message: result.message 83 | }) 84 | return 85 | } 86 | next() 87 | } 88 | async getList (req, res, next) { 89 | const data = req.query, 90 | arr = [ 91 | {label: 'curPage', value: data.curPage, rules: ['notnull', 'number']}, 92 | {label: 'pageSize', value: data.curPage, rules: ['notnull', 'number']} 93 | ], 94 | result = this.check(arr) 95 | if (!result.success) { 96 | res.json({ 97 | code: 20301, 98 | success: false, 99 | message: result.message 100 | }) 101 | return 102 | } 103 | next() 104 | } 105 | async getRoleMenu (req, res, next) { 106 | next() 107 | } 108 | async getAll (req, res, next) { 109 | next() 110 | } 111 | } 112 | 113 | export default new Menu() 114 | -------------------------------------------------------------------------------- /router/menu.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import Menu from '../controller/Menu' 3 | import ValidateMenu from '../validate/Menu' 4 | const router = express.Router() 5 | 6 | /** 7 | * 创建 8 | * @api {POST} /api/Menu/create 创建 9 | * @apiDescription 创建菜单 10 | * @apiName create 11 | * @apiHeader {String} Authorization token 12 | * @apiParam (参数) {Number} pid 父ID 13 | * @apiParam (参数) {Number} type 菜单类型: 1. 管理平台菜单 2. BBS菜单 3. 移动端菜单 14 | * @apiParam (参数) {String} code 菜单编码 15 | * @apiParam (参数) {String} name 菜单名称 16 | * @apiParam (参数) {String} icon 菜单图标 17 | * @apiParam (参数) {String} redirect 重定向路径: 配置菜单编码或URL 18 | * @apiParam (参数) {String} sort 排序 19 | * @apiParam (参数) {String} desc 描述 20 | * @apiParam (参数) {String} status 状态: 0:停用,1:启用(默认为1) 21 | * @apiSampleRequest /api/Menu/create 22 | * @apiGroup Menu 23 | * @apiVersion 0.0.1 24 | */ 25 | router.post('/create', ValidateMenu.create, Menu.create) 26 | /** 27 | * 编辑 28 | * @api {put} /api/Menu/update 编辑 29 | * @apiDescription 编辑 30 | * @apiName update 31 | * @apiHeader {String} Authorization token 32 | * @apiParam (参数) {Number} id 33 | * @apiParam (参数) {Number} pid 父ID 34 | * @apiParam (参数) {Number} type 菜单类型: 1. 管理平台菜单 2. BBS菜单 3. 移动端菜单 35 | * @apiParam (参数) {String} code 菜单编码 36 | * @apiParam (参数) {String} name 菜单名称 37 | * @apiParam (参数) {String} icon 菜单图标 38 | * @apiParam (参数) {String} redirect 重定向路径: 配置菜单编码或URL 39 | * @apiParam (参数) {String} sort 排序 40 | * @apiParam (参数) {String} desc 描述 41 | * @apiParam (参数) {String} status 状态: 0:停用,1:启用(默认为1) 42 | * @apiSampleRequest /api/Menu/update 43 | * @apiGroup Menu 44 | * @apiVersion 0.0.1 45 | */ 46 | router.put('/update', ValidateMenu.update, Menu.update) 47 | /** 48 | * 删除 49 | * @api {delete} /api/Menu/delete/:id 删除 50 | * @apiDescription 删除 51 | * @apiName delete 52 | * @apiHeader {String} Authorization token 53 | * @apiParam {Number} id 54 | * @apiSampleRequest /api/Menu/delete 55 | * @apiGroup Menu 56 | * @apiVersion 0.0.1 57 | */ 58 | router.delete('/delete/:id', ValidateMenu.delete, Menu.delete) 59 | 60 | /** 61 | * 获取菜单信息 62 | * @api {get} /api/Menu/getRow 获取菜单信息 63 | * @apiDescription 获取菜单信息 64 | * @apiName getRow 65 | * @apiHeader {String} Authorization token 66 | * @apiParam {Number} id 67 | * @apiSampleRequest /api/Menu/getRow 68 | * @apiGroup Menu 69 | * @apiVersion 0.0.1 70 | */ 71 | router.get('/getRow/:id', ValidateMenu.getRow, Menu.getRow) 72 | /** 73 | * 获取菜单列表 74 | * @api {get} /api/Menu/getList 获取菜单列表 75 | * @apiDescription 获取菜单列表 76 | * @apiName getList 77 | * @apiHeader {String} Authorization token 78 | * @apiParam (path参数) {Number} curPage 79 | * @apiParam (path参数) {Number} pageSize 80 | * @apiParam (path参数) {String} account 账号 81 | * @apiParam (path参数) {String} name 昵称 82 | * @apiParam (path参数) {Number} create_Menu 83 | * @apiSampleRequest /api/Menu/getList 84 | * @apiGroup Menu 85 | * @apiVersion 0.0.1 86 | */ 87 | router.get('/getList', ValidateMenu.getList, Menu.getList) 88 | /** 89 | * 获取用户拥有的所有菜单 90 | * @api {get} /api/Menu/getRoleMenu 获取所有菜单 91 | * @apiDescription 获取所有菜单 92 | * @apiName getRoleMenu 93 | * @apiParam {Number} type 94 | * @apiHeader {String} Authorization token 95 | * @apiSampleRequest /api/Menu/getRoleMenu 96 | * @apiGroup Menu 97 | * @apiVersion 0.0.1 98 | */ 99 | router.get('/getRoleMenu', ValidateMenu.getRoleMenu, Menu.getRoleMenu) 100 | /** 101 | * 获取所有菜单 102 | * @api {get} /api/Menu/getAll 获取所有菜单 103 | * @apiDescription 获取所有菜单 104 | * @apiName getAll 105 | * @apiParam {Number} type 106 | * @apiHeader {String} Authorization token 107 | * @apiSampleRequest /api/Menu/getAll 108 | * @apiGroup Menu 109 | * @apiVersion 0.0.1 110 | */ 111 | router.get('/getAll', ValidateMenu.getAll, Menu.getAll) 112 | 113 | export default router 114 | -------------------------------------------------------------------------------- /controller/RoleRelation.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import RoleRelationModel from '../model/RoleRelation' 3 | 4 | class RoleRelation extends Base { 5 | constructor () { 6 | super() 7 | this.setPermissions = this.setPermissions.bind(this) 8 | this.getPermissions = this.getPermissions.bind(this) 9 | this.setBindUser = this.setBindUser.bind(this) 10 | this.getBindUser = this.getBindUser.bind(this) 11 | } 12 | // 设置权限 13 | async setPermissions (req, res, next) { 14 | let userInfo = await this.getUserInfo(req), result, 15 | data = req.body 16 | try { 17 | result = await RoleRelationModel.setPermissions({ 18 | get: {role_id: data.roleId}, 19 | data: { 20 | menu: data.menu, 21 | permissions: data.permissions 22 | } 23 | }) 24 | } catch (e) { 25 | this.handleException(req, res, e) 26 | return 27 | } 28 | if (result) { 29 | res.json({ 30 | code: 20000, 31 | success: true, 32 | content: {}, 33 | message: '操作成功' 34 | }) 35 | } else { 36 | res.json({ 37 | code: 20001, 38 | success: false, 39 | content: {}, 40 | message: '操作失败' 41 | }) 42 | } 43 | } 44 | // 获取权限 45 | async getPermissions (req, res, next) { 46 | let userInfo = await this.getUserInfo(req), menu, permissions, 47 | role_id = req.query.roleId 48 | // TODO: 不是改用户创建的角色,用户不能查看到这个角色的权限 49 | try { 50 | menu = await RoleRelationModel.getMenu({get: {role_id}}) 51 | permissions = await RoleRelationModel.getDataPerms({get: {role_id}}) 52 | } catch (e) { 53 | this.handleException(req, res, e) 54 | return 55 | } 56 | res.json({ 57 | code: 20000, 58 | success: true, 59 | content: { 60 | menu: menu.map(item => item.id), 61 | permissions: permissions.map(item => item.id) 62 | }, 63 | message: '操作成功' 64 | }) 65 | } 66 | // 设置绑定用户 67 | async setBindUser (req, res, next) { 68 | let userInfo = await this.getUserInfo(req), checkBind, result, 69 | data = req.body 70 | try { 71 | // 当传入的用户已经有绑定的角色, 并且当前要绑定的不是之前的角色,则不往下执行 72 | checkBind = await RoleRelationModel.checkBindUser(data.user) 73 | checkBind = checkBind.filter(item => { 74 | return item.role_id !== data.roleId 75 | }) 76 | if (checkBind.length > 0) { 77 | res.json({ 78 | code: 20000, 79 | success: false, 80 | content: {}, 81 | message: `用户<${checkBind[0].name}>已绑定角色<${checkBind[0].role_name}>, 请先解绑` 82 | }) 83 | return 84 | } 85 | result = await RoleRelationModel.setBindUser({ 86 | get: {role_id: data.roleId}, 87 | data: { 88 | user: data.user 89 | } 90 | }) 91 | } catch (e) { 92 | this.handleException(req, res, e) 93 | return 94 | } 95 | if (result) { 96 | res.json({ 97 | code: 20000, 98 | success: true, 99 | content: {}, 100 | message: '操作成功' 101 | }) 102 | } else { 103 | res.json({ 104 | code: 20001, 105 | success: false, 106 | content: {}, 107 | message: '操作失败' 108 | }) 109 | } 110 | } 111 | // 获取绑定用户 112 | async getBindUser (req, res, next) { 113 | let result, userInfo = await this.getUserInfo(req), role_id = req.query.roleId 114 | try { 115 | result = await RoleRelationModel.getBindUser({get: {role_id, userId: userInfo.id}}) 116 | } catch (e) { 117 | this.handleException(req, res, e) 118 | return 119 | } 120 | res.json({ 121 | code: 20000, 122 | success: true, 123 | content: result, 124 | message: '操作成功' 125 | }) 126 | } 127 | } 128 | 129 | export default new RoleRelation() 130 | -------------------------------------------------------------------------------- /controller/Authority.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import TokenModel from '../model/Token' 3 | import UserModel from '../model/User' 4 | import DataPermsModel from '../model/DataPerms' 5 | import JWT from 'jsonwebtoken' 6 | 7 | class Authority extends Base{ 8 | constructor () { 9 | super() 10 | this.checkToken = this.checkToken.bind(this) 11 | this.setToken = this.setToken.bind(this) 12 | this.getToken = this.getToken.bind(this) 13 | this.permissions = this.permissions.bind(this) 14 | } 15 | // 验证Token令牌 16 | async checkToken (req, res, next) { 17 | const whiteList = ['/login', '/registered'] 18 | // 登录和注册页面不作限制 19 | // TODO: 暂时不对获取数据的接口验证 20 | if (req.method.toLocaleLowerCase() === 'get' || whiteList.includes(req.path)) { 21 | next() 22 | return 23 | } 24 | let token = req.headers.authorization, 25 | message = '', 26 | success = false, 27 | content = {}, 28 | search 29 | // token不存在 30 | if (!token) { 31 | res.json({ 32 | code: 20201, 33 | success: false, 34 | content: {}, 35 | message: '无访问权限' 36 | }) 37 | return 38 | } 39 | // 验证 Token 40 | JWT.verify(token, 'BBS', (error, decoded) => { 41 | if (error) { 42 | success = false 43 | message = 'token验证失败' 44 | return 45 | } 46 | success = true 47 | content = decoded 48 | message = '验证tonken成功' 49 | }) 50 | // 验证token格式失败 51 | if (!success) { 52 | res.json({ 53 | code: 20201, 54 | success: false, 55 | content: {}, 56 | message: '无效的token' 57 | }) 58 | return 59 | } 60 | // 查询数据库中该token的相关信息 61 | try { 62 | search = await this.getToken({get: {[content.type + '_token']: token}}) 63 | } catch (e) { 64 | res.json({ 65 | code: 20200, 66 | success: false, 67 | content: {}, 68 | message: '服务器内部错误' 69 | }) 70 | return 71 | } 72 | // 验证Token不存在或者Token过期 73 | if (search.length === 0) { 74 | res.json({ 75 | code: 20201, 76 | success: false, 77 | content: {}, 78 | message: '无访问权限' 79 | }) 80 | return 81 | } else if ((search[content.type + '_expire_time']) < +new Date()) { 82 | res.json({ 83 | code: 20201, 84 | success: false, 85 | content: {}, 86 | message: 'token过期' 87 | }) 88 | return 89 | } 90 | next() 91 | } 92 | // 设置Token令牌 93 | async setToken (data, obj) { 94 | let result 95 | try { 96 | result = await TokenModel.setToken(data, obj) 97 | } catch (e) { 98 | throw e 99 | } 100 | } 101 | // 获取Token令牌 102 | async getToken (obj) { 103 | return TokenModel.getToken(obj) 104 | } 105 | // 验证用户是否有操作权限 106 | async permissions (req, res, next) { 107 | const baseUrl = req.baseUrl.split('/') 108 | const method = req.method 109 | const userInfo = await this.getUserInfo(req) 110 | const whiteList = ['/api/user/login', '/api/user/registered', '/api/user/loginOut', 111 | '/api/article/create', '/api/article/update', 112 | '/api/articleComments/create', '/api/articleComments/delete', 113 | '/api/draft/giveUp', '/api/draft/giveUpAll'] 114 | let api = req.baseUrl + req.path 115 | // 如果是删除接口,将delete后面去掉再校验 116 | if (/delete/.test(api)) { 117 | api = api.replace(/\/[^/*]*$/, '') 118 | } 119 | // 当请求方式为get时或者登陆注册时,不需要验证数据权限 120 | if (method.toLocaleLowerCase() === 'get' || whiteList.includes(api) || whiteList.includes(req.originalUrl)) { 121 | next() 122 | return 123 | } 124 | // 查询当前接口是否配置权限 125 | const search = userInfo.id === 1 ? 126 | await DataPermsModel.getAll({get: {api}}) : 127 | await DataPermsModel.getRoleDataPerms({get: {role_id: userInfo.role_id, api: api.replace('/api/', '')}}) 128 | if (search.length > 0) { 129 | next() 130 | } else { 131 | res.json({ 132 | code: 20001, 133 | success: false, 134 | content: {}, 135 | message: '无操作权限' 136 | }) 137 | } 138 | } 139 | } 140 | 141 | export default new Authority() 142 | -------------------------------------------------------------------------------- /controller/Question.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import QuestionModel from '../model/Question' 3 | 4 | class Question extends Base { 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getAll = this.getAll.bind(this) 13 | } 14 | // 创建 15 | async create (req, res, next) { 16 | let data = JSON.parse(JSON.stringify(req.body)), 17 | userInfo = await this.getUserInfo(req), result 18 | try { 19 | // 参数处理 20 | data.create_user = userInfo.id, 21 | data.create_time = new Date() 22 | result = await QuestionModel.create({ 23 | set: data 24 | }) 25 | } catch (e) { 26 | this.handleException(req, res, e) 27 | return 28 | } 29 | res.json({ 30 | code: 20000, 31 | success: true, 32 | message: '创建成功' 33 | }) 34 | } 35 | // 编辑 36 | async update (req, res, next) { 37 | let id = req.body.id, 38 | data = JSON.parse(JSON.stringify(req.body)), 39 | result, 40 | userInfo = await this.getUserInfo(req) 41 | // 参数处理 42 | data.update_user = userInfo.id 43 | data.update_time = new Date() 44 | delete data.id 45 | try { 46 | result = await QuestionModel.update({set: data, get: {id}}) 47 | } catch (e) { 48 | this.handleException(req, res, e) 49 | return 50 | } 51 | if (result.affectedRows) { 52 | res.json({ 53 | code: 20000, 54 | success: true, 55 | message: '操作成功' 56 | }) 57 | } else { 58 | res.json({ 59 | code: 20001, 60 | success: false, 61 | message: '编辑失败' 62 | }) 63 | } 64 | } 65 | // 删除 66 | async delete (req, res, next) { 67 | const userInfo = await this.getUserInfo(req), 68 | result = await QuestionModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 69 | if (result.affectedRows) { 70 | res.json({ 71 | code: 20000, 72 | success: true, 73 | message: '删除成功' 74 | }) 75 | } else { 76 | res.json({ 77 | code: 20001, 78 | success: true, 79 | message: '删除失败' 80 | }) 81 | } 82 | } 83 | // 获取单条数据 84 | async getRow (req, res, next) { 85 | const search = await QuestionModel.getRow({get: {id: req.params.id, flag: 1}}) 86 | if (search.length === 0) { 87 | res.json({ 88 | code: 20401, 89 | success: false, 90 | content: search, 91 | message: '查询信息不存在' 92 | }) 93 | } else { 94 | res.json({ 95 | code: 20000, 96 | success: true, 97 | content: search, 98 | message: '操作成功' 99 | }) 100 | } 101 | } 102 | // 查询列表 103 | async getList (req, res, next) { 104 | let query = JSON.parse(JSON.stringify(req.query)), 105 | result, 106 | length, 107 | userInfo = await this.getUserInfo(req) 108 | // 设置非模糊查询字段 109 | for (let key in query) { 110 | if (['id', 'create_user'].indexOf(key) === -1) { 111 | query.like = [...query.like || [], key] 112 | } 113 | } 114 | try { 115 | result = await QuestionModel.getList({get: {...query, flag: 1}}) 116 | length = await QuestionModel.getTotals({get: {...query, flag: 1}}) 117 | } catch (e) { 118 | this.handleException(req, res, e) 119 | return 120 | } 121 | res.json({ 122 | code: 20000, 123 | success: true, 124 | content: { 125 | result, 126 | curPage: +query.curPage, 127 | pageSize: +query.pageSize, 128 | totals: length ? length[0].count : 0 129 | }, 130 | message: '操作成功' 131 | }) 132 | } 133 | // 获取所有 134 | async getAll (req, res, next) { 135 | let result, query = req.query 136 | try { 137 | result = await QuestionModel.getAll({get: {...query, flag: 1}}) 138 | } catch (e) { 139 | this.handleException(req, res, e) 140 | return 141 | } 142 | res.json({ 143 | code: 20000, 144 | success: true, 145 | content: result, 146 | message: '操作成功' 147 | }) 148 | } 149 | } 150 | 151 | export default new Question() 152 | -------------------------------------------------------------------------------- /controller/Carousel.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import CarouselModel from '../model/Carousel' 3 | 4 | class Carousel extends Base { 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getAll = this.getAll.bind(this) 13 | } 14 | // 创建 15 | async create (req, res, next) { 16 | let data = JSON.parse(JSON.stringify(req.body)), 17 | userInfo = await this.getUserInfo(req), result 18 | try { 19 | // 参数处理 20 | data.create_user = userInfo.id, 21 | data.create_time = new Date() 22 | result = await CarouselModel.create({ 23 | set: data 24 | }) 25 | } catch (e) { 26 | this.handleException(req, res, e) 27 | return 28 | } 29 | res.json({ 30 | code: 20000, 31 | success: true, 32 | message: '创建成功' 33 | }) 34 | } 35 | // 编辑 36 | async update (req, res, next) { 37 | let id = req.body.id, 38 | data = JSON.parse(JSON.stringify(req.body)), 39 | result, 40 | search, 41 | userInfo = await this.getUserInfo(req) 42 | // 参数处理 43 | data.update_user = userInfo.id 44 | data.update_time = new Date() 45 | delete data.id 46 | // 设置同时启用的轮播数量为5个 47 | search = await CarouselModel.getRow({get: {status: 1, flag: 1}}) 48 | if (search.length > 5) { 49 | res.json({ 50 | code: 20001, 51 | success: false, 52 | message: '轮播最多同时启用五个!' 53 | }) 54 | return 55 | } 56 | try { 57 | result = await CarouselModel.update({set: data, get: {id}}) 58 | } catch (e) { 59 | this.handleException(req, res, e) 60 | return 61 | } 62 | if (result.affectedRows) { 63 | res.json({ 64 | code: 20000, 65 | success: true, 66 | message: '操作成功' 67 | }) 68 | } else { 69 | res.json({ 70 | code: 20001, 71 | success: false, 72 | message: '编辑失败' 73 | }) 74 | } 75 | } 76 | // 删除 77 | async delete (req, res, next) { 78 | const userInfo = await this.getUserInfo(req), 79 | result = await CarouselModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 80 | if (result.affectedRows) { 81 | res.json({ 82 | code: 20000, 83 | success: true, 84 | message: '删除成功' 85 | }) 86 | } else { 87 | res.json({ 88 | code: 20001, 89 | success: true, 90 | message: '删除失败' 91 | }) 92 | } 93 | } 94 | // 获取单条数据 95 | async getRow (req, res, next) { 96 | const search = await CarouselModel.getRow({get: {id: req.params.id, flag: 1}}) 97 | if (search.length === 0) { 98 | res.json({ 99 | code: 20401, 100 | success: false, 101 | content: search, 102 | message: '查询信息不存在' 103 | }) 104 | } else { 105 | res.json({ 106 | code: 20000, 107 | success: true, 108 | content: search, 109 | message: '操作成功' 110 | }) 111 | } 112 | } 113 | // 查询列表 114 | async getList (req, res, next) { 115 | let query = JSON.parse(JSON.stringify(req.query)), 116 | result, 117 | length, 118 | userInfo = await this.getUserInfo(req) 119 | // 设置非模糊查询字段 120 | for (let key in query) { 121 | if (['id', 'create_user'].indexOf(key) === -1) { 122 | query.like = [...query.like || [], key] 123 | } 124 | } 125 | try { 126 | result = await CarouselModel.getList({get: {...query, flag: 1}}) 127 | length = await CarouselModel.getTotals({get: {...query, flag: 1}}) 128 | } catch (e) { 129 | this.handleException(req, res, e) 130 | return 131 | } 132 | res.json({ 133 | code: 20000, 134 | success: true, 135 | content: { 136 | result, 137 | curPage: +query.curPage, 138 | pageSize: +query.pageSize, 139 | totals: length ? length[0].count : 0 140 | }, 141 | message: '操作成功' 142 | }) 143 | } 144 | // 获取所有 145 | async getAll (req, res, next) { 146 | let result, query = req.query 147 | try { 148 | result = await CarouselModel.getAll({get: {...query, flag: 1}}) 149 | } catch (e) { 150 | this.handleException(req, res, e) 151 | return 152 | } 153 | res.json({ 154 | code: 20000, 155 | success: true, 156 | content: result, 157 | message: '操作成功' 158 | }) 159 | } 160 | } 161 | 162 | export default new Carousel() 163 | -------------------------------------------------------------------------------- /controller/TechSquare.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import TechSquareModel from '../model/TechSquare' 3 | 4 | class TechSquare extends Base { 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getAll = this.getAll.bind(this) 13 | } 14 | // 创建 15 | async create (req, res, next) { 16 | let data = JSON.parse(JSON.stringify(req.body)), 17 | userInfo = await this.getUserInfo(req), result 18 | try { 19 | // 参数处理 20 | data.create_user = userInfo.id, 21 | data.create_time = new Date() 22 | result = await TechSquareModel.create({ 23 | set: data 24 | }) 25 | } catch (e) { 26 | this.handleException(req, res, e) 27 | return 28 | } 29 | res.json({ 30 | code: 20000, 31 | success: true, 32 | message: '创建成功' 33 | }) 34 | } 35 | // 编辑 36 | async update (req, res, next) { 37 | let id = req.body.id, 38 | data = JSON.parse(JSON.stringify(req.body)), 39 | result, 40 | search, 41 | userInfo = await this.getUserInfo(req) 42 | // 参数处理 43 | data.update_user = userInfo.id 44 | data.update_time = new Date() 45 | delete data.id 46 | // 设置同时启用的轮播数量为5个 47 | search = await TechSquareModel.getRow({get: {status: 1, flag: 1}}) 48 | if (search.length > 15) { 49 | res.json({ 50 | code: 20001, 51 | success: false, 52 | message: '技术频道最多同时启用15个!' 53 | }) 54 | return 55 | } 56 | try { 57 | result = await TechSquareModel.update({set: data, get: {id}}) 58 | } catch (e) { 59 | this.handleException(req, res, e) 60 | return 61 | } 62 | if (result.affectedRows) { 63 | res.json({ 64 | code: 20000, 65 | success: true, 66 | message: '操作成功' 67 | }) 68 | } else { 69 | res.json({ 70 | code: 20001, 71 | success: false, 72 | message: '编辑失败' 73 | }) 74 | } 75 | } 76 | // 删除 77 | async delete (req, res, next) { 78 | const userInfo = await this.getUserInfo(req), 79 | result = await TechSquareModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 80 | if (result.affectedRows) { 81 | res.json({ 82 | code: 20000, 83 | success: true, 84 | message: '删除成功' 85 | }) 86 | } else { 87 | res.json({ 88 | code: 20001, 89 | success: true, 90 | message: '删除失败' 91 | }) 92 | } 93 | } 94 | // 获取单条数据 95 | async getRow (req, res, next) { 96 | const search = await TechSquareModel.getRow({get: {id: req.params.id, flag: 1}}) 97 | if (search.length === 0) { 98 | res.json({ 99 | code: 20401, 100 | success: false, 101 | content: search, 102 | message: '查询信息不存在' 103 | }) 104 | } else { 105 | res.json({ 106 | code: 20000, 107 | success: true, 108 | content: search, 109 | message: '操作成功' 110 | }) 111 | } 112 | } 113 | // 查询列表 114 | async getList (req, res, next) { 115 | let query = JSON.parse(JSON.stringify(req.query)), 116 | result, 117 | length, 118 | userInfo = await this.getUserInfo(req) 119 | // 设置非模糊查询字段 120 | for (let key in query) { 121 | if (['id', 'create_user'].indexOf(key) === -1) { 122 | query.like = [...query.like || [], key] 123 | } 124 | } 125 | try { 126 | result = await TechSquareModel.getList({get: {...query, flag: 1}}) 127 | length = await TechSquareModel.getTotals({get: {...query, flag: 1}}) 128 | } catch (e) { 129 | this.handleException(req, res, e) 130 | return 131 | } 132 | res.json({ 133 | code: 20000, 134 | success: true, 135 | content: { 136 | result, 137 | curPage: +query.curPage, 138 | pageSize: +query.pageSize, 139 | totals: length ? length[0].count : 0 140 | }, 141 | message: '操作成功' 142 | }) 143 | } 144 | // 获取所有 145 | async getAll (req, res, next) { 146 | let result, status = req.query.status 147 | try { 148 | result = await TechSquareModel.getAll(status ? {get: {status, flag: 1}} : {get: {flag: 1}}) 149 | } catch (e) { 150 | this.handleException(req, res, e) 151 | return 152 | } 153 | res.json({ 154 | code: 20000, 155 | success: true, 156 | content: result, 157 | message: '操作成功' 158 | }) 159 | } 160 | } 161 | 162 | export default new TechSquare() 163 | -------------------------------------------------------------------------------- /public/article/test_20190516145913_bun1.md: -------------------------------------------------------------------------------- 1 | > 最近在自己写页面,模仿思否论坛,然后写登录注册UI的时候需要一个验证码组件. 去搜一下没找到什么合适的,而且大多都是基于后端的,于是自己手写一个。 2 | 3 | ## 演示 ## 4 | ![图片描述][1] 5 | 6 | 7 | ## 分析验证码组件 ## 8 | 9 | **分析验证码功能** 10 | 11 | 1. 随机出现的数字大小写字母 (基础功能) 12 | 2. 不同的数字或者字母有不同的颜色 (功能优化) 13 | 3. 不同的数字或者字母有不同的字体大写 (功能优化) 14 | 4. 不同的数字或者字母有不同的边距 (功能优化) 15 | 5. 不同的数字或者字母有不同的倾斜角度 (功能优化) 16 | 6. 更多功能优化... 17 | 18 | 19 | ---------- 20 | **分析组件功能** 21 | 1. 可以设置生成验证码的长度 (基本功能) 22 | 2. 可以设置验证码组件的宽高 (基本功能) 23 | 24 | 25 | ---------- 26 | ## 编写验证码组件 ## 27 | 28 | **template** 29 | 30 | 最外层div绑定点击事件,点击后刷新验证码。 31 | span是单个验证码的载体,样式动态绑定 32 | ``` 33 | 38 | ``` 39 | **methods** 40 | 41 | refreshCode 刷新验证码的方法 42 | createdCode 生成验证码的方法 43 | getStyle 为每个元素生成动态的样式 44 | ``` 45 | methods: { 46 | refreshCode () { 47 | this.createdCode() 48 | }, 49 | createdCode () { 50 | let len = this.length, 51 | codeList = [], 52 | chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789', 53 | charsLen = chars.length 54 | // 生成 55 | for (let i = 0; i < len; i++) { 56 | let rgb = [Math.round(Math.random() * 220), Math.round(Math.random() * 240), Math.round(Math.random() * 200)] 57 | codeList.push({ 58 | code: chars.charAt(Math.floor(Math.random() * charsLen)), // 随机码 59 | color: `rgb(${rgb})`, // 随机颜色 60 | fontSize: `1${[Math.floor(Math.random() * 10)]}px`, // 随机字号 61 | padding: `${[Math.floor(Math.random() * 10)]}px`, // 随机内边距 62 | transform: `rotate(${Math.floor(Math.random() * 90) - Math.floor(Math.random() * 90)}deg)` // 随机旋转角度 63 | }) 64 | } 65 | // 指向 66 | this.codeList = codeList 67 | // 将当前数据派发出去 68 | this.$emit('update:value', codeList.map(item => item.code).join('')) 69 | }, 70 | // 动态绑定样式 71 | getStyle (data) { 72 | return `color: ${data.color}; font-size: ${data.fontSize}; padding: ${data.padding}; transform: ${data.transform}` 73 | } 74 | } 75 | ``` 76 | 77 | **完整代码** 78 | -------- 79 | 80 | **使用** 81 | 82 | ``` 83 | 84 | ``` 85 | 86 | **组件** 87 | ``` 88 | 93 | 94 | 150 | 151 | 162 | 163 | ``` 164 | 165 | [源码地址][2] 166 | 167 | [演示地址][3] 模仿思否写的网站,点注册可看到验证码 168 | 169 | [1]: https://image-static.segmentfault.com/601/311/6013117-5c4576fbd5d3c_articlex 170 | [2]: https://github.com/2017coding/BBS/tree/master/src/components/ValidCode 171 | [3]: https://lyh.red/#/ -------------------------------------------------------------------------------- /controller/DataPerms.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import DataPermsModel from '../model/DataPerms' 3 | 4 | class DataPerms extends Base { 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getRoleDataPerms = this.getRoleDataPerms.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | // 创建 16 | async create (req, res, next) { 17 | try { 18 | let data = JSON.parse(JSON.stringify(req.body)), 19 | userInfo = await this.getUserInfo(req), 20 | result 21 | // 参数处理 22 | data.create_user = userInfo.id, 23 | data.create_time = new Date() 24 | result = await DataPermsModel.create({ 25 | set: data 26 | }) 27 | } catch (e) { 28 | this.handleException(req, res, e) 29 | return 30 | } 31 | res.json({ 32 | code: 20000, 33 | success: true, 34 | message: '创建成功' 35 | }) 36 | } 37 | // 编辑 38 | async update (req, res, next) { 39 | let id = req.body.id, 40 | data = JSON.parse(JSON.stringify(req.body)), 41 | result, 42 | userInfo = await this.getUserInfo(req) 43 | // 参数处理 44 | data.update_user = userInfo.id 45 | data.update_time = new Date() 46 | delete data.id 47 | try { 48 | result = await DataPermsModel.update({set: data, get: {id}}) 49 | } catch (e) { 50 | this.handleException(req, res, e) 51 | return 52 | } 53 | if (result.affectedRows) { 54 | res.json({ 55 | code: 20000, 56 | success: true, 57 | message: '操作成功' 58 | }) 59 | } else { 60 | res.json({ 61 | code: 20001, 62 | success: false, 63 | message: '编辑失败' 64 | }) 65 | } 66 | } 67 | // 删除 68 | async delete (req, res, next) { 69 | const userInfo = await this.getUserInfo(req), 70 | result = await DataPermsModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 71 | if (result.affectedRows) { 72 | res.json({ 73 | code: 20000, 74 | success: true, 75 | message: '删除成功' 76 | }) 77 | } else { 78 | res.json({ 79 | code: 20001, 80 | success: true, 81 | message: '删除失败' 82 | }) 83 | } 84 | } 85 | // 获取单条数据 86 | async getRow (req, res, next) { 87 | const search = await DataPermsModel.getRow({get: {id: req.params.id}}) 88 | if (search.length === 0) { 89 | res.json({ 90 | code: 20401, 91 | success: false, 92 | content: search, 93 | message: '查询信息不存在' 94 | }) 95 | } else { 96 | res.json({ 97 | code: 20000, 98 | success: true, 99 | content: search, 100 | message: '操作成功' 101 | }) 102 | } 103 | } 104 | // 查询列表 105 | async getList (req, res, next) { 106 | let query = JSON.parse(JSON.stringify(req.query)), 107 | result, 108 | length, 109 | userInfo = await this.getUserInfo(req) 110 | // 设置非模糊查询字段 111 | for (let key in query) { 112 | if (['id', 'create_user'].indexOf(key) === -1) { 113 | query.like = [...query.like || [], key] 114 | } 115 | } 116 | try { 117 | result = await DataPermsModel.getList({get: query}) 118 | length = await DataPermsModel.getTotals({get: query}) 119 | } catch (e) { 120 | this.handleException(req, res, e) 121 | return 122 | } 123 | res.json({ 124 | code: 20000, 125 | success: true, 126 | content: { 127 | result, 128 | curPage: +query.curPage, 129 | pageSize: +query.pageSize, 130 | totals: length ? length[0].count : 0 131 | }, 132 | message: '操作成功' 133 | }) 134 | } 135 | // 获取当前用户拥有 136 | async getRoleDataPerms (req, res, next) { 137 | let menuId = req.query.menuId, result, userInfo = await this.getUserInfo(req) 138 | try { 139 | result = userInfo.id === 1 ? 140 | await DataPermsModel.getAll({get: {menu_id: menuId}}) : 141 | await DataPermsModel.getRoleDataPerms({get: {menu_id: menuId, role_id: userInfo.role_id}}) 142 | } catch (e) { 143 | this.handleException(req, res, e) 144 | return 145 | } 146 | res.json({ 147 | code: 20000, 148 | success: true, 149 | content: result, 150 | message: '操作成功' 151 | }) 152 | } 153 | // 获取所有 154 | async getAll (req, res, next) { 155 | let menuId = req.query.menuId, result 156 | try { 157 | result = await DataPermsModel.getAll(menuId ? {get: {menu_id: menuId}} : '') 158 | } catch (e) { 159 | this.handleException(req, res, e) 160 | return 161 | } 162 | res.json({ 163 | code: 20000, 164 | success: true, 165 | content: result, 166 | message: '操作成功' 167 | }) 168 | } 169 | } 170 | 171 | export default new DataPerms() 172 | -------------------------------------------------------------------------------- /controller/Menu.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import MenuModel from '../model/Menu' 3 | 4 | class Menu extends Base { 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getRoleMenu = this.getRoleMenu.bind(this) 13 | this.getAll = this.getAll.bind(this) 14 | } 15 | // 创建 16 | async create (req, res, next) { 17 | try { 18 | let data = JSON.parse(JSON.stringify(req.body)), 19 | userInfo = await this.getUserInfo(req), result 20 | // 参数处理 21 | data.create_user = userInfo.id, 22 | data.create_time = new Date() 23 | result = await MenuModel.create({ 24 | set: data 25 | }) 26 | } catch (e) { 27 | this.handleException(req, res, e) 28 | return 29 | } 30 | res.json({ 31 | code: 20000, 32 | success: true, 33 | message: '创建成功' 34 | }) 35 | } 36 | // 编辑 37 | async update (req, res, next) { 38 | let id = req.body.id, 39 | data = JSON.parse(JSON.stringify(req.body)), 40 | result, 41 | userInfo = await this.getUserInfo(req) 42 | // 参数处理 43 | data.update_user = userInfo.id 44 | data.update_time = new Date() 45 | delete data.id 46 | try { 47 | result = await MenuModel.update({set: data, get: {id}}) 48 | } catch (e) { 49 | this.handleException(req, res, e) 50 | return 51 | } 52 | if (result.affectedRows) { 53 | res.json({ 54 | code: 20000, 55 | success: true, 56 | message: '操作成功' 57 | }) 58 | } else { 59 | res.json({ 60 | code: 20001, 61 | success: false, 62 | message: '编辑失败' 63 | }) 64 | } 65 | } 66 | // 删除 67 | async delete (req, res, next) { 68 | // 如果当前模块下面有节点,则不能删除 69 | const child = await MenuModel.getAll({get: {pid: req.params.id}}) 70 | if (child.length > 0) { 71 | res.json({ 72 | code: 20001, 73 | success: false, 74 | message: '请先删除子目录' 75 | }) 76 | return 77 | } 78 | const userInfo = await this.getUserInfo(req), 79 | result = await MenuModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 80 | if (result.affectedRows) { 81 | res.json({ 82 | code: 20000, 83 | success: true, 84 | message: '删除成功' 85 | }) 86 | } else { 87 | res.json({ 88 | code: 20001, 89 | success: true, 90 | message: '删除失败' 91 | }) 92 | } 93 | } 94 | // 获取单条数据 95 | async getRow (req, res, next) { 96 | const search = await MenuModel.getRow({get: {id: req.params.id, flag: 1}}) 97 | if (search.length === 0) { 98 | res.json({ 99 | code: 20401, 100 | success: false, 101 | content: search, 102 | message: '查询信息不存在' 103 | }) 104 | } else { 105 | res.json({ 106 | code: 20000, 107 | success: true, 108 | content: search, 109 | message: '操作成功' 110 | }) 111 | } 112 | } 113 | // 查询列表 114 | async getList (req, res, next) { 115 | let query = JSON.parse(JSON.stringify(req.query)), 116 | result, 117 | length, 118 | userInfo = await this.getUserInfo(req) 119 | // 设置非模糊查询字段 120 | for (let key in query) { 121 | if (['id', 'create_user'].indexOf(key) === -1) { 122 | query.like = [...query.like || [], key] 123 | } 124 | } 125 | try { 126 | result = await MenuModel.getList({get: {...query, flag: 1}}) 127 | length = await MenuModel.getTotals({get: {...query, flag: 1}}) 128 | } catch (e) { 129 | this.handleException(req, res, e) 130 | return 131 | } 132 | res.json({ 133 | code: 20000, 134 | success: true, 135 | content: { 136 | result, 137 | curPage: +query.curPage, 138 | pageSize: +query.pageSize, 139 | totals: length ? length[0].count : 0 140 | }, 141 | message: '操作成功' 142 | }) 143 | } 144 | // 获取角色拥有的模块 145 | async getRoleMenu (req, res, next) { 146 | let result, query = req.query 147 | try { 148 | result = await MenuModel.getRoleMenu({get: {type: query.type, role_id: query.roleId, flag: 1}}) 149 | } catch (e) { 150 | this.handleException(req, res, e) 151 | return 152 | } 153 | res.json({ 154 | code: 20000, 155 | success: true, 156 | content: result, 157 | message: '操作成功' 158 | }) 159 | } 160 | // 获取所有 161 | async getAll (req, res, next) { 162 | let result, query = req.query 163 | try { 164 | result = await MenuModel.getAll({get: {...query, flag: 1}}) 165 | } catch (e) { 166 | this.handleException(req, res, e) 167 | return 168 | } 169 | res.json({ 170 | code: 20000, 171 | success: true, 172 | content: result, 173 | message: '操作成功' 174 | }) 175 | } 176 | } 177 | 178 | export default new Menu() 179 | -------------------------------------------------------------------------------- /controller/Tag.js: -------------------------------------------------------------------------------- 1 | import Base from './Base' 2 | import TagModel from '../model/Tag' 3 | 4 | class Tag extends Base { 5 | constructor () { 6 | super() 7 | this.create = this.create.bind(this) 8 | this.update = this.update.bind(this) 9 | this.delete = this.delete.bind(this) 10 | this.getRow = this.getRow.bind(this) 11 | this.getList = this.getList.bind(this) 12 | this.getAll = this.getAll.bind(this) 13 | } 14 | // 创建 15 | async create (req, res, next) { 16 | let data = JSON.parse(JSON.stringify(req.body)), 17 | userInfo = await this.getUserInfo(req), result, search, path 18 | // 查询标签是否存在 19 | try { 20 | search = await TagModel.getRow({get: {name: data.name, flag: 1}}) 21 | } catch (e) { 22 | this.handleException(req, res, e) 23 | return 24 | } 25 | // 如果存在,提示 26 | if (search.length === 0) { 27 | try { 28 | // 参数处理 29 | data.create_user = userInfo.id, 30 | data.create_time = new Date() 31 | result = await TagModel.create({ 32 | set: data 33 | }) 34 | } catch (e) { 35 | this.handleException(req, res, e) 36 | return 37 | } 38 | res.json({ 39 | code: 20000, 40 | success: true, 41 | message: '创建成功' 42 | }) 43 | } else { 44 | res.json({ 45 | code: 20001, 46 | success: false, 47 | message: '标签已存在' 48 | }) 49 | } 50 | } 51 | // 编辑 52 | async update (req, res, next) { 53 | let id = req.body.id, 54 | data = JSON.parse(JSON.stringify(req.body)), 55 | result, 56 | search, 57 | userInfo = await this.getUserInfo(req) 58 | // 参数处理 59 | data.update_user = userInfo.id 60 | data.update_time = new Date() 61 | delete data.id 62 | // 查询标签是否存在 63 | try { 64 | search = await TagModel.getRow({get: {name: data.name, flag: 1}}) 65 | } catch (e) { 66 | this.handleException(req, res, e) 67 | return 68 | } 69 | // 修改的名字重复 70 | if (search.length > 0 && search[0].id !== id) { 71 | res.json({ 72 | code: 20001, 73 | success: false, 74 | message: '标签名字重复' 75 | }) 76 | return 77 | } 78 | try { 79 | result = await TagModel.update({set: data, get: {id}}) 80 | } catch (e) { 81 | this.handleException(req, res, e) 82 | return 83 | } 84 | if (result.affectedRows) { 85 | res.json({ 86 | code: 20000, 87 | success: true, 88 | message: '操作成功' 89 | }) 90 | } else { 91 | res.json({ 92 | code: 20001, 93 | success: false, 94 | message: '编辑失败' 95 | }) 96 | } 97 | } 98 | // 删除 99 | async delete (req, res, next) { 100 | const userInfo = await this.getUserInfo(req), 101 | result = await TagModel.update({set: {flag: 0, delete_user: userInfo.id, delete_time: new Date()}, get: {id: req.params.id}}) 102 | if (result.affectedRows) { 103 | res.json({ 104 | code: 20000, 105 | success: true, 106 | message: '删除成功' 107 | }) 108 | } else { 109 | res.json({ 110 | code: 20001, 111 | success: true, 112 | message: '删除失败' 113 | }) 114 | } 115 | } 116 | // 获取单条数据 117 | async getRow (req, res, next) { 118 | const search = await TagModel.getRow({get: {id: req.params.id, flag: 1}}) 119 | if (search.length === 0) { 120 | res.json({ 121 | code: 20401, 122 | success: false, 123 | content: search, 124 | message: '查询信息不存在' 125 | }) 126 | } else { 127 | res.json({ 128 | code: 20000, 129 | success: true, 130 | content: search, 131 | message: '操作成功' 132 | }) 133 | } 134 | } 135 | // 查询列表 136 | async getList (req, res, next) { 137 | let query = JSON.parse(JSON.stringify(req.query)), 138 | result, 139 | length, 140 | userInfo = await this.getUserInfo(req) 141 | // 设置非模糊查询字段 142 | for (let key in query) { 143 | if (['id', 'create_user', 'type_id'].indexOf(key) === -1) { 144 | query.like = [...query.like || [], key] 145 | } 146 | } 147 | try { 148 | result = await TagModel.getList({get: {...query, flag: 1}}) 149 | length = await TagModel.getTotals({get: {...query, flag: 1}}) 150 | } catch (e) { 151 | this.handleException(req, res, e) 152 | return 153 | } 154 | res.json({ 155 | code: 20000, 156 | success: true, 157 | content: { 158 | result, 159 | curPage: +query.curPage, 160 | pageSize: +query.pageSize, 161 | totals: length ? length[0].count : 0 162 | }, 163 | message: '操作成功' 164 | }) 165 | } 166 | // 获取所有 167 | async getAll (req, res, next) { 168 | let result, query = req.query 169 | try { 170 | result = await TagModel.getAll({get: {...query, flag: 1}}) 171 | } catch (e) { 172 | this.handleException(req, res, e) 173 | return 174 | } 175 | res.json({ 176 | code: 20000, 177 | success: true, 178 | content: result, 179 | message: '操作成功' 180 | }) 181 | } 182 | } 183 | 184 | export default new Tag() 185 | --------------------------------------------------------------------------------