From 96333ae7a9af984fc6d796c1869a4b72965afe4e Mon Sep 17 00:00:00 2001 From: robin <9715115286> Date: Sat, 21 May 2022 06:48:12 +0800 Subject: [PATCH] up --- app/{ => chef}/event/test.js | 4 + app/{ => chef}/event/全局事件定义文件 | 0 app/chef/status/test.js | 13 + .../公共函数 => chef/status/状态管理} | 0 app/{ => cms}/controller/index.js | 5 +- app/{ => cms}/init.js | 0 app/{ => cms}/model/User.js | 2 +- app/{ => cms}/model/UserInfo.js | 0 app/{ => cms}/model/数据库模型 | 0 app/middleware/bodyparser.js | 4 - app/middleware/error.js | 12 - app/middleware/koaLogger.js | 3 - app/middleware/time.js | 10 - app/mkt/营销,推广 | 0 app/mps/消息推送 | 0 app/oms/订单管理 | 0 app/sqlite/database.sqlite | Bin 16384 -> 0 bytes components/公共函数 | 0 config/database.js | 26 +- config/extend.js | 13 + config/middleware.js | 5 +- extend/load/config.js | 4 + lib/bamboo/bamboo.js | 123 ++++++++++ {app/err => lib/bamboo}/errorException.js | 18 +- lib/bamboo/index.js | 36 +-- lib/bamboo/load.js | 41 ++++ lib/bamboo/status.js | 227 ++++++++++++++++++ lib/main.js | 2 +- middleware/bodyparser.js | 8 + middleware/error.js | 16 ++ middleware/koaLogger.js | 7 + middleware/time.js | 14 ++ middleware/全局中间件定义文件 | 0 package.json | 3 + schedule/pbm.js | 12 + {app/schedule => schedule}/test.js | 0 schedule/定时任务 | 0 sqlite/database.sqlite | Bin 0 -> 176128 bytes {app/sqlite => sqlite}/model/MysqlMD5.js | 1 - sqlite/model/PermissionsDatabase.js | 25 ++ sqlite/model/PermissionsElement.js | 16 ++ sqlite/model/PermissionsPage.js | 15 ++ sqlite/model/Role.js | 16 ++ sqlite/model/Rout.js | 14 ++ sqlite/model/Setting.js | 19 ++ 45 files changed, 650 insertions(+), 64 deletions(-) rename app/{ => chef}/event/test.js (63%) rename app/{ => chef}/event/全局事件定义文件 (100%) create mode 100644 app/chef/status/test.js rename app/{components/公共函数 => chef/status/状态管理} (100%) rename app/{ => cms}/controller/index.js (97%) rename app/{ => cms}/init.js (100%) rename app/{ => cms}/model/User.js (79%) rename app/{ => cms}/model/UserInfo.js (100%) rename app/{ => cms}/model/数据库模型 (100%) delete mode 100644 app/middleware/bodyparser.js delete mode 100644 app/middleware/error.js delete mode 100644 app/middleware/koaLogger.js delete mode 100644 app/middleware/time.js create mode 100644 app/mkt/营销,推广 create mode 100644 app/mps/消息推送 create mode 100644 app/oms/订单管理 delete mode 100644 app/sqlite/database.sqlite create mode 100644 components/公共函数 create mode 100644 config/extend.js create mode 100644 extend/load/config.js create mode 100644 lib/bamboo/bamboo.js rename {app/err => lib/bamboo}/errorException.js (63%) create mode 100644 lib/bamboo/load.js create mode 100644 lib/bamboo/status.js create mode 100644 middleware/bodyparser.js create mode 100644 middleware/error.js create mode 100644 middleware/koaLogger.js create mode 100644 middleware/time.js create mode 100644 middleware/全局中间件定义文件 create mode 100644 schedule/pbm.js rename {app/schedule => schedule}/test.js (100%) create mode 100644 schedule/定时任务 create mode 100644 sqlite/database.sqlite rename {app/sqlite => sqlite}/model/MysqlMD5.js (76%) create mode 100644 sqlite/model/PermissionsDatabase.js create mode 100644 sqlite/model/PermissionsElement.js create mode 100644 sqlite/model/PermissionsPage.js create mode 100644 sqlite/model/Role.js create mode 100644 sqlite/model/Rout.js create mode 100644 sqlite/model/Setting.js diff --git a/app/event/test.js b/app/chef/event/test.js similarity index 63% rename from app/event/test.js rename to app/chef/event/test.js index de77a3e..98aa8d7 100644 --- a/app/event/test.js +++ b/app/chef/event/test.js @@ -7,4 +7,8 @@ module.exports = { "event2": (args) => { console.log(args || 'event2') }, + //status定义的有限状态机 + "start.ling": (args) => { + console.log(args || 'event2') + }, } diff --git a/app/event/全局事件定义文件 b/app/chef/event/全局事件定义文件 similarity index 100% rename from app/event/全局事件定义文件 rename to app/chef/event/全局事件定义文件 diff --git a/app/chef/status/test.js b/app/chef/status/test.js new file mode 100644 index 0000000..fe8b34d --- /dev/null +++ b/app/chef/status/test.js @@ -0,0 +1,13 @@ +'use strict'; +const Smf = require('bamboo_smf'); +const smf = new Smf() + +// 测试状态 +smf.init('test', 'start') + .push('start', 'start.ling') + .push('ling', 'start.end') + .push('end') + + +module.exports = smf.getSmfData() + diff --git a/app/components/公共函数 b/app/chef/status/状态管理 similarity index 100% rename from app/components/公共函数 rename to app/chef/status/状态管理 diff --git a/app/controller/index.js b/app/cms/controller/index.js similarity index 97% rename from app/controller/index.js rename to app/cms/controller/index.js index ab88c94..9d604e7 100644 --- a/app/controller/index.js +++ b/app/cms/controller/index.js @@ -2,14 +2,14 @@ module.exports = { doc : "默认页面", - path : "/", + path : "cms/index/", method : ["get", "post"], middleware: [], params : { "age": "int?" }, return : {}, - controller: async (ctx, app) => { + fun: async (ctx, app) => { console.log(ctx.request.body); // app.err.ParameterException() // app.event.emit('test.event2') @@ -59,6 +59,7 @@ module.exports = { // }, "save": "" // }, { + "as": "user_info", "table" : "UserInfo", "where" : { "uid": "$as.user_data.id",//根据别名 user_data 返回的结果中的id值作为条件查询 diff --git a/app/init.js b/app/cms/init.js similarity index 100% rename from app/init.js rename to app/cms/init.js diff --git a/app/model/User.js b/app/cms/model/User.js similarity index 79% rename from app/model/User.js rename to app/cms/model/User.js index 43530b4..808aeac 100644 --- a/app/model/User.js +++ b/app/cms/model/User.js @@ -1,8 +1,8 @@ module.exports = { doc : "用户", + api : true,//是否需要生成api接口 model: { uid: {type: "STRING", comment: '用户id'}, age: {type: "INTEGER", comment: '年龄', defaultValue: 0,}, - } } diff --git a/app/model/UserInfo.js b/app/cms/model/UserInfo.js similarity index 100% rename from app/model/UserInfo.js rename to app/cms/model/UserInfo.js diff --git a/app/model/数据库模型 b/app/cms/model/数据库模型 similarity index 100% rename from app/model/数据库模型 rename to app/cms/model/数据库模型 diff --git a/app/middleware/bodyparser.js b/app/middleware/bodyparser.js deleted file mode 100644 index facc9b8..0000000 --- a/app/middleware/bodyparser.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; -const bodyParser = require('koa-bodyparser') -// 错误处理 -module.exports = bodyParser() diff --git a/app/middleware/error.js b/app/middleware/error.js deleted file mode 100644 index 92a17ba..0000000 --- a/app/middleware/error.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; -const error = require('koa-json-error') -// 错误处理 -module.exports = error((err) => { - return { - status : err.status, - message : err.message, - code : err.code, - res : false, - // postFormat: (e, obj) => process.env.NODE_ENV === 'production' ? _.omit(obj, 'stack') : obj - } -}) diff --git a/app/middleware/koaLogger.js b/app/middleware/koaLogger.js deleted file mode 100644 index 49a2327..0000000 --- a/app/middleware/koaLogger.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; -const logger = require('koa-logger') -module.exports = logger() diff --git a/app/middleware/time.js b/app/middleware/time.js deleted file mode 100644 index bff09eb..0000000 --- a/app/middleware/time.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; -/*响应时间*/ -module.exports = async (ctx, next, app) => { - // console.log(ctx, next, options); - // const timetaken = `${ctx.request.method}${ctx.request.url} 响应时间` - // console.time(timetaken) - // app.logger.debug("123") - await next() - // console.timeEnd(timetaken) -} diff --git a/app/mkt/营销,推广 b/app/mkt/营销,推广 new file mode 100644 index 0000000..e69de29 diff --git a/app/mps/消息推送 b/app/mps/消息推送 new file mode 100644 index 0000000..e69de29 diff --git a/app/oms/订单管理 b/app/oms/订单管理 new file mode 100644 index 0000000..e69de29 diff --git a/app/sqlite/database.sqlite b/app/sqlite/database.sqlite deleted file mode 100644 index c38eb5c2227516375d418cdd19ab789a5355fa32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI%%Wm306b9fii9o7E=mxQ9C1x2!Kr>?-UsiDwt2F_V5~nJwm|#1C+yhy3nLI(; zP2M37(siGp>pn(@aFIZ1noXrB{39XH_=v;IH)AC0?0&3u2N8|WE>GG6s*=}4QOG)_ zgsgujge;Fg3L!<=y&n&+!zS(wdW-fKg!MuI0uX=z z1Rwwb2tWV=5P$##{)<5E$ypDT6v@^-kL>lM%eG;}p~bb32{VdA5yv5mRny|SsjHoe zE|?G{rj?jQ1-FH2t7f?(DzwO$&DbQ$1(hLPwYgd5hB1x~-~VON9}NN!fB*y_009U< z00Izz00bZafdvp4*8ekaSAH(QQn5q`KmY;|fB*y_009U<00Izr0Rq+KB*|tyZ&)`M zDpx1f?@?`>Rcu}<8-|#xjXxZ%E1-74~qhxo9;}O{Ao+=e?Osi8IPAn=@Mo znPyUuA4O;C{~b+eD%T8EH9I1VW1*RbB{X3im}bm1Ym)Fu^?zYAwQOnnc-DUa|LJxZ diff --git a/components/公共函数 b/components/公共函数 new file mode 100644 index 0000000..e69de29 diff --git a/config/database.js b/config/database.js index 6f44e78..c1a0bda 100644 --- a/config/database.js +++ b/config/database.js @@ -1,6 +1,6 @@ /*数据库配置*/ module.exports = { - mysql: { + mysql : { database: "bamboo", username: "bamboo", password: "bamboo", @@ -46,11 +46,31 @@ module.exports = { }, }, }, - redis:{}, - sqlite:{ + redis : {}, + sqlite: { dialect: 'sqlite', storage: 'app/sqlite/database.sqlite', logging: false, + // model的全局配置 + define : { + // 添加create,update,delete时间戳 + timestamps: true, + // 添加软删除 + paranoid: false, + // 防止修改表名为复数 + freezeTableName: true, + // 防止驼峰式字段被默认转为下划线 + underscored: false, + }, + dialectOptions: { + typeCast(field, next) {// 让读取date类型数据时返回字符串而不是UTC时间 + if (field.type === 'DATETIME') { + // console.log(field); + return field.string(); + } + return next(); + }, + }, }, diff --git a/config/extend.js b/config/extend.js new file mode 100644 index 0000000..87e9f64 --- /dev/null +++ b/config/extend.js @@ -0,0 +1,13 @@ +module.exports = { + dir: { + "event" : "app/*/event/*.js", + "status" : "app/*/status/*.js", + "controller": "app/*/controller/*.js", + "model" : "app/*/model/*.js", + "middleware": "middleware/*.js", + "extend" : "extend/*.js", + "schedule" : "schedule/*.js", + "sqlite" : "sqlite/model/*.js", + "config" : "config/*.js", + } +} diff --git a/config/middleware.js b/config/middleware.js index 7652933..c3d00a9 100644 --- a/config/middleware.js +++ b/config/middleware.js @@ -1,7 +1,4 @@ 'use strict'; module.exports = { - register: ["bodyparser", "error", "time", "koaLogger", "verify"], - time : { - params: '123' - }, + } diff --git a/extend/load/config.js b/extend/load/config.js new file mode 100644 index 0000000..a197a85 --- /dev/null +++ b/extend/load/config.js @@ -0,0 +1,4 @@ +//加载配置文件 +module.exports = (app) => { + +} diff --git a/lib/bamboo/bamboo.js b/lib/bamboo/bamboo.js new file mode 100644 index 0000000..3c94346 --- /dev/null +++ b/lib/bamboo/bamboo.js @@ -0,0 +1,123 @@ +const Koa = require("koa") +const load = require("./load") +const path = require('path') +const xe = require("xe-utils") +const EventEmitter = require('events'); +const Router = require("koa-router"); +const Parameter = require('parameter'); +const error = require('./errorException'); +const log4js = require("log4js"); +const Smf = require('./smf/smf'); + +module.exports = class Bamboo extends Koa { + constructor() { + super(); + this.init() + } + + path(args) { + return this.isPath + '/' + (args || "") + } + + isPath(args) { + return path.resolve('./' + (args || "")) + } + + get xe() { + return xe + } + + async init() { + this.config = {} + await this.loadConfig() + this.event = new EventEmitter() + this.parameter = new Parameter(); + this.error = error; + this.smf = new Smf() + log4js.configure(this.config['log']); + this.logger = log4js.getLogger(); + // await this.loadEvent() + // await this.loadStatus() + // await this.loadMiddleware() + // await this.loadController() + } + + /** + * 加载配置 + */ + async loadConfig() { + this.config = {} + const config = await load(this.isPath(), "config") + config.forEach(item => { + this.config[item.file_name] = item.res + }) + } + // + // /** + // * 加载事件 + // */ + // async loadEvent() { + // const event = await load(this.isPath(), "event") + // event.forEach(item => { + // Object.keys(item.res).forEach(key => { + // this.event.on(key, item.res[key]) + // }) + // }) + // } + // + // /** + // * 加载状态 + // */ + // async loadStatus() { + // const status = await load(this.isPath(), "status") + // const setSmfDataList = [] + // status.forEach(item => { + // setSmfDataList.push(item.res) + // }) + // this.smf.setSmfDataList(setSmfDataList) + // //监听流程变更 + // this.smf.on((e, paras) => { + // this.event.emit(e.currentState, paras) + // }) + // } + // + // /** + // * 加载控制器路由 + // */ + // async loadController() { + // const controller = await load(this.isPath(), "controller") + // const router = new Router(); + // controller.forEach(item => { + // item.res.method.forEach(method => { + // router[method](item.res.path, async (ctx, next) => { + // const validate = this.parameter.validate(item.res.params, ctx.request.body); + // if (validate) { + // console.error(validate); + // this.error.ParameterException(validate); + // } + // else { + // await item.res.fun(ctx, this.application) + // await next(); + // } + // }) + // }) + // }) + // } + // + // /** + // * 加载中间件 + // */ + // async loadMiddleware() { + // const middleware = await load(this.isPath(), "middleware") + // let hashList = xe.toArray(middleware) + // hashList = xe.orderBy(hashList, "fun.sort") + // hashList = hashList.filter(item => item.res.use) + // hashList.forEach(item => { + // this.use(async (ctx, next) => { + // ctx['logger'] = this.logger + // return await item.res.fun(ctx, next, this.application) + // }) + // }) + // } + +} diff --git a/app/err/errorException.js b/lib/bamboo/errorException.js similarity index 63% rename from app/err/errorException.js rename to lib/bamboo/errorException.js index 7fc90da..810a8f5 100644 --- a/app/err/errorException.js +++ b/lib/bamboo/errorException.js @@ -11,7 +11,7 @@ class HttpException extends Error { class ParameterException extends HttpException { constructor(message, code, status) { super() - this.status = status || 402 + this.status = status || 402 this.code = code this.message = message || '参数错误' } @@ -20,7 +20,7 @@ class ParameterException extends HttpException { class NotFound extends HttpException { constructor(message, code, status) { super() - this.status = status || 404 + this.status = status || 404 this.code = 404 this.message = message || '资源未找到' } @@ -29,7 +29,7 @@ class NotFound extends HttpException { class AuthFailed extends HttpException { constructor(message, code, status) { super() - this.status = status || 401 + this.status = status || 401 this.message = message || '授权失败' this.code = 401 } @@ -38,16 +38,16 @@ class AuthFailed extends HttpException { class Forbidden extends HttpException { constructor(message, code, status) { super() - this.status = status || 403 + this.status = status || 403 this.message = message || '禁止访问' this.code = 403 } } module.exports = { - HttpException, - ParameterException, - NotFound, - AuthFailed, - Forbidden, + HttpException: (message, code, status) => {throw new HttpException(message, code, status)}, + ParameterException: (message, code, status) => {throw new ParameterException(message, code, status)}, + NotFound: (message, code, status) => {throw new NotFound(message, code, status)}, + AuthFailed: (message, code, status) => {throw new AuthFailed(message, code, status)}, + Forbidden: (message, code, status) => {throw new Forbidden(message, code, status)}, } diff --git a/lib/bamboo/index.js b/lib/bamboo/index.js index e2be1f6..fc4c10c 100644 --- a/lib/bamboo/index.js +++ b/lib/bamboo/index.js @@ -92,7 +92,7 @@ module.exports = class Bamboo extends Koa { registeredError() { console.log('注册 错误'); this.errorException = {} - const hash = requireDirectory(module, this.path('app/err'), { + const hash = requireDirectory(module, this.path('lib/bamboo/err'), { visit: (obj) => { for (let key of Object.keys(obj)) { this.errorException[key] = (message, code) => { @@ -308,9 +308,8 @@ module.exports = class Bamboo extends Koa { const parse = path.parse(filename); // super.on(parse.name, obj); for (let key of Object.keys(obj)) { - this.event.on(`${parse.name}.${key}`, obj[key]); + this.event.on(`${parse.name}.${key}`, e[key]); } - return obj } }); @@ -338,18 +337,27 @@ module.exports = class Bamboo extends Koa { console.log('注册 middleware'); const hash = requireDirectory(module, this.path('app/middleware'), { visit: (obj, joined, filename) => { - console.log(obj, joined, filename); - const parse = path.parse(filename); - const config = this.config.middleware[parse.name] - // super.use(obj(config || {})) - super.use(async (ctx, next) => { - ctx['logger'] = this.logger - return await obj(ctx, next, this.application) - }) + // console.log(obj, joined, filename); + // const parse = path.parse(filename); + // const config = this.config.middleware[parse.name] + // // super.use(obj(config || {})) + // super.use(async (ctx, next) => { + // ctx['logger'] = this.logger + // return await obj.fun(ctx, next, this.application) + // }) return obj } }); - // console.log(hash); + let hashList = xe.toArray(hash) + hashList = xe.orderBy(hashList,"sort") + hashList = hashList.filter(item=>item.use) + hashList.forEach(item=>{ + super.use(async (ctx, next) => { + ctx['logger'] = this.logger + return await item.fun(ctx, next, this.application) + }) + }) + console.log(hashList); } //注册 utils @@ -938,7 +946,7 @@ module.exports = class Bamboo extends Koa { const tkKeys = Object.keys(tk) for (let key of tkKeys) { if (key === "as") { continue; } - if (key === "where"||key === "data") { + if (key === "where" || key === "data") { const findJsonRes = this.findJsonValue(tk[key], (n) => { if (typeof n === "string") { // console.log(tk[key],n); @@ -996,7 +1004,7 @@ module.exports = class Bamboo extends Koa { } path = path || [] // 获取所有的子节点,并遍历 - if (typeof n ==="object") { + if (typeof n === "object") { const nkeys = Object.keys(n) for (let k of nkeys) { // concat() 方法用于连接两个或多个数组 diff --git a/lib/bamboo/load.js b/lib/bamboo/load.js new file mode 100644 index 0000000..f9aa208 --- /dev/null +++ b/lib/bamboo/load.js @@ -0,0 +1,41 @@ +const glob = require("glob") +const path = require('path') +/** + * 项目文件加载 + */ +const list = { + "event" : "app/*/event/*.js", + "status" : "app/*/status/*.js", + "controller": "app/*/controller/*.js", + "model" : "app/*/model/*.js", + "middleware": "middleware/*.js", + "extend" : "extend/*.js", + "schedule" : "schedule/*.js", + "sqlite" : "sqlite/model/*.js", + "config" : "config/*.js", +} + +module.exports = function load(directory, key) { + return new Promise((resolve, reject) => { + const options = { + root: directory + } + glob(list[key], options, function (er, files) { + if (er) { reject(er) } + console.log(files); + files = files.map(item => { + const parse = path.parse(item); + return { + dir : parse.dir, + file_name: parse.name, + res : require(path.resolve(directory + "/" + item)) + } + }) + resolve(files) + }) + }) +} + + + + diff --git a/lib/bamboo/status.js b/lib/bamboo/status.js new file mode 100644 index 0000000..ac25af2 --- /dev/null +++ b/lib/bamboo/status.js @@ -0,0 +1,227 @@ +const xe = require("xe-utils") +/** + * 状态机-编排复杂的流程状态业务 + * @param {string} listName 列名. + */ +module.exports = class Status { + constructor(listName, status, data) { + this.data = data + this.status = status + this.listName = listName + this.list = [] + } + + /** + * 返回上个状态 + */ + back() { + let index = this.getStatusIndex(this.listName, this.status) + const res = this.getList(this.listName) + if ((index - 1) < 0) { + return null + } + const status = res.status[index - 1] + if (res.listName && status.name) { + this.go(res.listName, status.name) + } + return this + } + + /** + * 下一个状态 + */ + next() { + let index = this.getStatusIndex(this.listName, this.status) + const res = this.getList(this.listName) + if (res.status.length <= (index + 1)) { + return null + } + const status = res.status[index + 1] + if (res.listName && status.name) { + this.go(res.listName, status.name) + } + return this + } + + /** + * 触发成功事件 + */ + success() { + const index = this.getStatusIndex(this.listName, this.status) + const res = this.getList(this.listName) + const status = res.status[index] + if (status.success.event) { this.emitEvent(status.success.event) } + if (status.success.listName && status.success.status) { + this.go(status.success.listName, status.success.status) + } + return this + } + + emitEvent(eventName) { + console.log("emitEvent:", eventName); + } + + fail() { + const index = this.getStatusIndex(this.listName, this.status) + const res = this.getList(this.listName) + const status = res.status[index] + if (status.fail.event) { this.emitEvent(status.fail.event) } + if (status.fail.listName && status.fail.status) { + this.go(status.fail.listName, status.fail.status) + } + return this + } + + go(listName, status) { + this.status = status + this.listName = listName + return this + } + + getStatusIndex(listName, status) { + const res = this.getList(listName) + let index = xe.findKey(res.status, item => item.name === status) + return index ? Number(index) : null + } + + getList(listName) { + const res = this.list.filter(item => item.listName === listName) + if (res.length <= 0) { return false } + return res[0] + } + + push({status, success, fail}) { + const res = this.getList(this.listName) + if (res) { + success = success || {} + success["listName"] = success["listName"] || "" + success["status"] = success["status"] || "" + success["event"] = success["event"] || "" + fail = fail || {} + fail["listName"] = fail["listName"] || "" + fail["status"] = fail["status"] || "" + fail["event"] = fail["event"] || "" + + res.status.push({ + name : status, + success: success, + fail : fail, + }) + } + else {return false} + return this + } + + create(listName) { + if (!listName) { return false } + const res = this.getList(listName) + if (res) { return false } + this.list.push({ + listName: listName, + status : [] + }) + this.listName = listName + return this + } +} +// +// const s = new Status() +// +// s.create("ord") +// .push({ +// status : "start", +// success: { +// listName: "ord", //成功后切换到的listName +// status : "pay", //成功后切换到的status +// event : "ord.start", +// }, +// fail : { +// listName: "", //失败后切换到的listName +// status : "", //失败后切换到的status +// event : "", +// }, +// }) +// .push({ +// status : "pay", +// success: { +// listName: "ord", //成功后切换到的listName +// status : "end", //成功后切换到的status +// event : "ord.pay", +// }, +// fail : { +// listName: "refund", //失败后切换到的listName +// status : "start", //失败后切换到的status +// event : "", +// }, +// }) +// .push({ +// status : "end", +// success: { +// listName: "", //成功后切换到的listName +// status : "", //成功后切换到的status +// event : "ord.end", +// }, +// fail : { +// listName: "", //失败后切换到的listName +// status : "", //失败后切换到的status +// event : "", +// }, +// }) +// s.create("refund") +// .push({ +// status : "start", +// success: { +// listName: "refund", //成功后切换到的listName +// status : "ret", //成功后切换到的status +// event : "refund.start", +// }, +// fail : { +// listName: "", //失败后切换到的listName +// status : "", //失败后切换到的status +// event : "", +// }, +// }) +// .push({ +// status : "ret", +// success: { +// listName: "refund", //成功后切换到的listName +// status : "end", //成功后切换到的status +// event : "refund.ret", +// }, +// fail : { +// listName: "", //失败后切换到的listName +// status : "", //失败后切换到的status +// event : "", +// }, +// }) +// .push({ +// status : "end", +// success: { +// listName: "", //成功后切换到的listName +// status : "", //成功后切换到的status +// event : "refund.end", +// }, +// fail : { +// listName: "", //失败后切换到的listName +// status : "", //失败后切换到的status +// event : "", +// }, +// }) +// // console.log(s); +// +// s.go("ord", "start") +// console.log(s.listName, s.status); +// s.success() +// console.log(s.listName, s.status); +// s.fail() +// console.log(s.listName, s.status); +// s.success() +// console.log(s.listName, s.status); +// s.success() +// console.log(s.listName, s.status); +// s.success() +// console.log(s.listName, s.status); +// s.next() +// console.log(s.listName, s.status); + + diff --git a/lib/main.js b/lib/main.js index ca4290e..e7a9f8c 100644 --- a/lib/main.js +++ b/lib/main.js @@ -13,6 +13,6 @@ require('@babel/register')({ ] }) require('@babel/polyfill') -const bamboo = require('./bamboo/index') +const bamboo = require('./bamboo/bamboo') const app = new bamboo(); // app.listen(3000); diff --git a/middleware/bodyparser.js b/middleware/bodyparser.js new file mode 100644 index 0000000..16e20ec --- /dev/null +++ b/middleware/bodyparser.js @@ -0,0 +1,8 @@ +'use strict'; +const bodyParser = require('koa-bodyparser') +// 错误处理 +module.exports = { + sort: 4, //排序 + use : true, // 是否使用 + fun : bodyParser() +} diff --git a/middleware/error.js b/middleware/error.js new file mode 100644 index 0000000..9709b52 --- /dev/null +++ b/middleware/error.js @@ -0,0 +1,16 @@ +'use strict'; +const error = require('koa-json-error') +// 错误处理 +module.exports = { + sort: 3, //排序 + use : true, // 是否使用 + fun : error((err) => { + return { + status : err.status, + message: err.message, + code : err.code, + res : false, + // postFormat: (e, obj) => process.env.NODE_ENV === 'production' ? _.omit(obj, 'stack') : obj + } + }) +} diff --git a/middleware/koaLogger.js b/middleware/koaLogger.js new file mode 100644 index 0000000..1a3f527 --- /dev/null +++ b/middleware/koaLogger.js @@ -0,0 +1,7 @@ +'use strict'; +const logger = require('koa-logger') +module.exports = { + sort: 2, //排序 + use : true, // 是否使用 + fun : logger() +} diff --git a/middleware/time.js b/middleware/time.js new file mode 100644 index 0000000..4741f8c --- /dev/null +++ b/middleware/time.js @@ -0,0 +1,14 @@ +'use strict'; +/*响应时间*/ +module.exports = { + sort: 1, //排序 + use : true, // 是否使用 + fun : async (ctx, next, app) => { + // console.log(ctx, next, options); + // const timetaken = `${ctx.request.method}${ctx.request.url} 响应时间` + // console.time(timetaken) + // app.logger.debug("123") + await next() + // console.timeEnd(timetaken) + } +} diff --git a/middleware/全局中间件定义文件 b/middleware/全局中间件定义文件 new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json index 7e2ea08..d39ace4 100644 --- a/package.json +++ b/package.json @@ -39,13 +39,16 @@ "dependencies": { "@babel/core": "^7.16.7", "@babel/node": "^7.16.8", + "@babel/plugin-proposal-decorators": "^7.17.9", "@babel/polyfill": "^7.4.4", "@babel/preset-env": "^7.16.8", "@babel/runtime": "^7.5.5", "ajv": "^8.11.0", "babel-loader": "^8.2.3", + "bamboo_smf": "^1.0.5", "clean-webpack-plugin": "^4.0.0", "cross-env": "^7.0.3", + "glob": "^8.0.1", "koa-bodyparser": "^4.3.0", "koa-json-error": "^3.1.2", "koa-logger": "^2.0.1", diff --git a/schedule/pbm.js b/schedule/pbm.js new file mode 100644 index 0000000..b9c3e74 --- /dev/null +++ b/schedule/pbm.js @@ -0,0 +1,12 @@ +'use strict'; +// 定时任务 +module.exports = [ + { + name : "", + time : "*/3 * * * * *", + run : true,//系统启动时立即执行一次 + schedule: (app) => { + // console.log('每3秒我执行一次' + app.utils.VERSION) + } + }, +] diff --git a/app/schedule/test.js b/schedule/test.js similarity index 100% rename from app/schedule/test.js rename to schedule/test.js diff --git a/schedule/定时任务 b/schedule/定时任务 new file mode 100644 index 0000000..e69de29 diff --git a/sqlite/database.sqlite b/sqlite/database.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..87824de5f50312c7862477017bb220413ee25d76 GIT binary patch literal 176128 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