doomiwork 4.1.9 → 4.2.0

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.
@@ -1,30 +0,0 @@
1
- const errnum = require('./enumconst')
2
-
3
- class ActionResult {
4
- constructor({ successed = true, errcode = 0, errmessage = '', data = [] }) {
5
- return { successed: successed, errorcode: errorcode, errmessage: errmessage, data: data }
6
- }
7
- //*为结果添加一些附加的值
8
- static decorateResult(result, opts) {
9
- Object.keys(opts).forEach(key => {
10
- result[key] = opts[key];
11
- });
12
- return result;
13
- }
14
- }
15
- ActionResult.DB_CONNECTED_FAILED = { successed: false, errmessage: 'DB_CONNECTED_FAILED', errorcode: errnum.DATABASE_ERROR.DATABASE_CONNECTED_ERROR };
16
- ActionResult.DB_EXECUTE_FAILED = { successed: false, errorcode: errnum.DATABASE_ERROR.DATABASE_EXECUTE_ERROR };
17
- ActionResult.DB_NO_EFFECTIVE = { successed: false, errmessage: 'DB_NO_EFFECTIVE', errorcode: errnum.DATABASE_ERROR.NO_RECORD_EFFECTED };
18
- ActionResult.DB_NO_RECORD_FOUND = { successed: false, errmessage: 'DB_NO_RECORD_FOUND', errorcode: errnum.DATABASE_ERROR.NO_RECORD_FOUND };
19
-
20
- ActionResult.SUCCESS_RESULT = { successed: true, errorcode: 0 };
21
- ActionResult.RETURN_TO_INDEX = { successed: false, errorcode: errnum.COMMON_ERROR.VISIT_TO_INDEX };
22
- ActionResult.TOKEN_IS_EXPIRED = { successed: false, errmessage: 'TOKEN_IS_EXPIRED', errorcode: errnum.COMMON_ERROR.TOKEN_EXPIRED , total: 0, rows: [] };
23
- ActionResult.TOKEN_IS_INVALID = { successed: false, errmessage: 'TOKEN_IS_INVALID', errorcode: errnum.COMMON_ERROR.TOKEN_IS_INVALID, total: 0, rows: [] };
24
- ActionResult.TOKEN_IS_MISSING = { successed: false, errmessage: 'TOKEN_IS_MISSING', errorcode: errnum.COMMON_ERROR.TOKEN_IS_MISSING, total: 0, rows: [] };
25
- ActionResult.UNAUTHORIZATION_RESULT = { successed: false, errmessage: 'UNAUTHORIZATION_RESULT', errorcode: errnum.COMMON_ERROR.UNAUTHORIZATION_ERROR, total: 0, rows: [] };
26
- ActionResult.NO_ACCESS_RIGHT_RESULT = { successed: false, errmessage: 'NO_ACCESS_RIGHT_RESULT', errorcode: errnum.COMMON_ERROR.NO_ACCESS_RIGHT, total: 0, rows: [] };
27
- ActionResult.API_PARAMETERS_ERROR_RESULT = { successed: false, errmessage: 'API_PARAMETERS_ERROR_RESULT', errorcode: errnum.COMMON_ERROR.API_PARAMETERS_ERROR, total: 0, rows: [] };
28
- ActionResult.VERIFY_CODE_ERROR = { successed: false, errmessage: 'VERIFY_CODE_ERROR', errorcode: errnum.COMMON_ERROR.VERIFY_CODE_ERROR, total: 0, rows: [] };
29
-
30
- exports = module.exports = ActionResult;
@@ -1,380 +0,0 @@
1
- /*
2
- * Controller 基类
3
- * 所有Node编写的业务处理控制类都集成此基类,路由的配置直接配置在roterConfig.json中
4
- * 功能:
5
- * 基类主要实现了数据基础的增删改查的基本操作,如无特殊业务逻辑子类已无需再
6
- * 重新实现,如有特殊的业务可以重写几个方法
7
- */
8
- const express = require('express');
9
- const {Data2View,View2Data} = require('../utilities/transferutility');
10
- const ExcelUtility = require('../utilities/excelutility');
11
- const constEnum = require('./enumconst');
12
- const { getListInfo, getDetailInfo, parseTagInSql } = require('../utilities/requestparser');
13
- const apiResult = require('./actionresult');
14
- const daoBase = require('./database/daoBase');
15
- const exportUtility = ExcelUtility.getInstance();
16
-
17
- class controller {
18
- /**
19
- * 构造函数,每个Controller传递进来本业务的数据访问实例
20
- * @param {*} application app 对象
21
- * @param {*} dao DAO层
22
- */
23
- constructor(application, dao) {
24
- this.app = application;
25
- ///高速缓存
26
- this._redisHelper = this.app.redis;
27
- ///日志记录器
28
- this.logger = this.app.logger;
29
- ///用户行为记录器
30
- this.actionLogger = this.app.actionLogger;
31
- ///需要数据访问实体的实例
32
- this._daoModel = dao?dao:new daoBase();
33
- this._daoModel.actionLogger = this.actionLogger;
34
- this._daoModel.logger = application.logger;
35
- this._router = express.Router();
36
- ///实现的集成类中只需要去重写此方法
37
- this.initializeRouter(this);
38
-
39
- }
40
- get router() { return this._router; }
41
- get baseUrl() { return null };
42
- /**
43
- * 权限的业务sql过滤
44
- */
45
- PermissonBusiness(_req){
46
- return null;
47
- }
48
- /**
49
- * 导出数据到Excel 中
50
- * @param {*} data
51
- * @param {*} excelkey
52
- */
53
- async export2Excel(data,excelkey) {
54
- let excelResult = await exportUtility.recordset2ExcelFile(data,excelkey, this.beforeExportExcel)
55
- return excelResult;
56
- }
57
- /**
58
- * 导出数据到Excel的多个workseet中
59
- * @param {*} data
60
- * @param {*} excelkey
61
- */
62
- async export2MutlisheetExcel(datainfo) {
63
- if (!Array.isArray(datainfo) || datainfo.length == 0) return {successed:false};
64
- let excelResult = await exportUtility.recordset2MutlisheetExcelFile(datainfo, this.beforeExportExcel)
65
- return excelResult;
66
- }
67
- /**
68
- * 写入Excel数据
69
- * @param {*} data
70
- * @param {*} excelkey
71
- * @returns
72
- */
73
- async writeExcel(data, excelkey){
74
- let excelResult = await exportUtility.writeExcel(data, excelkey)
75
- return excelResult;
76
- }
77
- /**
78
- * 记录用户的操作行为
79
- * req:HttpRequest
80
- * business:业务信息
81
- * action:操作的行为
82
- * successed:操作是否成功
83
- *
84
- */
85
- logUserAction(req,business,action,successed=0,memo=null){
86
- if (this.actionLogger && business && action) this.actionLogger.log(req,business,action,successed,memo)
87
- }
88
- /**
89
- * 创建基于CRUD的基础路由方式
90
- * @param {*} actionType
91
- * @param {*} req
92
- * @param {*} res
93
- */
94
- createCRUDRoute(actionType,url,datakey,middleware){
95
- let instance = this;
96
- instance.router[actionType.method](url, middleware ? middleware : (req, res, next)=>{return next()},async (req,res)=>{
97
- ////执行CRUD之前,可由继承的子类实现规则验证
98
- ////如果返回successed:false,则不再继续
99
- let beforeResult = await instance.beforeCRUD(actionType,req,res)
100
- if (!beforeResult.successed) return res.json(beforeResult);
101
- ////具体执行基类的CRUD方法
102
- let result;
103
- if (actionType.method==='delete')
104
- result = await instance.delete(req,req.params.id);
105
- else
106
- result = await instance[actionType.func](req, datakey);
107
- ////执行完CRUD方法之后的处理
108
- result = await instance.afterCRUD(result,actionType,datakey,url,req,res)
109
- return res.json(result)
110
- })
111
- }
112
- /**
113
- * 快速构造Controller中的CRUD各个路由,大部分基础表都可复用
114
- * @param {*} url ////基础地址,根据RESTFUL的风格生成CRUD风格的
115
- * CREATE : POST url
116
- * UPDATE : PUT url/{id}
117
- * LIST : GET url
118
- * DELETE : DELETE url/{id}
119
- * @param {*} datakey 对应在dataconfig.json中的key,方便实体和传递的数据的映射以及SQL
120
- * @param {*} action 操作的组合 CRUDS
121
- */
122
- initializeCRUDRouter(url, datakey, action = 'SCRUD', middleware){
123
- if(!url || !datakey) return;
124
- let urlWithId = url.endsWith('/')?`${url}:id`:`${url}/:id`;
125
- if (action.indexOf('C') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Create, url, datakey, middleware)
126
- if (action.indexOf('S') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Single, urlWithId, datakey, middleware)
127
- if (action.indexOf('R') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Retrieve, url, datakey, middleware)
128
- if (action.indexOf('U') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Update, urlWithId, datakey, middleware)
129
- if (action.indexOf('D') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Delete, urlWithId, datakey, middleware)
130
- }
131
- /**
132
- * CRUD真正进入数据库之前的处理,可由继承的类来处理
133
- * 不处理则默认返回继续
134
- * @param {*} result
135
- * @param {*} action
136
- */
137
- async beforeCRUD(_action, _req,_res){
138
- return {successed:true}
139
- }
140
- /**
141
- * CRUD执行数据库之后的处理,可由继承的类来处理
142
- * @param {*} result
143
- * @param {*} action
144
- */
145
- async afterCRUD(result,_action,_datakey,_url, _req,_res){
146
- return result;
147
- }
148
- /*
149
- * 初始化路由处理器(空方法,待继承的子类去实现)
150
- * 除了在routerConfig中配置的路由以外,继承的子类可以重写实现此方法来
151
- * 继续配置你的路由
152
- */
153
- initializeRouter(_instance) { }
154
- /*
155
- * 数据加载之前的动作
156
- * 子类可以重写该方法
157
- */
158
- async beforeAccessDB(_req, sql, sqlParams, _type, _instance) {
159
- return { sql: sql, sqlParams: sqlParams, canceled: false };
160
- }
161
- /**
162
- * 数据导出到Excel之前可以由继承类再进行处理
163
- * @param {*} dataOption
164
- */
165
- beforeExportExcel(dataOption) {
166
- return dataOption;
167
- }
168
- /**
169
- * 执行批量操作更新
170
- * @param {*} model 需要更新的字段和值
171
- */
172
- async batchUpdate(req,model,id){
173
- if (!id) id = req.params.id;
174
- if (!id) return {successed:false,errcode:-2,errmsg:'缺失批量操作的id'}
175
- let batchSql = parseTagInSql(req,this._daoModel.BatchSql());
176
- let result = await this._daoModel.batchUpdate(batchSql, model, id, req.user?.id)
177
- this.logUserAction(req,this._daoModel.getBusiness(),6,result.successed?0:-1);
178
- return result;
179
- }
180
- /*
181
- * 获取查询列表记录的方法
182
- */
183
- async getListData(req, dataKey, configFile = 0) {
184
- if (this.logger) this.logger.trace("准备获取dataconfig文件中对应的 %s list数据",dataKey)
185
- const listinfo = getListInfo(req, dataKey, configFile, this._daoModel); //, ignorefilter==1
186
- if (!listinfo) return { successed: false, errcode: -10, errmsg:`缺失${dataKey}对应的查询语句`};
187
-
188
- ////直接操作数据库之前,可由子类再次Handler
189
- let beforeData = await this.beforeAccessDB(req, listinfo.sql, listinfo.params, "list", this);
190
- ////如果返回Null,则表示不加载数据了
191
- if (beforeData.canceled === true) return { successed: false, errorcode: 1, errmsg: "操作取消" };
192
- ////操作数据库
193
- let result = await this._daoModel.loadData(beforeData.sql, beforeData.sqlParams);
194
- if(!result.successed) {
195
- ////失败也需要记录
196
- if (req.query.exportexcel==='true') this.logUserAction(req,this._daoModel.getBusiness(),5,-1);
197
- return result;
198
- }
199
- ///从数据库中获取到了原始数据
200
- if (result.rows) {
201
- ///将从数据库中获得的结果集根据dataconfig中的配置进行映射转换
202
- let resultItem = Data2View(result.rows[0], listinfo.fields)
203
- ///输出的结果是否需要装饰带有successed,total等,便于列表
204
- let outputData = { successed: true, page: listinfo.page, rows: resultItem.data };
205
- ///需要进行尾部统计的列表
206
- if (listinfo.hascounter) {
207
- let footerItem = Data2View(result.rows[2], listinfo.footers)
208
- outputData.footer = footerItem.data;
209
- }
210
- outputData.total = await this.getListRecordCount(result);
211
- ///处理导出Excel
212
- if (req.query.exportexcel==='true') {
213
- outputData= await this.export2Excel(outputData.rows,req.query.excelkey || dataKey)
214
- this.logUserAction(req,this._daoModel.getBusiness(),5,0);
215
- }
216
- return outputData;
217
- }
218
- return {successed:false, errcode: -1, total: 0, rows: [] };
219
- }
220
- /**
221
- * 返回数据结果的记录总数
222
- * @param {*} data
223
- */
224
- async getListRecordCount(result){
225
- return result.rows[1][0].total;
226
- }
227
- /*
228
- * 获取详细记录的方法
229
- */
230
- async getDataById(req, dataKey, sqlCommand,idValue) {
231
- if (this.logger) this.logger.trace("准备获取dataconfig文件中对应的 %s 详细数据",dataKey)
232
- const detailinfo = getDetailInfo(req, dataKey);
233
- if (!detailinfo) return { successed: false, errcode: -10, errmsg: `缺失${dataKey}对应的详情配置` };
234
- let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.getByIdSql(), idValue ||req.params.id, "detail", this);
235
- ////如果返回Null,则表示不加载数据了
236
- if (beforeData.canceled===true) return { successed: false, errorcode: 1, errormessage: "操作已取消" };
237
- /////处理SQL中的一些定义符
238
- let parseSql = parseTagInSql(req,beforeData.sql);
239
- ////操作数据库
240
- let result = await this._daoModel.getBykey(parseSql, beforeData.sqlParams);
241
- if (!result.successed) return result;
242
- if (result.rows && result.rows.length == 1) {
243
- ///如果对象有数据权限控制,则需要插入
244
- ///提交的权限设置
245
- ///将从数据库中获得的结果集根据dataconfig中的配置进行映射转换
246
- let resultMapping = Data2View(result.rows, detailinfo.fields);
247
- ///如果业务对象具备权限控制的业务,则需要将该数据的所赋予的权限对象加载出来
248
- if (this._daoModel.hasPermissionControl) {
249
- const accessResult = await this._daoModel.getDataPermissionSetting(req.params.id,this.PermissonBusiness(req))
250
- if (accessResult.successed) {
251
- resultMapping.data[0].managepermission = accessResult.managepermission;
252
- resultMapping.data[0].consumepermission = accessResult.consumepermission;
253
- }
254
- }
255
- return { successed: true, rows: resultMapping.data[0], id: req.params.id };
256
- }
257
- return apiResult.DB_NO_RECORD_FOUND;
258
- }
259
- /*
260
- * 新增实体记录的方法
261
- */
262
- async create(req, dataKey, sqlCommand) {
263
- if (this.logger) this.logger.trace("准备根据dataconfig文件中对应的 %s 配置插入数据",dataKey)
264
- let mapping = req.query.Mapping??true; //|| 'true'==='true' ;//commonHelper.ifNull(req.query.Mapping, true);
265
- let detailinfo, resultItem = { successed: true, data: req.body };
266
- ///是否需要将data中的key-value值到配置文件中进行转换
267
- if (mapping == true) {
268
- detailinfo = getDetailInfo(req, dataKey);
269
- if (!detailinfo) return { successed: false, errcode: -10, errmsg: `缺失${dataKey}对应的详情配置` };
270
- resultItem = View2Data(req, detailinfo.fields, "create");
271
- ///如果转换的验证过程中出现错误,则返回
272
- if (!resultItem.successed) return resultItem;
273
- }
274
- let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.insertSql(), resultItem.data, "create", this);
275
- ////如果返回Null,则表示不加载数据了
276
- if (beforeData.canceled) return { successed: false, errorcode: 1, errormessage: "操作取消" };
277
- if (this.logger) this.logger.trace("插入数据准备 : ",beforeData)
278
- let result = await this._daoModel.create(beforeData.sql, beforeData.sqlParams, req)
279
- if(!result.successed) {
280
- this.logUserAction(req,this._daoModel.getBusiness(),1,-1);
281
- return result;
282
- }
283
- let primaryKey;
284
- if (mapping && detailinfo.primary) {
285
- ///自动增长的主键字段
286
- if (detailinfo.autoincrease === true) primaryKey = result.rows.insertId;
287
- else {
288
- if (typeof (detailinfo.primary) === "string") primaryKey = beforeData.sqlParams[detailinfo.primary];
289
- if (typeof (detailinfo.primary) === "object")
290
- primaryKey = detailinfo.primary.map(element => { return beforeData.sqlParams[element]; });
291
- }
292
- }
293
- ///如果对象有数据权限控制,则需要插入
294
- ///提交的权限设置
295
- if (this._daoModel.hasPermissionControl){
296
- let param = {}
297
- if (req.body.managepermission)
298
- param.managepermission = JSON.parse(req.body.managepermission);
299
- else
300
- param.managepermission= {};
301
- if (req.body.consumepermission)
302
- param.consumepermission = JSON.parse(req.body.consumepermission);
303
- else
304
- param.consumepermission = {}
305
- this._daoModel.saveDataPermissionSetting(primaryKey, param)
306
- }
307
- this.logUserAction(req,this._daoModel.getBusiness(),1,0);
308
- return { successed: true, data: resultItem.data, id: primaryKey };
309
- }
310
- /*
311
- * 修改实体记录的方法
312
- */
313
- async update(req, dataKey, sqlCommand, id) {
314
- if (this.logger) this.logger.trace("准备根据dataconfig文件中对应的 %s 配置修改数据",dataKey)
315
- if (id == null) id = req.params.id;
316
- let mapping = req.query.Mapping??true;// commonHelper.ifNull(req.query.Mapping, true);
317
- let detailinfo, resultItem = { successed: true, data: req.body };
318
- ///是否需要将data中的key-value值到配置文件中进行转换
319
- if (mapping == true) {
320
- detailinfo = getDetailInfo(req, dataKey);
321
- if (!detailinfo) return { successed: false, errcode: -10, errmsg: `缺失${dataKey}对应的详情配置` };
322
- ///从Request中获取到用户提交的数据
323
- resultItem = View2Data(req, detailinfo.fields, "update");
324
- }
325
- ///如果不需要转换,则直接使用前端提交上来的值
326
- let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.updateSql(), resultItem.data, "update", this);
327
- ////如果返回Null,则表示不加载数据了
328
- if (beforeData.canceled) return { successed: false, errorcode: 1, errormessage: "操作取消" };
329
- if (this.logger) this.logger.trace("修改数据准备 : ",beforeData)
330
- /////处理SQL中的一些定义符
331
- let parseSql = parseTagInSql(req,beforeData.sql);
332
- let result = await this._daoModel.update(parseSql, beforeData.sqlParams, id);
333
- if(!result.successed) {
334
- this.logUserAction(req,this._daoModel.getBusiness(),3,-1);
335
- return result;
336
- }
337
- ///更新成功
338
- if (result.rows.affectedRows == 1) {
339
- ///如果对象有数据权限控制,则需要插入
340
- ///提交的权限设置
341
- if (this._daoModel.hasPermissionControl) {
342
- let param = {}
343
- if (req.body.managepermission)
344
- param.managepermission = JSON.parse(req.body.managepermission);
345
- else
346
- param.managepermission = {}
347
- if (req.body.consumepermission)
348
- param.consumepermission = JSON.parse(req.body.consumepermission);
349
- else
350
- param.consumepermission = {}
351
- this._daoModel.saveDataPermissionSetting(id, param)
352
- }
353
- this.logUserAction(req,this._daoModel.getBusiness(),3,0);
354
- return { successed: true, data: resultItem.data, id: id };
355
- }
356
- ///更新失败
357
- return apiResult.DB_NO_EFFECTIVE; //{successed:false,errorcode:errorcode.DATABASE_ERROR.NO_RECORD_EFFECTED,data:resultItem.data};
358
- }
359
-
360
- /*
361
- * 删除实体记录的方法
362
- */
363
- async delete(req, id, sqlCommand) {
364
- if (this.logger) this.logger.trace("准备删除数据",id)
365
- let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.deleteSql(id), id, "delete", this);
366
- ////如果返回Null,则表示不加载数据了
367
- if (beforeData.canceled) return { successed: false, errorcode: 1, errormessage: "操作取消" };
368
- /////处理SQL中的一些定义符
369
- let parseSql = parseTagInSql(req,beforeData.sql);
370
- ////操作数据库
371
- let result = await this._daoModel.delete(parseSql, beforeData.sqlParams,req.user?.id)
372
- if(!result.successed) {
373
- this.logUserAction(req,this._daoModel.getBusiness(),2,-1);
374
- return result;
375
- }
376
- this.logUserAction(req,this._daoModel.getBusiness(),2,0);
377
- return { successed: true, id: id, count: result.rows.affectedRows };
378
- }
379
- }
380
- exports = module.exports = controller;