q-koa 11.3.4 → 11.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core/app.js
CHANGED
|
@@ -853,6 +853,7 @@ class APP {
|
|
|
853
853
|
!_.get(app, `${appName}.model.${controller}`) ||
|
|
854
854
|
!_.get(app, `${appName}.controller.${controller}`)
|
|
855
855
|
) {
|
|
856
|
+
console.error(`${controller}`)
|
|
856
857
|
throw new Error('路由model定义缺失')
|
|
857
858
|
}
|
|
858
859
|
await next()
|
|
@@ -870,6 +871,7 @@ class APP {
|
|
|
870
871
|
!_.get(app, `${appName}.model.${controller}.${fn}`) &&
|
|
871
872
|
!_.get(app, `${appName}.controller.${controller}.${fn}`)
|
|
872
873
|
) {
|
|
874
|
+
console.error(`${controller}.${fn}`)
|
|
873
875
|
throw new Error('路由fn定义缺失')
|
|
874
876
|
}
|
|
875
877
|
|
|
@@ -45,3 +45,599 @@ exports.initModel = async (ctx) => {
|
|
|
45
45
|
return ctx.ERROR(`app.model没有${model}`)
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
exports.customRouter = async (ctx) => {
|
|
50
|
+
// const {
|
|
51
|
+
// app,
|
|
52
|
+
// appName,
|
|
53
|
+
// } = getAppByCtx(ctx);
|
|
54
|
+
|
|
55
|
+
// const list = [{
|
|
56
|
+
// path: 'jiangong_statis',
|
|
57
|
+
// name: '数据面板'
|
|
58
|
+
// }]
|
|
59
|
+
const list = []
|
|
60
|
+
ctx.SUCCESS(list)
|
|
61
|
+
return list
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
exports.showTables = async (ctx) => {
|
|
65
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
66
|
+
|
|
67
|
+
if (app.cache && app.cache.get('showTables')) {
|
|
68
|
+
ctx.SUCCESS(app.cache.get('showTables'))
|
|
69
|
+
return app.cache.get('showTables')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const pluginDir = path.resolve(
|
|
73
|
+
__dirname,
|
|
74
|
+
`${process.cwd()}/app/${appName}/plugins`
|
|
75
|
+
)
|
|
76
|
+
let aliasModelList = []
|
|
77
|
+
const allList = await fsPromise.readdir(pluginDir)
|
|
78
|
+
allList.forEach((folder) => {
|
|
79
|
+
const isFolder = fs.lstatSync(path.resolve(pluginDir, folder)).isDirectory()
|
|
80
|
+
const hasConfig = fs.existsSync(
|
|
81
|
+
path.resolve(
|
|
82
|
+
__dirname,
|
|
83
|
+
`${process.cwd()}/app/${appName}/plugins/${folder}/config.js`
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
let hasModel = false
|
|
87
|
+
if (hasConfig) {
|
|
88
|
+
const folderConfig = require(`${process.cwd()}/app/${appName}/plugins/${folder}/config.js`)
|
|
89
|
+
if (folderConfig.model) {
|
|
90
|
+
hasModel = true
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (
|
|
95
|
+
isFolder &&
|
|
96
|
+
hasConfig &&
|
|
97
|
+
hasModel &&
|
|
98
|
+
!Object.keys(app.model).includes(folder)
|
|
99
|
+
) {
|
|
100
|
+
aliasModelList = [...aliasModelList, folder]
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
const modelList = [...Object.keys(app.model), ...aliasModelList]
|
|
104
|
+
const models = modelList.map((_model) => {
|
|
105
|
+
const defaultExcludes = [
|
|
106
|
+
'id',
|
|
107
|
+
'created_at',
|
|
108
|
+
'updated_at',
|
|
109
|
+
'deleted_at',
|
|
110
|
+
'createdid',
|
|
111
|
+
]
|
|
112
|
+
const mock = !lodash.isEmpty(
|
|
113
|
+
app.mock && app.mock[_model] && app.mock[_model]()
|
|
114
|
+
)
|
|
115
|
+
const defaultConfigPath = path.resolve(__dirname, `../${_model}/config.js`)
|
|
116
|
+
const defaultConfigExist = fs.existsSync(defaultConfigPath)
|
|
117
|
+
const target =
|
|
118
|
+
app.config[_model] &&
|
|
119
|
+
Object.keys(app.config[_model]).length === 0 &&
|
|
120
|
+
defaultConfigExist
|
|
121
|
+
? require(defaultConfigPath)
|
|
122
|
+
: app.config[_model]
|
|
123
|
+
// const target = Object.keys(app.config[model])
|
|
124
|
+
|
|
125
|
+
if (!target) throw new Error(`检查是否有${_model}/config.js`)
|
|
126
|
+
const model = target.model ? target.model : _model
|
|
127
|
+
return {
|
|
128
|
+
modelName: _model,
|
|
129
|
+
model,
|
|
130
|
+
name: target ? target.name : '',
|
|
131
|
+
// 属于哪个分类
|
|
132
|
+
belongs: lodash.get(target, 'belongs', 'page'),
|
|
133
|
+
// list切换tab显示 ex lanuage
|
|
134
|
+
limit: lodash.get(target, 'limit', 20),
|
|
135
|
+
excludeAuth: lodash.get(target, 'excludeAuth', []),
|
|
136
|
+
// 可排序字段
|
|
137
|
+
order: lodash.get(target, 'order', []),
|
|
138
|
+
// 默认排序
|
|
139
|
+
defaultOrder: lodash.get(target, 'defaultOrder', []),
|
|
140
|
+
// 下拉筛选
|
|
141
|
+
select: lodash.get(target, 'select', []),
|
|
142
|
+
// 是否可以选择批量删除
|
|
143
|
+
multiple: lodash.get(target, 'multiple', true),
|
|
144
|
+
// 是否后台拆分sql
|
|
145
|
+
is_split: lodash.get(target, 'is_split', false),
|
|
146
|
+
// 是否后台拆分count
|
|
147
|
+
is_split_count: lodash.get(target, 'is_split_count', false),
|
|
148
|
+
// 是否后台显示虚拟字段
|
|
149
|
+
show_virtual: lodash.get(target, 'show_virtual', false),
|
|
150
|
+
// 忽略字段
|
|
151
|
+
excludes:
|
|
152
|
+
_model === 'setting'
|
|
153
|
+
? lodash.get(target, 'excludes', [])
|
|
154
|
+
: lodash.difference(
|
|
155
|
+
lodash.uniq([
|
|
156
|
+
...defaultExcludes,
|
|
157
|
+
...lodash.get(target, 'excludes', []),
|
|
158
|
+
]),
|
|
159
|
+
lodash.get(target, 'order', [])
|
|
160
|
+
),
|
|
161
|
+
// reference admin components
|
|
162
|
+
reference: lodash.get(target, 'reference', []),
|
|
163
|
+
// reference admin components
|
|
164
|
+
personal: lodash.get(target, 'personal', []),
|
|
165
|
+
// sortOrder router
|
|
166
|
+
sortOrder: lodash.get(target, 'sortOrder', 1),
|
|
167
|
+
|
|
168
|
+
attributes: lodash.mapValues(
|
|
169
|
+
app.attributes[model],
|
|
170
|
+
(item) => item.comment
|
|
171
|
+
),
|
|
172
|
+
|
|
173
|
+
// include for admin
|
|
174
|
+
include: lodash.get(target, 'include', ''),
|
|
175
|
+
// only include exsit, and for custom like user_distribute has two user model
|
|
176
|
+
relate: lodash.get(target, 'relate', ''),
|
|
177
|
+
// can be mock boolean
|
|
178
|
+
mock,
|
|
179
|
+
// reference model query
|
|
180
|
+
referenceSelect: lodash.get(target, 'referenceSelect', []),
|
|
181
|
+
// 是否可以选择批量删除
|
|
182
|
+
availableSort: lodash.get(target, 'availableSort', false),
|
|
183
|
+
// 用于后台管理不要查询太多数据,常用于表多的model
|
|
184
|
+
autoData: lodash.get(target, 'autoData', null),
|
|
185
|
+
// 有些model需要前置查询其它model数据
|
|
186
|
+
initList: lodash.get(target, 'initList', []),
|
|
187
|
+
// 有些table需要前置查询数据
|
|
188
|
+
initTableList: lodash.get(target, 'initTableList', []),
|
|
189
|
+
// 局部更新列表
|
|
190
|
+
editInline: lodash.get(target, 'editInline', {}),
|
|
191
|
+
// 有些model需要前置查询其它model数据
|
|
192
|
+
comment: lodash.get(target, 'comment', {}),
|
|
193
|
+
// 默认查询,覆盖之前
|
|
194
|
+
modelQuery: lodash.get(target, 'modelQuery', {}),
|
|
195
|
+
// 默认更新,覆盖之前
|
|
196
|
+
modelUpsert: lodash.get(target, 'modelUpsert', {}),
|
|
197
|
+
// 软删除比如is_on:false,就upsert
|
|
198
|
+
modelDelete: lodash.get(target, 'modelDelete', {}),
|
|
199
|
+
// 删除时检查是不是含有
|
|
200
|
+
deleteCheckList: lodash.get(target, 'deleteCheckList', []),
|
|
201
|
+
// 批量更新字段
|
|
202
|
+
bulkCreateList: lodash.get(target, 'bulkCreateList', []),
|
|
203
|
+
|
|
204
|
+
fn: app.controller[_model] ? Object.keys(app.controller[_model]) : [],
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
ctx.SUCCESS(models)
|
|
209
|
+
app.cache && app.cache.set('showTables', models)
|
|
210
|
+
return models
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
exports.getTable = async (ctx) => {
|
|
214
|
+
const { app } = getAppByCtx(ctx)
|
|
215
|
+
|
|
216
|
+
const {
|
|
217
|
+
model: _model,
|
|
218
|
+
show_virtual = false,
|
|
219
|
+
is_cache = true,
|
|
220
|
+
} = ctx.request.body
|
|
221
|
+
if (_model === 'page') return ctx.SUCCESS({})
|
|
222
|
+
if (is_cache && app.cache && app.cache.get(`${_model}-table`)) {
|
|
223
|
+
return ctx.SUCCESS(app.cache.get(`${_model}-table`))
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const model = app.config[_model].model || _model
|
|
227
|
+
|
|
228
|
+
const _result = await app.sequelize.getQueryInterface().describeTable(model)
|
|
229
|
+
|
|
230
|
+
const modelAttributes = lodash.cloneDeep(app.attributes[model])
|
|
231
|
+
const result = lodash.pick(_result, [
|
|
232
|
+
...Object.keys(modelAttributes),
|
|
233
|
+
'id',
|
|
234
|
+
'createdid',
|
|
235
|
+
'updated_at',
|
|
236
|
+
'created_at',
|
|
237
|
+
])
|
|
238
|
+
|
|
239
|
+
const obj = {}
|
|
240
|
+
if (show_virtual) {
|
|
241
|
+
Array.from(
|
|
242
|
+
new Set([...Object.keys(result), ...Object.keys(modelAttributes)])
|
|
243
|
+
).forEach((attr) => {
|
|
244
|
+
obj[attr] = lodash.merge(
|
|
245
|
+
modelAttributes[attr],
|
|
246
|
+
lodash.omitBy(result[attr], lodash.isNull),
|
|
247
|
+
app.config[_model].comment && app.config[_model].comment
|
|
248
|
+
? app.config[_model].comment[attr]
|
|
249
|
+
: {}
|
|
250
|
+
)
|
|
251
|
+
})
|
|
252
|
+
} else {
|
|
253
|
+
Object.keys(result).forEach((attr) => {
|
|
254
|
+
obj[attr] = lodash.merge(
|
|
255
|
+
modelAttributes[attr],
|
|
256
|
+
lodash.omitBy(result[attr], lodash.isNull),
|
|
257
|
+
app.config[_model].comment && app.config[_model].comment
|
|
258
|
+
? app.config[_model].comment[attr]
|
|
259
|
+
: {}
|
|
260
|
+
)
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
app.cache && app.cache.set(`${_model}-table`, obj)
|
|
265
|
+
return ctx.SUCCESS(obj)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
exports.dropModel = async (ctx) => {
|
|
269
|
+
const { app } = getAppByCtx(ctx)
|
|
270
|
+
|
|
271
|
+
const { model } = ctx.request.body
|
|
272
|
+
const result = await app.model[model].drop()
|
|
273
|
+
return ctx.SUCCESS(result)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
exports.getImage = async (ctx) => {
|
|
277
|
+
const { app } = getAppByCtx(ctx)
|
|
278
|
+
|
|
279
|
+
const appConfig = getConfig(app)
|
|
280
|
+
|
|
281
|
+
const { site_host } = await appConfig.getObject('base')
|
|
282
|
+
// const { dir, upload } = app.config.static;
|
|
283
|
+
const targetDir = `${path.resolve(
|
|
284
|
+
__dirname,
|
|
285
|
+
`${process.cwd()}/public/upload`
|
|
286
|
+
)}`
|
|
287
|
+
const files = await fsPromise.readdir(targetDir)
|
|
288
|
+
const images = files.filter((file) =>
|
|
289
|
+
/\w(\.gif|\.jpeg|\.png|\.jpg|\.bmp)/i.test(file)
|
|
290
|
+
)
|
|
291
|
+
const result = []
|
|
292
|
+
for (let i = 0; i < images.length; i++) {
|
|
293
|
+
const image = `${path.resolve(
|
|
294
|
+
__dirname,
|
|
295
|
+
`${process.cwd()}/public/upload/${images[i]}`
|
|
296
|
+
)}`
|
|
297
|
+
|
|
298
|
+
result.push({
|
|
299
|
+
img: `http://${site_host || 'api.kuashou.com'}/upload/${images[i]}`,
|
|
300
|
+
name: images[i],
|
|
301
|
+
...fs.statSync(image),
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
ctx.SUCCESS(result)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
exports.mock = async (ctx) => {
|
|
309
|
+
const { app } = getAppByCtx(ctx)
|
|
310
|
+
|
|
311
|
+
const { model } = ctx.request.body
|
|
312
|
+
const result = app.mock && app.mock[model] && app.mock[model]()
|
|
313
|
+
return ctx.SUCCESS(!lodash.isEmpty(result))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
exports.table = async (ctx) => {
|
|
317
|
+
const { app } = getAppByCtx(ctx)
|
|
318
|
+
const { model } = ctx.request.body
|
|
319
|
+
if (!model) {
|
|
320
|
+
const result = Object.keys(app.model).map((m) => ({
|
|
321
|
+
[m]: lodash.mapValues(app.attributes[m], (item) => item.comment),
|
|
322
|
+
}))
|
|
323
|
+
ctx.SUCCESS(result)
|
|
324
|
+
} else {
|
|
325
|
+
const result = app.attributes[model]
|
|
326
|
+
ctx.SUCCESS(result)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
exports.showAllSchemas = async (ctx) => {
|
|
331
|
+
const { app } = getAppByCtx(ctx)
|
|
332
|
+
|
|
333
|
+
const { model } = ctx.request.body
|
|
334
|
+
const result = await app.sequelize.getQueryInterface().describeTable(model)
|
|
335
|
+
return ctx.SUCCESS(result)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
exports.initDataWithCache = exports.initData = async (ctx) => {
|
|
339
|
+
const { app } = getAppByCtx(ctx)
|
|
340
|
+
const appConfig = getConfig(app)
|
|
341
|
+
|
|
342
|
+
const { is_cache } = await appConfig.getObject('base')
|
|
343
|
+
const { includes, excludes = [] } = ctx.request.body
|
|
344
|
+
|
|
345
|
+
const cacheTarget = JSON.stringify(ctx.request.body)
|
|
346
|
+
|
|
347
|
+
let result = null
|
|
348
|
+
if (is_cache && cache.get(cacheTarget)) {
|
|
349
|
+
result = cache.get(cacheTarget)
|
|
350
|
+
} else {
|
|
351
|
+
result = await app.service.system.initData({
|
|
352
|
+
app,
|
|
353
|
+
includes,
|
|
354
|
+
excludes,
|
|
355
|
+
ctx,
|
|
356
|
+
})
|
|
357
|
+
if (is_cache && cacheTarget.includes('setting/findAll')) {
|
|
358
|
+
cache.set(cacheTarget, result)
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return ctx.SUCCESS(result)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
exports.recentlyError = async (ctx) => {
|
|
365
|
+
// const {
|
|
366
|
+
// app,
|
|
367
|
+
// appName,
|
|
368
|
+
// } = getAppByCtx(ctx);
|
|
369
|
+
|
|
370
|
+
if (ctx.ws) {
|
|
371
|
+
const ws = await ctx.ws()
|
|
372
|
+
const send = (data) => ws.send(JSON.stringify(data))
|
|
373
|
+
ctx.app.on('error', async (err) => {
|
|
374
|
+
console.log(err)
|
|
375
|
+
try {
|
|
376
|
+
send({
|
|
377
|
+
type: 'error',
|
|
378
|
+
payload: err ? err.errorData : {},
|
|
379
|
+
})
|
|
380
|
+
} catch (e) {
|
|
381
|
+
console.log(e)
|
|
382
|
+
}
|
|
383
|
+
})
|
|
384
|
+
} else {
|
|
385
|
+
throw new Error('这是一个websocket url')
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
exports.sandbox = async (ctx) => {
|
|
390
|
+
const code = `
|
|
391
|
+
module.exports = async (callback)=>{
|
|
392
|
+
callback({
|
|
393
|
+
name:1
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
`
|
|
397
|
+
// const { code } = ctx.request.body;
|
|
398
|
+
const vm = new VM({
|
|
399
|
+
sandbox: {
|
|
400
|
+
axios,
|
|
401
|
+
cheerio,
|
|
402
|
+
module,
|
|
403
|
+
setTimeout,
|
|
404
|
+
sleep: (time) =>
|
|
405
|
+
new Promise((resolve) => setTimeout(resolve, time * 1000)),
|
|
406
|
+
},
|
|
407
|
+
})
|
|
408
|
+
vm.run(code)(ctx.SUCCESS)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
exports.onlineChat = async (ctx) => {
|
|
412
|
+
if (ctx.ws) {
|
|
413
|
+
const ws = await ctx.ws()
|
|
414
|
+
const send = (data) => ws.send(JSON.stringify(data))
|
|
415
|
+
ws.on('message', async (code) => {
|
|
416
|
+
const vm = new VM({
|
|
417
|
+
sandbox: {
|
|
418
|
+
send: (data) => ws.send(JSON.stringify(data)),
|
|
419
|
+
axios,
|
|
420
|
+
cheerio,
|
|
421
|
+
},
|
|
422
|
+
})
|
|
423
|
+
vm.run(code)
|
|
424
|
+
const unhandledRejections = {}
|
|
425
|
+
|
|
426
|
+
process.on('unhandledRejection', (reason) => {
|
|
427
|
+
if (unhandledRejections[reason]) {
|
|
428
|
+
console.log('====?', reason)
|
|
429
|
+
} else {
|
|
430
|
+
send({
|
|
431
|
+
type: 'error',
|
|
432
|
+
payload: `${reason}`,
|
|
433
|
+
})
|
|
434
|
+
unhandledRejections[reason] = true
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
})
|
|
438
|
+
} else {
|
|
439
|
+
throw new Error('这是一个websocket url')
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
exports.chat = async (ctx) => {
|
|
444
|
+
const { app } = getAppByCtx(ctx)
|
|
445
|
+
if (ctx.ws) {
|
|
446
|
+
const ws = await ctx.ws()
|
|
447
|
+
const send = (data) => ws.send(JSON.stringify(data))
|
|
448
|
+
ws.on('message', async (payload) => {
|
|
449
|
+
const message = JSON.parse(payload)
|
|
450
|
+
const result = await app.model.ask.create({
|
|
451
|
+
user_id: message.payload.user_id,
|
|
452
|
+
content: message.payload.content,
|
|
453
|
+
is_ask: Boolean(message.payload.user_id),
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
send({
|
|
457
|
+
type: 'message',
|
|
458
|
+
payload: result,
|
|
459
|
+
})
|
|
460
|
+
})
|
|
461
|
+
} else {
|
|
462
|
+
throw new Error('这是一个websocket url')
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
exports.task = async (ctx) => {
|
|
467
|
+
const { app } = getAppByCtx(ctx)
|
|
468
|
+
|
|
469
|
+
const { task } = ctx.request.body
|
|
470
|
+
|
|
471
|
+
if (app.task && app.task[task]) {
|
|
472
|
+
await app.task[task](app)
|
|
473
|
+
}
|
|
474
|
+
ctx.SUCCESS(task)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
exports.dashboard = async (ctx) => {
|
|
478
|
+
// const {
|
|
479
|
+
// app,
|
|
480
|
+
// } = getAppByCtx(ctx);
|
|
481
|
+
|
|
482
|
+
const result = [
|
|
483
|
+
// {
|
|
484
|
+
// name: '用户',
|
|
485
|
+
// number: 5,
|
|
486
|
+
// route: 'page/user'
|
|
487
|
+
// }
|
|
488
|
+
]
|
|
489
|
+
ctx.SUCCESS(result)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
exports.showAllModel = async (ctx) => {
|
|
493
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
494
|
+
const { is_count = false } = ctx.request.body
|
|
495
|
+
const result = await app.sequelize.showAllSchemas()
|
|
496
|
+
const list = result.map(
|
|
497
|
+
(item) => item[`Tables_in_${app.sequelize.config.database}`]
|
|
498
|
+
)
|
|
499
|
+
let tableList = []
|
|
500
|
+
for (let i = 0; i < list.length; i++) {
|
|
501
|
+
if (!app.model[list[i]]) continue
|
|
502
|
+
const defaultConfigPath = path.resolve(__dirname, `../${list[i]}/config.js`)
|
|
503
|
+
const defaultConfigExist = fs.existsSync(defaultConfigPath)
|
|
504
|
+
const target =
|
|
505
|
+
app.config[list[i]] &&
|
|
506
|
+
Object.keys(app.config[list[i]]).length === 0 &&
|
|
507
|
+
defaultConfigExist
|
|
508
|
+
? require(defaultConfigPath)
|
|
509
|
+
: app.config[list[i]]
|
|
510
|
+
let count = 0
|
|
511
|
+
if (is_count) {
|
|
512
|
+
count = await app.model[list[i]].count()
|
|
513
|
+
}
|
|
514
|
+
tableList = [
|
|
515
|
+
...tableList,
|
|
516
|
+
{
|
|
517
|
+
count,
|
|
518
|
+
name: target.name,
|
|
519
|
+
model: list[i],
|
|
520
|
+
count,
|
|
521
|
+
},
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
return ctx.SUCCESS(
|
|
525
|
+
tableList.map((item) => lodash.omit(item, is_count ? [] : ['count']))
|
|
526
|
+
)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
exports.drop = async (ctx) => {
|
|
530
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
531
|
+
|
|
532
|
+
const result = await app.sequelize.showAllSchemas()
|
|
533
|
+
const list = result.map(
|
|
534
|
+
(item) => item[`Tables_in_${app.sequelize.config.database}`]
|
|
535
|
+
)
|
|
536
|
+
const filterList = list.filter((item) => !app.model[item])
|
|
537
|
+
await Promise.all(
|
|
538
|
+
filterList.map((folder) => {
|
|
539
|
+
const model = app.sequelize.define(
|
|
540
|
+
folder,
|
|
541
|
+
{
|
|
542
|
+
id: {
|
|
543
|
+
type: Sequelize.INTEGER(11),
|
|
544
|
+
allowNull: false,
|
|
545
|
+
primaryKey: true,
|
|
546
|
+
autoIncrement: true,
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
freezeTableName: true,
|
|
551
|
+
comment: folder,
|
|
552
|
+
createdAt: 'created_at',
|
|
553
|
+
updatedAt: 'updated_at',
|
|
554
|
+
name: {
|
|
555
|
+
singular: folder,
|
|
556
|
+
plural: `${folder}s`,
|
|
557
|
+
},
|
|
558
|
+
}
|
|
559
|
+
)
|
|
560
|
+
return model.drop()
|
|
561
|
+
})
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
ctx.SUCCESS(`删除${filterList.length}个无用表`)
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
exports.mockPay = async (ctx) => {
|
|
568
|
+
const { app } = getAppByCtx(ctx)
|
|
569
|
+
const { order_id, order_price, prefix, ...rest } = ctx.request.body
|
|
570
|
+
const model = prefix ? `${prefix}_order` : 'order'
|
|
571
|
+
console.log(model, 'model')
|
|
572
|
+
if (!(app.service[model] && app.service[model].notify)) {
|
|
573
|
+
throw new Error(`没配置${model}支付回调notify`)
|
|
574
|
+
}
|
|
575
|
+
await app.service[model].notify({
|
|
576
|
+
app,
|
|
577
|
+
order_id,
|
|
578
|
+
order: model,
|
|
579
|
+
order_price,
|
|
580
|
+
...rest,
|
|
581
|
+
})
|
|
582
|
+
ctx.SUCCESS('ok')
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
exports.copyOther = async (ctx) => {
|
|
586
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
587
|
+
|
|
588
|
+
const { model, source } = ctx.request.body
|
|
589
|
+
if (!model) return ctx.ERROR('model?')
|
|
590
|
+
if (!source) return ctx.ERROR('source? https://www.kuashou.com/kuashou')
|
|
591
|
+
let list = []
|
|
592
|
+
if (Array.isArray(model)) {
|
|
593
|
+
list = model
|
|
594
|
+
} else {
|
|
595
|
+
if (model !== 'all') {
|
|
596
|
+
list = [model]
|
|
597
|
+
} else {
|
|
598
|
+
const result = await app.sequelize.showAllSchemas()
|
|
599
|
+
list = result.map(
|
|
600
|
+
(item) => item[`Tables_in_${app.sequelize.config.database}`]
|
|
601
|
+
)
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const prefix = `${source}`
|
|
606
|
+
let successList = []
|
|
607
|
+
let failList = []
|
|
608
|
+
for (let i = 0; i < list.length; i++) {
|
|
609
|
+
const url = `${prefix}/${list[i]}/findAll`
|
|
610
|
+
|
|
611
|
+
const result = await axios
|
|
612
|
+
.post(
|
|
613
|
+
url,
|
|
614
|
+
{},
|
|
615
|
+
{
|
|
616
|
+
headers: {
|
|
617
|
+
'Client-Type': 0,
|
|
618
|
+
},
|
|
619
|
+
}
|
|
620
|
+
)
|
|
621
|
+
.then((res) => res.data)
|
|
622
|
+
if (result.code === 200) {
|
|
623
|
+
await app.model[list[i]].sync({
|
|
624
|
+
force: true,
|
|
625
|
+
})
|
|
626
|
+
try {
|
|
627
|
+
await app.model[list[i]].bulkCreate(
|
|
628
|
+
result.data.map((i) => lodash.omitBy(i, lodash.isNull)),
|
|
629
|
+
{}
|
|
630
|
+
)
|
|
631
|
+
successList = [...successList, list[i]]
|
|
632
|
+
} catch (e) {
|
|
633
|
+
console.log(e.message)
|
|
634
|
+
failList = [...failList, list[i]]
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
console.log(url, result.data)
|
|
638
|
+
failList = [...failList, list[i]]
|
|
639
|
+
continue
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
ctx.SUCCESS({ successList, failList })
|
|
643
|
+
}
|
|
@@ -1352,7 +1352,13 @@ exports.refund_notify = async (ctx) => {
|
|
|
1352
1352
|
app_key: key.length > 10 ? key : partner_key,
|
|
1353
1353
|
})
|
|
1354
1354
|
|
|
1355
|
-
const {
|
|
1355
|
+
const {
|
|
1356
|
+
out_refund_no,
|
|
1357
|
+
out_trade_no,
|
|
1358
|
+
total_fee,
|
|
1359
|
+
refund_fee,
|
|
1360
|
+
refund_desc,
|
|
1361
|
+
} = refundResult
|
|
1356
1362
|
|
|
1357
1363
|
const refund_price = Number(refund_fee) / 100
|
|
1358
1364
|
|
|
@@ -1367,9 +1373,7 @@ exports.refund_notify = async (ctx) => {
|
|
|
1367
1373
|
: Number(out_refund_no)
|
|
1368
1374
|
const type = out_refund_no.includes('_') ? out_refund_no.split('_')[1] : ''
|
|
1369
1375
|
const model = prefix ? `${prefix}_order` : 'order'
|
|
1370
|
-
|
|
1371
|
-
// `微信退款回调 prefix:${prefix}/model:${model}/order_id:${order_id}/type:${type}`
|
|
1372
|
-
// )
|
|
1376
|
+
console.log(`微信退款回调 ${refund_desc}`)
|
|
1373
1377
|
if (app.service[model] && app.service[model].refund_notify) {
|
|
1374
1378
|
await app.service[model].refund_notify({
|
|
1375
1379
|
app,
|
|
@@ -1377,6 +1381,7 @@ exports.refund_notify = async (ctx) => {
|
|
|
1377
1381
|
order: model,
|
|
1378
1382
|
refund_price,
|
|
1379
1383
|
type,
|
|
1384
|
+
out_refund_no,
|
|
1380
1385
|
})
|
|
1381
1386
|
}
|
|
1382
1387
|
|
|
@@ -1706,7 +1711,7 @@ exports.setMsgJumpPath = async (ctx) => {
|
|
|
1706
1711
|
const { app, appName } = getAppByCtx(ctx)
|
|
1707
1712
|
const appConfig = getConfig(app)
|
|
1708
1713
|
|
|
1709
|
-
const {config = 'weixin_mp'
|
|
1714
|
+
const { config = 'weixin_mp', path = 'pages/index/index' } = ctx.request.body
|
|
1710
1715
|
const { app_id, app_secrect } = await appConfig.getObject(config)
|
|
1711
1716
|
|
|
1712
1717
|
const weixinMp = new WeixinMp({
|
|
@@ -1721,4 +1726,4 @@ exports.setMsgJumpPath = async (ctx) => {
|
|
|
1721
1726
|
})
|
|
1722
1727
|
|
|
1723
1728
|
ctx.SUCCESS('ok')
|
|
1724
|
-
}
|
|
1729
|
+
}
|