├── .gitattributes ├── README.md ├── .gitignore ├── config └── config.js ├── core ├── util.js ├── db.js ├── init.js └── http-exception.js ├── app.js ├── app ├── models │ ├── vip.js │ ├── suggest.js │ └── userInfo.js └── api │ └── v1 │ ├── vip.js │ ├── userInfo.js │ └── suggest.js ├── middlewares ├── exceptions.js └── auth.js ├── package.json └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-idle-game服务端 2 | 3 | > 基于KOA2编写的vue-idle-game服务端,游戏链接:[couy.xyz](http://couy.xyz) 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | # local env files 4 | .env.local 5 | .env.*.local 6 | config/config.js 7 | 8 | # Log files 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.sw? 21 | -------------------------------------------------------------------------------- /config/config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | port: 3001, 3 | database: { 4 | dbName: 'idleGame', 5 | username: 'root', 6 | password: 'root', 7 | port: '3306', 8 | host: 'localhost' 9 | }, 10 | security:{ 11 | secretKey:"couy", 12 | expiresIn:60*60 13 | } 14 | } 15 | 16 | module.exports = config -------------------------------------------------------------------------------- /core/util.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken') 2 | const config= require('../config/config') 3 | //生成yonghutoken 4 | const generateToken = function(uid,scope){ 5 | const secretKey = config.security.secretKey 6 | const expiresIn = config.security.expiresIn 7 | const token = jwt.sign({ 8 | uid,scope 9 | },secretKey,{ 10 | expiresIn 11 | }) 12 | return token 13 | } 14 | 15 | module.exports = { 16 | generateToken 17 | } -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa') 2 | const app = new Koa() 3 | const initManager = require('./core/init') 4 | const parser = require('koa-bodyparser') 5 | const catchError = require('./middlewares/exceptions') 6 | const cors = require('koa2-cors'); 7 | 8 | app.use(parser()) 9 | app.use(catchError) 10 | app.use( 11 | cors({ 12 | origin: function(ctx) { 13 | return '*'; // 允许来自所有域名请求 14 | // return 'http://couy.xyz/rpg'; //只允许http://localhost:8080这个域名的请求 15 | }, 16 | }) 17 | ); 18 | 19 | initManager.initCore(app) 20 | app.listen(3001) -------------------------------------------------------------------------------- /app/models/vip.js: -------------------------------------------------------------------------------- 1 | //创建user用户表 2 | const bcrypt = require('bcryptjs') 3 | const { 4 | sequelize 5 | } = require('../../core/db') 6 | const { 7 | Sequelize, 8 | Model 9 | } = require('sequelize') 10 | 11 | class Vip extends Model { 12 | } 13 | 14 | Vip.init({ 15 | id: { 16 | type: Sequelize.INTEGER, 17 | primaryKey: true, //主键 18 | autoIncrement: true //id是否自增 19 | }, 20 | lv: Sequelize.TEXT, 21 | version: Sequelize.TEXT, 22 | standby1:Sequelize.STRING, 23 | standby2:Sequelize.STRING, 24 | standby3:Sequelize.STRING, 25 | }, { 26 | sequelize, 27 | tableName: 'vip' 28 | }) 29 | 30 | module.exports = { 31 | Vip 32 | } -------------------------------------------------------------------------------- /app/models/suggest.js: -------------------------------------------------------------------------------- 1 | //创建user用户表 2 | const bcrypt = require('bcryptjs') 3 | const { 4 | sequelize 5 | } = require('../../core/db') 6 | const { 7 | Sequelize, 8 | Model 9 | } = require('sequelize') 10 | 11 | class Suggest extends Model { 12 | } 13 | 14 | Suggest.init({ 15 | id: { 16 | type: Sequelize.INTEGER, 17 | primaryKey: true, //主键 18 | autoIncrement: true //id是否自增 19 | }, 20 | name: Sequelize.TEXT, 21 | suggest: Sequelize.TEXT, 22 | standby1:Sequelize.STRING, 23 | standby2:Sequelize.STRING, 24 | standby3:Sequelize.STRING, 25 | }, { 26 | sequelize, 27 | tableName: 'suggest' 28 | }) 29 | 30 | module.exports = { 31 | Suggest 32 | } -------------------------------------------------------------------------------- /middlewares/exceptions.js: -------------------------------------------------------------------------------- 1 | // 全局捕获错误 2 | const catchError =async (ctx,next) =>{ 3 | try { 4 | await next() 5 | } catch (error) { 6 | // throw error 7 | if(error instanceof global.errs.httpException){ 8 | ctx.body = { 9 | error_code:error.errorCode, 10 | msg:error.msg, 11 | content:error.content, 12 | request:`${ctx.method} ${ctx.path}` 13 | } 14 | ctx.status = error.code 15 | } 16 | else{ 17 | ctx.body = { 18 | error_code:999, 19 | msg:'服务器内部错误', 20 | request:`${ctx.method} ${ctx.path}` 21 | } 22 | ctx.status = 500 23 | } 24 | 25 | } 26 | } 27 | 28 | module.exports = catchError -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "axios": "^0.20.0", 13 | "bcryptjs": "^2.4.3", 14 | "formidable": "^1.2.2", 15 | "fs": "^0.0.1-security", 16 | "jsonwebtoken": "^8.5.1", 17 | "koa-bodyparser": "^4.3.0", 18 | "koa-router": "^9.4.0", 19 | "koa-static": "^5.0.0", 20 | "mysql2": "^2.1.0", 21 | "require-directory": "^2.1.1", 22 | "sequelize": "^6.3.5" 23 | }, 24 | "dependencies": { 25 | "koa": "^2.13.0", 26 | "koa2-cors": "^2.0.6" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/db.js: -------------------------------------------------------------------------------- 1 | //数据库连接 2 | 3 | const Sequelize = require('sequelize') 4 | const { 5 | dbName, 6 | username, 7 | password, 8 | port, 9 | host 10 | } = require('../config/config').database 11 | 12 | const sequelize = new Sequelize(dbName,username,password,{ 13 | dialect:'mysql', 14 | host, 15 | port, 16 | logging:true, 17 | timezone:'+08:00', 18 | define:{ 19 | timestamps:true, //创建时间与更改时间 20 | paranoid: true, //删除时间 21 | createdAt:'created_at', 22 | updatedAt:'updated_at', 23 | deletedAt:'deleted_at', 24 | underscored:true //驼峰转为下划线 25 | } 26 | }) 27 | 28 | sequelize.sync({ 29 | force:false //每次运行是否删除现有表,然后新增 30 | }) 31 | module.exports = { 32 | sequelize 33 | } -------------------------------------------------------------------------------- /core/init.js: -------------------------------------------------------------------------------- 1 | //初始化程序 2 | 3 | const requireDirectoty = require('require-directory') 4 | const Router = require('koa-router') 5 | const Static = require('koa-static') 6 | const path = require('path') 7 | 8 | class InitManager{ 9 | static initCore(app){ 10 | InitManager.app = app 11 | InitManager.initInitRouter() 12 | InitManager.loadHttpException() 13 | InitManager.loadKoaStatic() 14 | } 15 | static initInitRouter(){ 16 | const modules = requireDirectoty(module,'../app/api',{visit:(obj)=>{ 17 | if(obj instanceof Router){ 18 | InitManager.app.use(obj.routes()) 19 | } 20 | }}) 21 | } 22 | 23 | static loadHttpException(){ 24 | const errors = require('./http-exception') 25 | global.errs = errors 26 | } 27 | 28 | static loadKoaStatic(){ 29 | const staticPath = '../static' 30 | InitManager.app.use(Static( 31 | path.join( __dirname, staticPath) 32 | )) 33 | } 34 | } 35 | 36 | module.exports = InitManager -------------------------------------------------------------------------------- /app/models/userInfo.js: -------------------------------------------------------------------------------- 1 | //创建user用户表 2 | const bcrypt = require('bcryptjs') 3 | const { 4 | sequelize 5 | } = require('../../core/db') 6 | const { 7 | Sequelize, 8 | Model 9 | } = require('sequelize') 10 | 11 | class UserInfo extends Model { 12 | } 13 | 14 | UserInfo.init({ 15 | id: { 16 | type: Sequelize.INTEGER, 17 | primaryKey: true, //主键 18 | autoIncrement: true //id是否自增 19 | }, 20 | name: Sequelize.STRING, 21 | endlessLv: Sequelize.STRING, 22 | playtime: Sequelize.STRING, 23 | password: { 24 | type: Sequelize.STRING, 25 | set(val) { 26 | const salt = bcrypt.genSaltSync(10) //加密 27 | const psw = bcrypt.hashSync(val, salt) 28 | this.setDataValue('password',psw) 29 | } 30 | }, 31 | saveData:Sequelize.TEXT, 32 | standby1:Sequelize.STRING, 33 | standby2:Sequelize.STRING, 34 | standby3:Sequelize.STRING, 35 | }, { 36 | sequelize, 37 | tableName: 'userInfo' 38 | }) 39 | 40 | module.exports = { 41 | UserInfo 42 | } -------------------------------------------------------------------------------- /middlewares/auth.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken') 2 | const config= require('../config/config') 3 | class Auth { 4 | constructor(level){ 5 | this.level = level||1 6 | Auth.USER = 8 7 | Auth.ADMIN = 16 8 | } 9 | get m(){ 10 | return async (ctx,next)=>{ 11 | const userToken = ctx.headers.token 12 | if(!userToken){ 13 | throw new global.errs.Forbbiden() 14 | } 15 | try { 16 | var code = jwt.verify(userToken,config.security.secretKey) 17 | } catch (error) { 18 | if(error.name == 'TokenExpiredError'){ 19 | throw new global.errs.Forbbiden('令牌过期') 20 | } 21 | throw new global.errs.Forbbiden('令牌不合法') 22 | } 23 | 24 | if(code.scope { 12 | try { 13 | var body = ctx.request.body 14 | const vip = { 15 | lv: body.lv, 16 | version:body.version 17 | } 18 | var r = await Vip.create(vip) 19 | throw new global.errs.Success('操作成功') 20 | } catch (error) { 21 | console.log(error) 22 | throw error 23 | } 24 | 25 | }) 26 | 27 | router.post('/get', async (ctx) => { 28 | try { 29 | var body = ctx.request.body 30 | const r = await Vip.findAndCountAll({ 31 | where: { 32 | lv: { 33 | [Op.like]: '%' + body.lv || '' + '%' 34 | }, 35 | }, 36 | order:[['created_at', 'DESC']], 37 | limit: parseInt(body.size || 10), 38 | offset: parseInt((body.size * (body.page-1)) || 0) 39 | }) 40 | throw new global.errs.Success('操作成功', r) 41 | } catch (error) { 42 | console.log(error) 43 | throw error 44 | } 45 | }) 46 | module.exports = router -------------------------------------------------------------------------------- /core/http-exception.js: -------------------------------------------------------------------------------- 1 | //定义全局异常的处理 2 | 3 | class httpException extends Error { 4 | constructor(msg = "服务器异常", errorCode = 10000, code = 400) { 5 | super() 6 | this.errorCode = errorCode 7 | this.code = code 8 | this.msg = msg 9 | } 10 | } 11 | class ParameterException extends httpException { 12 | constructor(msg, errorCode) { 13 | super() 14 | this.code = 400 15 | this.msg = msg || '参数错误' 16 | this.errorCode = errorCode || '10000' 17 | } 18 | } 19 | 20 | class NotFound extends httpException { 21 | constructor(msg, errorCode) { 22 | super() 23 | this.code = 404 24 | this.msg = msg || '未找到匹配项' 25 | this.errorCode = errorCode || '10000' 26 | } 27 | } 28 | 29 | class AuthFailed extends httpException { 30 | constructor(msg, errorCode) { 31 | super() 32 | this.code = 401 33 | this.msg = msg || '授权失败' 34 | this.errorCode = errorCode || '10004' 35 | } 36 | } 37 | 38 | class Forbbiden extends httpException { 39 | constructor(msg, errorCode) { 40 | super() 41 | this.code = 403 42 | this.msg = msg || '权限不足禁止访问' 43 | this.errorCode = errorCode || '10006' 44 | } 45 | } 46 | 47 | class Success extends httpException { 48 | constructor(msg,content) { 49 | super() 50 | this.code = 200 51 | this.content = content 52 | this.msg = msg || 'ok' 53 | this.errorCode = 20000 || '0' 54 | } 55 | } 56 | 57 | module.exports = { 58 | httpException, 59 | ParameterException, 60 | Success, 61 | NotFound, 62 | AuthFailed, 63 | Forbbiden 64 | } -------------------------------------------------------------------------------- /app/api/v1/userInfo.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | const Op = Sequelize.Op; 3 | const Router = require('koa-router') 4 | const router = new Router({ 5 | prefix: '/v1/userInfo' 6 | }) 7 | const { 8 | UserInfo 9 | } = require('../../models/userInfo') 10 | 11 | router.post('/add', async (ctx) => { 12 | try { 13 | var body = ctx.request.body 14 | const userInfo = { 15 | name: body.name, 16 | endlessLv: body.endlessLv, 17 | password: body.password, 18 | playtime: body.playtime, 19 | saveData:body.saveData 20 | } 21 | var r = await UserInfo.create(userInfo) 22 | throw new global.errs.Success('操作成功') 23 | } catch (error) { 24 | console.log(error) 25 | throw error 26 | } 27 | 28 | }) 29 | router.get('/get', async (ctx) => { 30 | try { 31 | var body = ctx.request.body 32 | const r = await UserInfo.findAndCountAll({ 33 | where: { 34 | name: { 35 | [Op.like]: '%' + body.name || '' + '%' 36 | }, 37 | }, 38 | limit: parseInt(body.size || 10), 39 | offset: parseInt((body.size * (body.page - 1)) || 0) 40 | }) 41 | throw new global.errs.Success('操作成功', r) 42 | } catch (error) { 43 | console.log(error) 44 | throw error 45 | } 46 | }) 47 | 48 | router.put('/update', async (ctx) => { 49 | try { 50 | var body = ctx.request.body 51 | await UserInfo.update( 52 | { 53 | name: body.name, 54 | number: body.number, 55 | password: body.password, 56 | file: body.file, 57 | }, { 58 | 'where': { 59 | 'id': body.id 60 | } 61 | } 62 | ); 63 | throw new global.errs.Success('操作成功') 64 | } catch (error) { 65 | console.log(error) 66 | throw error 67 | } 68 | }) 69 | 70 | router.delete('/delete', async (ctx) => { 71 | try { 72 | var body = ctx.request.body 73 | await UserInfo.destroy( 74 | { 75 | 'where': { 76 | 'id': body.id 77 | } 78 | } 79 | ); 80 | throw new global.errs.Success('删除成功') 81 | } catch (error) { 82 | console.log(error) 83 | throw error 84 | } 85 | }) 86 | 87 | module.exports = router -------------------------------------------------------------------------------- /app/api/v1/suggest.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | const Op = Sequelize.Op; 3 | const Router = require('koa-router') 4 | const router = new Router({ 5 | prefix: '/v1/suggest' 6 | }) 7 | const { 8 | Suggest 9 | } = require('../../models/suggest') 10 | 11 | router.post('/add', async (ctx) => { 12 | try { 13 | var body = ctx.request.body 14 | if(body.name.length>20||body.suggest.length>300){ 15 | throw new global.errs.ParameterException('你输入的太长了,删一点?') 16 | } 17 | if(body.name==''||body.suggest==''){ 18 | throw new global.errs.ParameterException('提交的时候请填写完整哦') 19 | } 20 | const suggest = { 21 | name: body.name, 22 | suggest:body.suggest 23 | } 24 | var r = await Suggest.create(suggest) 25 | throw new global.errs.Success('操作成功') 26 | } catch (error) { 27 | console.log(error) 28 | throw error 29 | } 30 | 31 | }) 32 | 33 | router.post('/get', async (ctx) => { 34 | try { 35 | var body = ctx.request.body 36 | const r = await Suggest.findAndCountAll({ 37 | where: { 38 | name: { 39 | [Op.like]: '%' + body.name || '' + '%' 40 | }, 41 | }, 42 | order:[['created_at', 'DESC']], 43 | limit: parseInt(body.size || 10), 44 | offset: parseInt((body.size * (body.page-1)) || 0) 45 | }) 46 | throw new global.errs.Success('操作成功', r) 47 | } catch (error) { 48 | console.log(error) 49 | throw error 50 | } 51 | }) 52 | 53 | router.post('/getReviewed', async (ctx) => { 54 | try { 55 | var body = ctx.request.body 56 | const r = await Suggest.findAndCountAll({ 57 | where: { 58 | standby2: '1', 59 | }, 60 | order:[['created_at', 'DESC']], 61 | limit: parseInt(body.size || 10), 62 | offset: parseInt((body.size * (body.page-1)) || 0) 63 | }) 64 | throw new global.errs.Success('操作成功', r) 65 | } catch (error) { 66 | console.log(error) 67 | throw error 68 | } 69 | }) 70 | 71 | router.post('/reply', async (ctx) => { 72 | try { 73 | var body = ctx.request.body 74 | const r = await Suggest.findByPk(body.id); 75 | r.standby1 = body.reply 76 | r.standby2 = 1 77 | await r.save() 78 | throw new global.errs.Success('操作成功') 79 | } catch (error) { 80 | console.log(error) 81 | throw error 82 | } 83 | }) 84 | 85 | router.post('/showOrHide', async (ctx) => { 86 | try { 87 | var body = ctx.request.body 88 | const r = await Suggest.findByPk(body.id); 89 | r.standby2 = body.showOrHide 90 | await r.save() 91 | throw new global.errs.Success('操作成功') 92 | } catch (error) { 93 | console.log(error) 94 | throw error 95 | } 96 | }) 97 | 98 | module.exports = router --------------------------------------------------------------------------------