You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
6.9 KiB
241 lines
6.9 KiB
8 months ago
|
'use strict';
|
||
|
const Service = require('egg').Service;
|
||
|
const _ = require("lodash")
|
||
|
const mongoose = require('mongoose');
|
||
|
const crc16 = require('crc/crc16');
|
||
|
// const dayjs = require('dayjs');
|
||
|
const ObjectId = mongoose.Types.ObjectId;
|
||
|
class UtilsService extends Service {
|
||
|
//基础表
|
||
|
baseModel() {
|
||
|
let WorkflowlaunchSchema = new mongoose.Schema({
|
||
|
create_at: {
|
||
|
type: Date,
|
||
|
default: Date.now,
|
||
|
index: true
|
||
|
},
|
||
|
update_at: {
|
||
|
type: Date,
|
||
|
default: Date.now,
|
||
|
index: true
|
||
|
},
|
||
|
title: {
|
||
|
type: String,
|
||
|
index: true
|
||
|
},
|
||
|
user: {
|
||
|
type: String,
|
||
|
ref: 'XbyUser',
|
||
|
index: true
|
||
|
},
|
||
|
delete: {
|
||
|
type: Number,
|
||
|
default: 0, //0代表未删除,1代表删除
|
||
|
index: true
|
||
|
},
|
||
|
}, {
|
||
|
strict: false
|
||
|
});
|
||
|
return WorkflowlaunchSchema;
|
||
|
}
|
||
|
//数据库查找表
|
||
|
async findModelByName(name) {
|
||
|
if (!this.ctx.model.hasOwnProperty(name)) {
|
||
|
let baseModel = this.baseModel();
|
||
|
let lowerFirstName = _.lowerFirst(name)
|
||
|
this.ctx.model[name] = mongoose.model(lowerFirstName, baseModel, lowerFirstName);
|
||
|
}
|
||
|
return this.ctx.model[name];
|
||
|
}
|
||
|
/**
|
||
|
* 通用数据获取接口
|
||
|
* @param modelObj
|
||
|
* @param filterOption 过滤条件、排序、分页条件
|
||
|
* {
|
||
|
"filters": {
|
||
|
"submission.name": {
|
||
|
"$regex": ".*66",
|
||
|
"$options": "i"
|
||
|
}
|
||
|
},
|
||
|
"sort": {
|
||
|
"create_at": -1
|
||
|
},
|
||
|
"skip": 0,
|
||
|
"limit": 20,
|
||
|
}
|
||
|
* @returns {Promise<*>}
|
||
|
*/
|
||
|
async getDataList(name, filterOption = {}) {
|
||
|
// let { ctx } = this;
|
||
|
//facet 查询结果的同时显示总数
|
||
|
let modelObj = await this.findModelByName(name)
|
||
|
let facet = {
|
||
|
$facet: {
|
||
|
total: [{
|
||
|
$count: "total"
|
||
|
}],
|
||
|
results: []
|
||
|
}
|
||
|
};
|
||
|
//sort 排序用
|
||
|
if (!_.isEmpty(filterOption.sort)) {
|
||
|
facet.$facet.results.push({
|
||
|
$sort: filterOption.sort
|
||
|
});
|
||
|
}
|
||
|
//skip 排序用
|
||
|
facet.$facet.results.push({
|
||
|
$skip: _.get(filterOption, ["skip"], 0) || 0
|
||
|
});
|
||
|
//limit 排序用
|
||
|
if (_.get(filterOption, ["limit"], 1)) {
|
||
|
facet.$facet.results.push({
|
||
|
$limit: filterOption.limit
|
||
|
});
|
||
|
}
|
||
|
let agg = [];
|
||
|
//转换字符串_id为objectid,目前只能转第一层和第二层的id,要改为迭代查找
|
||
|
for (let key in (_.get(filterOption, ["filters"], {}) || {})) {
|
||
|
if (key === '_id' && _.isString(filterOption.filters[key]) && ObjectId.isValid(filterOption.filters[key])) {
|
||
|
//值是一个 mongodb id字符串
|
||
|
filterOption.filters[key] = ObjectId(filterOption.filters[key]);
|
||
|
}
|
||
|
else if (key === 'create_at' || key === 'update_at') {
|
||
|
filterOption.filters[key]["$gte"] = new Date(filterOption.filters[key]["$gte"]);
|
||
|
filterOption.filters[key]["$lt"] = new Date(filterOption.filters[key]["$lt"]);
|
||
|
}
|
||
|
}
|
||
|
agg.push({
|
||
|
$match: { delete: 0, ...(_.get(filterOption, ["filters"], {}) || {}) }
|
||
|
});
|
||
|
if (filterOption.hasOwnProperty('project') && !_.isEmpty(filterOption.project)) {
|
||
|
facet.$facet.results.push({
|
||
|
$project: filterOption.project
|
||
|
});
|
||
|
}
|
||
|
//当results ===0 时, 只保留统计
|
||
|
let aggTotal = []
|
||
|
let aggResults = []
|
||
|
aggTotal = [...agg, ...facet["$facet"]["total"]]
|
||
|
aggResults = [...agg, ...facet["$facet"]["results"]]
|
||
|
// ctx.logger.debug(modelObj.modelName, JSON.stringify(aggResults));
|
||
|
let resultRecords = [];
|
||
|
//allowDiskUse:解决管道内数据量超过100M时报错问题
|
||
|
let resultTotal = await modelObj.collection.aggregate(aggTotal, { allowDiskUse: true }).toArray();
|
||
|
if (filterOption.results !== 0) {
|
||
|
resultRecords = await modelObj.collection.aggregate(aggResults, { allowDiskUse: true }).toArray();
|
||
|
}
|
||
|
let r = resultTotal[0] ? resultTotal[0] : { total: 0 }
|
||
|
r["results"] = resultRecords
|
||
|
return r;
|
||
|
}
|
||
|
//修改数据
|
||
|
async update(name, updateData, filter = {}) {
|
||
|
let modelObj = await this.findModelByName(name)
|
||
|
updateData['update_at'] = Date.now();
|
||
|
//转换子路径是因为更新子路径要用.点的形式,不能用字典形式
|
||
|
if ("submission" in updateData) {
|
||
|
_.forEach(updateData.submission, function (value, key) {
|
||
|
updateData["submission." + key] = value;
|
||
|
})
|
||
|
updateData = _.omit(updateData, "submission")
|
||
|
}
|
||
|
updateData = {
|
||
|
$set: updateData
|
||
|
};
|
||
|
filter = _.isEmpty(filter) ? { "_id": updateData["$set"]._id } : filter
|
||
|
delete updateData["$set"]['_id']
|
||
|
return await modelObj.findOneAndUpdate(
|
||
|
filter
|
||
|
, updateData, {
|
||
|
lean: true
|
||
|
}).exec();
|
||
|
|
||
|
}
|
||
|
//新增数据
|
||
|
async save(name, addOption) {
|
||
|
let modelObj = await this.findModelByName(name)
|
||
|
if (!_.isArray(addOption)) {
|
||
|
addOption = [addOption]
|
||
|
}
|
||
|
let saveData = await modelObj.create(addOption)
|
||
|
return saveData
|
||
|
}
|
||
|
//modbus生成crc校验
|
||
|
/**
|
||
|
* MODBUS-RTU CRC校验
|
||
|
* @param data 命令(不带crc16循环冗余码的命令)
|
||
|
* @returns {any[]} 十六进制高低位
|
||
|
* @constructor
|
||
|
*/
|
||
|
MODBUS_CRC(data, isAll = false, type = "string") {
|
||
|
let trimStr = _.replace(data, /[\s]/g, '')
|
||
|
let res = crc16(trimStr, 'hex')
|
||
|
let dataBuffer = Buffer.from(trimStr, "HEX")
|
||
|
let crcValue = 0xFFFF;
|
||
|
for (let i = 0; i < dataBuffer.length; i++) {
|
||
|
crcValue ^= dataBuffer[i]
|
||
|
for (let j = 0; j < 8; j++) {
|
||
|
if (crcValue & 0x0001) {
|
||
|
crcValue >>= 1
|
||
|
crcValue ^= 0xA001
|
||
|
} else {
|
||
|
crcValue >>= 1
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
crcValue = crcValue.toString(16)
|
||
|
crcValue = _.padStart(crcValue, 4, "0")
|
||
|
//处理进来的字符串
|
||
|
if (type === "string") {
|
||
|
let result = "";
|
||
|
for (let i = 0; i < trimStr.length; i++) {
|
||
|
result += trimStr[i];
|
||
|
if (i % 2 === 1) result += ' ';
|
||
|
}
|
||
|
|
||
|
|
||
|
let returnData = `${crcValue.substring(2, 4)} ${crcValue.substring(0, 2)}`
|
||
|
if (isAll) {
|
||
|
returnData = `${result}${crcValue.substring(2, 4)} ${crcValue.substring(0, 2)}`
|
||
|
}
|
||
|
return returnData
|
||
|
|
||
|
} else {
|
||
|
let result = [];
|
||
|
for (let i = 0; i < trimStr.length; i++) {
|
||
|
if (i % 2 === 1) {
|
||
|
let item = trimStr.substr(i - 1, 2)
|
||
|
result.push(parseInt(`0x${item}`, 16))
|
||
|
};
|
||
|
}
|
||
|
let returnDataArr = [parseInt(`0x${crcValue.substring(2, 4)}`, 16), parseInt(`0x${crcValue.substring(0, 2)}`, 16)]
|
||
|
result.push(returnDataArr[0])
|
||
|
result.push(returnDataArr[1])
|
||
|
if (isAll) {
|
||
|
return Buffer.from(result)
|
||
|
} else {
|
||
|
return Buffer.from(returnDataArr)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
sleep(time) {
|
||
|
return new Promise((resolve) => setTimeout(resolve, time));
|
||
|
}
|
||
|
async checkPerssion(model, filter) {
|
||
|
let { ctx } = this
|
||
|
try {
|
||
|
let res = await ctx.model[model].find(filter)
|
||
|
if (res && res.length) {
|
||
|
return true
|
||
|
} else {
|
||
|
return false
|
||
|
}
|
||
|
} catch (err) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = UtilsService;
|