基于Vue2和Node.js的反欺诈系统设计与实现 (11)

比如说我想编写一个请求响应时间的中间件,那么可以在app文件夹下新建middleware文件夹,然后新建cost.js文件

// app/middleware/cost.js module.exports = options => { const header = options.header || 'X-Response-Time'; return async function cost(ctx, next) { const now = Date.now(); await next(); ctx.set(header, `${Date.now() - now}ms`); }; };

在config/config.default.js文件中,我们注册它

// add your middleware config here config.middleware = ['cost', 'errorHandler'];

这样在请求响应的时候就会带上一个x-Response-Time

eggjs中的中间件:https://eggjs.org/zh-cn/basics/middleware.html

eggjs中的通用工具包

比如你想写一些通用的工具类, 那么可以这么去做,在app目录下新建utils文件夹,然后创建一个generator.js(这里以生成id举例), 代码如下:

const { v4: uuidv4 } = require('uuid'); function generateUUID() { return uuidv4().replace(/-/g, ''); } function getNo(num) { const numStr = `000${(num % 1000).toString()}`; return numStr.slice(-3); } module.exports = { generateUUID, getNo, };

然后再config/config.default.js中配置

config.customLoader = { utils: { directory: 'app/utils', inject: 'app', loadunit: true, }, };

它表示加载app/utils下面的文件,注入到application对象中。调用的时候就可以直接app.utils.generateUUID()

功能实现-文件上传与下载

egg内置了multipart插件,通过这个插件我们很容易实现文件上传

async upload() { const { ctx, service } = this; const file = ctx.request.files[0]; if (!file) return ctx.throw(404); // const filename = path.extname(file.filename).toLowerCase(); const { filename } = file; const type = path.extname(filename).toLowerCase(); const { username, nickname } = ctx.session.userinfo; const createBy = nickname || username; const uuid = ctx.app.utils.generator.generateUUID(); const targetPathPrefix = path.join(this.config.baseDir, 'app/public', uuid); const targetPath = path.join( this.config.baseDir, 'app/public', uuid, filename ); const source = fs.createReadStream(file.filepath); await mkdirp(targetPathPrefix); const target = fs.createWriteStream(targetPath); let result = ''; try { await pump(source, target); const stats = fs.statSync(targetPath); const size = ctx.app.utils.compute.bytesToSize(stats.size); const url = `public/${uuid}/${filename}`; result = await service.file.add(filename, type, size, url, createBy); ctx.logger.info('save %s to %s', file.filepath, targetPath, stats, size); } finally { // delete those request tmp files await ctx.cleanupRequestFiles(); } ctx.success(result); }

上面的代码就是在读取前端传过来的文件后,在app/public文件夹下创建文件,并将记录写到数据库中

在config/config.default.js中可以对文件进行相关配置,比如说模式是流还是文件,相关文件的大小,相关文件的格式等。

exports.multipart = { mode: 'file', fileSize: '100mb', whitelist: [ // images '.jpg', '.jpeg', // image/jpeg '.png', // image/png, image/x-png '.gif', // image/gif '.bmp', // image/bmp '.wbmp', // image/vnd.wap.wbmp '.webp', '.tif', '.psd', // text '.svg', '.js', '.jsx', '.json', '.css', '.less', '.html', '.htm', '.xml', '.xlsx', '.xls', '.doc', '.docx', '.ppt', '.pptx', '.pdf', // tar '.zip', '.rar', '.gz', '.tgz', '.gzip', // video '.mp3', '.mp4', '.avi', ], };

eggjs中的文件上传: https://eggjs.github.io/zh/guide/upload.html

egg-multipart: https://github.com/eggjs/egg-multipart

功能实现-数据统计

在Model层,需要对进行一定范围的查询,如下:

static async getTotal(start, end) { const where = { crimeTime: { [Op.between]: [start, end], }, }; try { const ret = await this.count({ where }); logger.info(this.getTotal, start, end, ret); return ret; } catch (e) { logger.error(e); return false; } }

可能细心的读者发现了,我这边存储数据用的是时间戳,一个月的时间戳是2592000。所以这边想要取一个月的数据就很简单了框定范围[start, start + 2592000]就好了。

以饼图的为例, service层代码如下:

async calculateCount(start, end) { const { Bank, Mobile, Virtual, Website } = this; const bankCount = await Bank.getTotal(start, end + 2592000); const mobileCount = await Mobile.getTotal(start, end + 2592000); const virtualCount = await Virtual.getTotal(start, end + 2592000); const websiteCount = await Website.getTotal(start, end + 2592000); return [ { name: '银行查控', count: bankCount || 0 }, { name: '电话查控', count: mobileCount || 0 }, { name: '虚拟账号查控', count: virtualCount || 0 }, { name: '网站查控', count: websiteCount || 0 }, ]; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzfxzj.html