明树Git Lab

Commit 27254597 authored by zengfanpei's avatar zengfanpei

code

parents
Pipeline #83310 failed with stages
node_modules/
.git
package-lock.json
.vscode
test/
public/avatar
\ No newline at end of file
# 文件结构
### config
### controller
### db
### middlerware
### modules
### public
### router
### test
### utils
### server.js
1. 现阶段进展:20240822
a. 建表用户表、设备表(多种设备集成)、三张信息采集表(按设备种类对应采集表)
b. 定时任务获取 墒情设备列表、获取设备信息入库代码流程基本走通
c. 用户、角色、菜单权限(要看前端控制程度, 是否包含父子结构)
2. 未处理
a. 设备在线状态 接口获取到状态直接更新倒redis里面
b. 硬件返回信息 返回形式 有待细化
{
"tokenEx": 86400,
"dbURI": "mongodb://bridata:Mingshu20170706@47.94.146.184:27017/letian?authSource=admin",
"file": {
"storagePath": "public/avatar"
},
"device": {
"secretKey": "EB29BBD58E06997E",
"getDeviceList": "http://open.sennor.net:8088/device/getDeviceList",
"getDeviceInfo": "http://open.sennor.net:8088/device/getDeviceInfo",
"upDeviceInfo": "http://open.sennor.net:8088/device/upDeviceInfo",
"fileBaseUrl": "http://insect.sennor.net:1881/openFile/",
"token": "24a2232a85bd4ce7a846c460ff3b34c2",
"userName": "cqwangfeng1",
"password": "b5be656a7060dd3525027d6763c33ca0",
"getAllDevice": "http://open.sennor.net:1881/getAllDevice",
"getInsectNewCollectionResult": "http://open.sennor.net:1881/getInsectNewCollectionResult",
"uploadCameraPhoto": "http://open.sennor.net:1881/uploadCameraPhoto",
"getPreventionToInsectName": "http://open.sennor.net:1881/getPreventionToInsectName"
},
"cron": {
"getDeviceList": false,
"getAllDevice": false,
"collectDeviceInfo": false
}
}
\ No newline at end of file
const config = require(`./${process.env.NODE_ENV}.json`);
global.sysConfig = config;
\ No newline at end of file
{
"tokenEx": 86400,
"dbURI": "",
"file": {
"storagePath": "public/avatar"
},
"device": {
"secretKey": "EB29BBD58E06997E",
"getDeviceList": "http://open.sennor.net:8088/device/getDeviceList",
"getDeviceInfo": "http://open.sennor.net:8088/device/getDeviceInfo",
"upDeviceInfo": "http://open.sennor.net:8088/device/upDeviceInfo",
"fileBaseUrl": "http://insect.sennor.net:1881/openFile/",
"token": "24a2232a85bd4ce7a846c460ff3b34c2",
"userName": "cqwangfeng1",
"password": "b5be656a7060dd3525027d6763c33ca0",
"getAllDevice": "http://open.sennor.net:1881/getAllDevice",
"getInsectNewCollectionResult": "http://open.sennor.net:1881/getInsectNewCollectionResult",
"uploadCameraPhoto": "http://open.sennor.net:1881/uploadCameraPhoto",
"getPreventionToInsectName": "http://open.sennor.net:1881/getPreventionToInsectName"
},
"cron": {
"getDeviceList": false,
"getAllDevice": false,
"collectDeviceInfo": false
}
}
\ No newline at end of file
{
"tokenEx": 86400,
"cron": {
}
}
\ No newline at end of file
async function list(req, res, next) {
try {
//
} catch (error) {
next(error)
}
}
module.exports = {
list
}
\ No newline at end of file
const _ = require('lodash');
const collectIPSModule = require('../module/collectIPSModule');
/**
* 虫情 翻页查询
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function list(req, res, next) {
try {
let search = {del: 0};
if(req.body.name) {
search.name = {$regex: req.body.name}
}
if(req.body.startTime) {
search.time = search.time || {};
search.time.$gte = req.body.startTime;
}
if(req.body.endTime) {
search.time = search.time || {};
search.time.$lte = req.body.endTime
}
if(_.isArray(req.body.time) && req.body.time.length == 2) {
search.time = {
$lte: req.body.time[1],
$gte: req.body.time[0]
}
}
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
let count = await collectIPSModule.count(search);
let data = await collectIPSModule.findList(search, {skip, limit: pageSize});
res.sendData({list: data, count});
} catch (error) {
next(error);
}
}
/**
* 虫情 查询一个信息
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function queryInfo(req, res, next) {
try {
let _id = req.body._id;
let data = await collectIPSModule.findOne({_id});
return res.sendData(data);
} catch (error) {
next(error);
}
}
/**
*
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function updateInfo(req, res, next) {
try {
let _id = req.body._id;
let updateObj = {
}
let ret = await collectIPSModule.updateOne({_id}, updateObj);
} catch (error) {
next(error);
}
}
/**
* 删除
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function delInfo(req, res, next) {
try {
let _id = req.body._id;
let ret = await collectIPSModule.updateOne({_id}, {del: 1});
return res.sendData(ret)
} catch (error) {
next(error);
}
}
async function test(req, res, next) {
try {
} catch (error) {
next(error);
}
}
module.exports = {
list,
queryInfo,
updateInfo,
delInfo,
}
\ No newline at end of file
const _ = require('lodash');
const collectSMCModule = require('../module/collectSMCModule');
/**
* 土壤 翻页查询
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function list(req, res, next) {
try {
let search = { del: 0 };
if (req.body.name) {
search.name = { $regex: req.body.name }
}
if (req.body.startTime) {
search.time = search.time || {};
search.time.$gte = req.body.startTime;
}
if (req.body.endTime) {
search.time = search.time || {};
search.time.$lte = req.body.endTime
}
if (_.isArray(req.body.time) && req.body.time.length == 2) {
search.time = {
$lte: req.body.time[1],
$gte: req.body.time[0]
}
}
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
let count = await collectSMCModule.count(search);
let data = await collectSMCModule.findList(search, { skip, limit: pageSize });
res.sendData({ list: data, count });
} catch (error) {
next(error);
}
}
/**
* 土壤 查询一个信息
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function queryInfo(req, res, next) {
try {
let _id = req.body._id;
let data = await collectSMCModule.findOne({ _id });
return res.sendData(data);
} catch (error) {
next(error);
}
}
/**
*
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function updateInfo(req, res, next) {
try {
let _id = req.body._id;
let updateObj = {
...req.body,
}
let ret = await collectSMCModule.updateOne({ _id }, updateObj);
} catch (error) {
next(error);
}
}
/**
* 删除
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function delInfo(req, res, next) {
try {
let _id = req.body._id;
let ret = await collectSMCModule.updateOne({ _id }, { del: 1 });
return res.sendData(ret)
} catch (error) {
next(error);
}
}
async function test(req, res, next) {
try {
} catch (error) {
next(error);
}
}
module.exports = {
list,
queryInfo,
updateInfo,
delInfo,
}
\ No newline at end of file
const _ = require('lodash');
const collectWSModule = require('../module/collectWSModule');
/**
* 虫情 翻页查询
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function list(req, res, next) {
try {
let search = {del: 0};
if(req.body.name) {
search.name = {$regex: req.body.name}
}
if(req.body.startTime) {
search.time = search.time || {};
search.time.$gte = req.body.startTime;
}
if(req.body.endTime) {
search.time = search.time || {};
search.time.$lte = req.body.endTime
}
if(_.isArray(req.body.time) && req.body.time.length == 2) {
search.time = {
$lte: req.body.time[1],
$gte: req.body.time[0]
}
}
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
let count = await collectWSModule.count(search);
let data = await collectWSModule.findList(search, {skip, limit: pageSize});
res.sendData({list: data, count});
} catch (error) {
next(error);
}
}
/**
* 虫情 查询一个信息
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function queryInfo(req, res, next) {
try {
let _id = req.body._id;
let data = await collectWSModule.findOne({_id});
return res.sendData(data);
} catch (error) {
next(error);
}
}
/**
*
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function updateInfo(req, res, next) {
try {
let _id = req.body._id;
let updateObj = {
}
let ret = await collectWSModule.updateOne({_id}, updateObj);
} catch (error) {
next(error);
}
}
/**
* 删除
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function delInfo(req, res, next) {
try {
let _id = req.body._id;
let ret = await collectWSModule.updateOne({_id}, {del: 1});
return res.sendData(ret)
} catch (error) {
next(error);
}
}
async function test(req, res, next) {
try {
} catch (error) {
next(error);
}
}
module.exports = {
list,
queryInfo,
updateInfo,
delInfo,
}
\ No newline at end of file
const departModule = require('../module/departModule');
const errorMessage = require('../utils/errorMessage');
const _ = require('lodash');
/**
* 添加部门
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function createDepart(req, res, next) {
try {
let newDep = {
name: req.body.name,
}
// 处理父级数据
let parentIds = [];
if (req.body.parentId) {
let parentDepart = await departModule.findOne({ _id: req.body.parentId });
if (!(parentDepart && parentDepart._id)) {
res.sendError(errorMessage.resourceNotFound);
}
parentIds = parentDepart.parentIds || [];
parentIds.push(parentDepart._id);
newDep.parentId = req.body.parentId;
newDep.parentIds = parentIds;
}
let ret = await departModule.create(newDep);
res.sendData(ret);
} catch (error) {
next(error);
}
}
/**
* 查询单个部门详情
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function getDepartInfo(req, res, next) {
try {
let dep = await departModule.findOne({ _id: req.body._id });
res.sendData(dep);
} catch (error) {
next(error);
}
}
async function updateDepart(req, res, next) {
try {
let updateObj = {
...req.body,
_id: undefined,
}
// 处理父级数据
let parentIds = [];
if (req.body.parentId) {
let parentDepart = await departModule.findOne({ _id: req.body.parentId });
if (!(parentDepart && parentDepart._id)) {
res.sendError(errorMessage.resourceNotFound);
}
parentIds = parentDepart.parentIds || [];
parentIds.push(parentDepart._id);
updateObj.parentId = req.body.parentId;
updateObj.parentIds = parentIds;
}
let ret = await departModule.findOneAndUpdate({ _id: req.body._id }, updateObj);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function list(req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
search.name = { $regex: req.body.name };
}
const count = await departModule.count(search);
const list = await departModule.findList(search, { skip, limit: pageSize });
return res.sendData({ list, count });
} catch (error) {
next(error);
}
}
async function tree(req, res, next) {
try {
let search = { del: 0 };
if (req.body.name) {
search.name = { $regex: req.body.name };
}
const deps = await departModule.findAll(search);
// 处理树结构, 先将deps里面的parentIds取出来
let nodes = [], nodeMap = {};
for (let i = 0; i < deps.length; i++) {
const dep = deps[i];
dep.parentIds = dep.parentIds || [];
let ids = [];
for (let ii = 0; ii < dep.parentIds.length; ii++) {
const pre = dep.parentIds[ii];
ids.push(pre._id);
if (!nodeMap[pre._id]) {
nodes.push(pre);
nodeMap[pre._id] = 1;
}
}
dep.parentIds = ids;
if (!nodeMap[dep._id]) {
nodes.push(dep);
nodeMap[dep._id] = 1;
}
}
const tree = utils.buildTree(nodes);
res.sendData(tree);
} catch (error) {
next(error);
}
}
async function test(req, res, next) {
try {
} catch (error) {
next(error);
}
}
module.exports = {
createDepart,
getDepartInfo,
updateDepart,
list,
tree,
}
\ No newline at end of file
const errorMessage = require('../utils/errorMessage');
const deviceModule = require('../module/deviceModule')
const _ = require('lodash');
async function list(req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
search.name = { $regex: req.body.name };
}
const count = await DB.Device.countDocuments(search);
let list = await DB.Device.find(search).skip(skip).limit(pageSize).select('deviceNumber creatTime deviceHQState deviceHQType name').populate({path: "land"}).lean().exec();
let deviceNumbers = [];
//处理在线状态
let onlineArr = await deviceModule.getDeviceOnlineMap();
list = list.map(o => {o.online = onlineArr.includes(o.deviceNumber); deviceNumbers.push(o.deviceNumber); return o});
//处理阈值
let ths = await DB.CollectThreshold.find({del: 0, enable: true, deviceNumber: {$in: deviceNumbers}});
let thsMap = {};
ths.map(o => {thsMap[o.deviceNumber] = thsMap[o.deviceNumber] || []; thsMap[o.deviceNumber].push(o); return;});
list = list.map(o => {o.thresholds = thsMap[o.deviceNumber] || []; console.log(o); return o;});
return res.sendData({ list, count });
} catch (error) {
next(error);
}
}
async function updateDevice(req, res, next) {
try {
let updateObj = {...req.body,_id: undefined};
let search = {_id: req.body._id};
if(req.body.deviceNumber) {
search.deviceNumber = req.body.deviceNumber;
}
let ret = await DB.Device.findOneAndUpdate(search, updateObj);
// // 2. 处理阈值入库
if(_.isArray(req.body.thresholds) && ret.deviceNumber) {
let attrMap = {}
let attrs = await DB.CollectAttribute.find({del: 0, enable: true});
attrs.map(o => {attrMap[o._id] = o; return});
for (let i = 0; i < req.body.thresholds.length; i++) {
const element = req.body.thresholds[i];
let {dbKey, deviceKey, name} = attrMap[element.attrId];
await DB.CollectThreshold.findOneAndUpdate({deviceNumber: ret.deviceNumber, dbKey}, {
max: element.max,
min: element.min,
attrId: element.attrId,
dbKey,
deviceKey,
name,
}, {upsert: true});
}
}
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function getDevice(req, res, next) {
try {
let search = {_id: req.body._id};
if(req.body.deviceNumber) {
search.deviceNumber = req.body.deviceNumber;
}
let device = await DB.Device.findOne(search).populate({path: "land"}).lean().exec();
//处理在线状态
let onlineArr = await deviceModule.getDeviceOnlineMap();
device.online = !!onlineArr.includes(device.deviceNumber);
//处理阈值
let ths = await DB.CollectThreshold.find({del: 0, enable: true, deviceNumber: device.deviceNumber});
device.thresholds = ths;
res.sendData(device)
} catch (error) {
next(error);
}
}
async function test(req, res, next) {
try {
} catch (error) {
next(error);
}
}
/* -----------------------阈值--------------------------- */
// 获取硬件所有可以设置的属性
async function listAttribute(req, res, next) {
try {
let list = await DB.CollectAttribute.find({del:0, enable: true});
res.sendData(list);
} catch (error) {
next(error);
}
}
//设置阈值
async function setThreshold(req, res, next) {
try {
let devices = req.body.devices || [];
// 1. 处理thresholds
let attrMap = {}
let attrs = await DB.CollectAttribute.find({del: 0, enable: true});
attrs.map(o => {attrMap[o._id] = o; return});
// 2. 处理阈值入库
for (let index = 0; index < devices.length; index++) {
const dev = devices[index];
let deviceNumber = dev && dev.deviceNumber || dev;
let thresholds = req.body.thresholds || [];
for (let i = 0; i < thresholds.length; i++) {
const element = thresholds[i];
let {dbKey, deviceKey, name} = attrMap[element.attrId];
await DB.CollectThreshold.findOneAndUpdate({deviceNumber, dbKey}, {
max: element.max,
min: element.min,
attrId: element.attrId,
dbKey,
deviceKey,
name,
}, {upsert: true});
}
}
res.sendData({});
} catch (error) {
next(error);
}
}
async function listThreshold(req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
search.name = { $regex: req.body.name };
}
const count = await DB.Device.countDocuments(search);
let list = await DB.Device.find(search).skip(skip).limit(pageSize).select('deviceNumber name').lean().exec();
//处理阈值
let deviceNumbers = [];
list.map(o => {deviceNumbers.push(o.deviceNumber); return;});
let ths = await DB.CollectThreshold.find({del: 0, enable: true, deviceNumber: {$in: deviceNumbers}});
let thsMap = {};
ths.map(o => {thsMap[o.deviceNumber] = thsMap[o.deviceNumber] || []; thsMap[o.deviceNumber].push(o); return;});
list = list.map(o => {o.thresholds = thsMap[o.deviceNumber] || []; console.log(o); return o;});
return res.sendData({ list, count });
} catch (error) {
next(error);
}
}
module.exports = {
list,
updateDevice,
getDevice,
listAttribute,
setThreshold,
listThreshold,
}
\ No newline at end of file
async function upload(req, res, next) {
try {
console.log(req.file, req.body);
await DB.File.create({
originalname: req.file.originalname,
mimetype: req.file.mimetype,
filename: req.file.filename,
path: req.file.path,
size: req.file.size,
url: '有待处理',
});
res.sendData(req.file);
} catch (error) {
next(error);
}
}
module.exports = {
upload
}
\ No newline at end of file
const moment = require('moment');
const mongoose = require('mongoose');
async function init(req, res) {
// 1. 初始化数据采集属性
let attrs = [
{ deviceKey: "温度", dbKey: "soilTemperature", name: "土壤温度" },
{ deviceKey: "湿度", dbKey: "soilMoisture", name: "土壤湿度" },
{ deviceKey: "氮", dbKey: "nitrogen", name: "氮" },
{ deviceKey: "磷", dbKey: "phosphorus", name: "磷" },
{ deviceKey: "钾", dbKey: "potassium", name: "钾" },
{ deviceKey: "PH", dbKey: "soilPH", name: "土壤PH值" },
{ deviceKey: "电导率", dbKey: "soilConductivity", name: "土壤电导率" },
{ deviceKey: "风速", dbKey: "windSpeed", name: "风速" },
{ deviceKey: "风向", dbKey: "windDirection", name: "风向" },
{ deviceKey: "雨量", dbKey: "rainfall", name: "雨量" },
{ deviceKey: "信号强度", dbKey: "signalSterngth", name: "信号强度" },
{ deviceKey: "错误码", dbKey: "errorCode", name: "错误码" },
{ deviceKey: "版本号", dbKey: "version", name: "版本号" },
]
for (let index = 0; index < attrs.length; index++) {
const element = attrs[index];
await DB.CollectAttribute.findOneAndUpdate({ dbKey: element.dbKey }, element, { upsert: true });
}
// 土壤
for (let index = 0; index < 20; index++) {
await DB.CollectSMC.findOneAndUpdate({ time: moment('2024-08-26').add(index, 'day') }, {
id: 8746,
name: "设备名称修改测试",
deviceNumber: "16A67205BA3A",
time: moment('2024-08-26').add(index, 'day'),
soilTemperature: 11 + Math.floor(Math.random() * 20),
soilMoisture: 11 + Math.floor(Math.random() * 20),
nitrogen: 11 + Math.floor(Math.random() * 20),
phosphorus: 11 + Math.floor(Math.random() * 20),
potassium: 11 + Math.floor(Math.random() * 20),
soilPH: 11 + Math.floor(Math.random() * 20),
soilConductivity: 11 + Math.floor(Math.random() * 20),
}, { upsert: true })
}
//气象
for (let index = 0; index < 20; index++) {
await DB.CollectWS.findOneAndUpdate({ time: moment('2024-08-26').add(index, 'day') }, {
id: 8746,
name: "气象站",
deviceNumber: "1111111111111",
time: moment('2024-08-26').add(index, 'day'),
windSpeed: 11 + Math.floor(Math.random() * 20),
windDirection: 11 + Math.floor(Math.random() * 20),
rainfall: 11 + Math.floor(Math.random() * 20),
}, { upsert: true })
}
// 虫情
for (let index = 0; index < 20; index++) {
let dataId = new mongoose.Types.ObjectId()
let data = await DB.CollectIPS.create({
_id: dataId,
id: 8746,
name: "虫情系统",
deviceNumber: "FF35d4072d53",
time: moment('2024-08-26').add(index, 'day'),
downloadUrl: "pictures/FF35D4072D53/2024-08-20-15-03-43.jpg",
newTime: moment('2024-08-26').add(index, 'day'),
newCount: 11 + Math.floor(Math.random() * 20)
});
let typeId = new mongoose.Types.ObjectId()
let type = await DB.CollectIPSType.create({ _id: typeId, name: "虫子" + index });
let planId = new mongoose.Types.ObjectId()
let plan = await DB.CollectIPSPlan.create({ _id: planId, name: "虫子" + index, controlPlan: "防治建议" + index });
await DB.CollectIPSResult.findOneAndUpdate({ data: dataId }, {
deviceNumber: "FF35d4072d53",
name: "虫子" + index,
count: 1 + Math.floor(Math.random() * 10),
time: moment('2024-08-26').add(index, 'day'),
type: typeId,
plan: planId,
data: dataId,
}, { upsert: true });
}
res.sendData({})
}
module.exports = {
init
}
\ No newline at end of file
async function create (req, res, next) {
try {
let ret = await DB.Land.create(req.body);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function update (req, res, next) {
try {
let ret = await DB.Land.findOneAndUpdate({_id: req.body._id}, req.body);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteLand (req, res, next) {
try {
let ret = await DB.Land.findOneAndUpdate({_id: req.body._id}, {del: 1});
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function list (req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
search.name = { $regex: req.body.name };
}
const count = await DB.Land.countDocuments(search);
const list = await DB.Land.find(search).skip(skip).limit(pageSize);
return res.sendData({ list, count });
} catch (error) {
next(error);
}
}
module.exports = {
create,
update,
deleteLand,
list,
}
async function createMenu(req, res, next) {
try {
let newData = {
...req.body
}
// 处理父级数据
let parentIds = [];
if (req.body.parentId) {
let parentDepart = await DB.Menu.findOne({ _id: req.body.parentId });
if (!(parentDepart && parentDepart._id)) {
res.sendError(errorMessage.resourceNotFound);
}
parentIds = parentDepart.parentIds || [];
parentIds.push(parentDepart._id);
newData.parentId = req.body.parentId;
newData.parentIds = parentIds;
}
let ret = await DB.Menu.create(newData);
res.sendData(ret);
} catch (error) {
next(error)
}
}
async function updateMenu(req, res, next) {
try {
let updateObj = {
...req.body,
_id: undefined,
createdAt: undefined,
updatedAt: undefined,
}
// 处理父级数据
let parentIds = [];
if (req.body.parentId) {
let parentDepart = await DB.Menu.findOne({ _id: req.body.parentId });
if (!(parentDepart && parentDepart._id)) {
res.sendError(errorMessage.resourceNotFound);
}
parentIds = parentDepart.parentIds || [];
parentIds.push(parentDepart._id);
updateObj.parentId = req.body.parentId;
updateObj.parentIds = parentIds;
}
let ret = await DB.Menu.findOneAndUpdate({ _id: req.body._id }, updateObj);
res.sendData(ret);
} catch (error) {
next(error)
}
}
async function listMenu(req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
search.name = { $regex: req.body.name };
}
let count = await DB.Menu.countDocuments(search);
let list = await DB.Menu.find(search).skip(skip).limit(pageSize);
res.sendData({ count, list });
} catch (error) {
next(error)
}
}
async function treeMenu(req, res, next) {
try {
let nodes = await DB.Menu.find({del: 0}).lean().exec();
let buttons = await DB.Button.find({del: 0}).select('name key menuId').lean().exec();
let buttonMap = {};
for (let index = 0; index < buttons.length; index++) {
const element = buttons[index];
buttonMap[element.menuId] = buttonMap[element.menuId] || [];
buttonMap[element.menuId].push(element);
}
nodes = nodes.map(o => {o.buttons = buttonMap[o._id]; return o})
const tree = utils.buildTree(nodes);
res.sendData(tree);
} catch (error) {
next(error)
}
}
/**----------------------按钮---------------------------- */
async function createButton(req, res, next) {
try {
let ret = await DB.Button.create(req.body);
res.sendData(ret);
} catch (error) {
next(error)
}
}
async function updateButton(req, res, next) {
try {
let updateObj = {
...req.body,
_id: undefined,
createdAt: undefined,
updatedAt: undefined,
}
let ret = await DB.Button.findOneAndUpdate({ _id: req.body._id }, updateObj);
res.sendData(ret);
} catch (error) {
next(error)
}
}
module.exports = {
createMenu,
listMenu,
updateMenu,
treeMenu,
createButton,
updateButton,
}
\ No newline at end of file
const moment = require('moment');
/**
* 获取墒情 时间段内变化趋势
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function getSMCChangeTrend(req, res, next) {
try {
let search = {
};
if((req.body.startTime && req.body.endTime)) {
search.time = {$gte: new Date(req.body.startTime), $lte: new Date(req.body.endTime)}
}
let aggr = [
{
$match: {
...search
}
},
{
$group: {
_id: { $dateToString: { format: "%Y-%m-%d", date: "$time" } }, // 将时间戳转换为日期字符串
soilTemperature: { $avg: "$soilTemperature" },
soilMoisture: { $avg: "$soilMoisture" },
nitrogen: { $avg: "$nitrogen" },
phosphorus: { $avg: "$phosphorus" },
potassium: { $avg: "$potassium" },
soilPH: { $avg: "$soilPH" },
}
}
];
let ret = await DB.CollectSMC.aggregate(aggr);
res.sendData(ret);
} catch (error) {
next(error);
}
}
/**
* 获取气象某个时间段变化趋势
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function getWSChangeTrend(req, res, next) {
try {
let search = {
};
if((req.body.startTime && req.body.endTime)) {
search.time = {$gte: new Date(req.body.startTime), $lte: new Date(req.body.endTime)}
}
let aggr = [
{
$match: {
...search
}
},
{
$group: {
_id: { $dateToString: { format: "%Y-%m-%d", date: "$time" } }, // 将时间戳转换为日期字符串
windSpeed: { $avg: "$windSpeed" },
windDirection: { $avg: "$windDirection" },
rainfall: { $avg: "$rainfall" },
}
}
];
let ret = await DB.CollectWS.aggregate(aggr);
res.sendData(ret);
} catch (error) {
next(error);
}
}
/**
* 获取虫情某个时间段的虫子数量和种类数量
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function getIPSChangeTrend(req, res, next) {
try {
let search = {
};
if((req.body.startTime && req.body.endTime)) {
search.time = {$gte: new Date(req.body.startTime), $lte: new Date(req.body.endTime)}
}
let aggr = [
{
$match: {
...search
}
},
{
$project: {
fTime: {$dateToString: { format: "%Y-%m-%d", date: "$time" }},
name: 1,
count: 1
}
},
{
$group: {
_id: {time: "$fTime", name: "$name"}, // 将时间戳转换为日期字符串
count: { $sum: "$count" }, // 累计每日虫子总数量
// typeCount: { $sum: 1 }, // 有几条 就是有几种虫子
}
},
{
$project: {
time: '$_id.time',
name: '$_id.name',
count: 1,
_id: -1,
}
},
{
$group: {
_id: '$time',
count: {$sum: '$count'},
typeCount: {$sum: 1}
}
}
];
let ret = await DB.CollectIPSResult.aggregate(aggr);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function getDeviceCount(req, res, next) {
try {
} catch (error) {
next(error)
}
}
module.exports = {
getSMCChangeTrend,
getWSChangeTrend,
getIPSChangeTrend,
getDeviceCount,
}
\ No newline at end of file
const crypto = require('crypto');
const _ = require('lodash');
const userModule = require('../module/userModule');
const errorMessage = require('../utils/errorMessage');
// 注册 暂时用作注册admin 后续用户应该以后台添加方式进行
async function regist(req, res, next) {
try {
//暂时不做前后交互加密
const { salt, passwordHash } = utils.saltHashPassword(req.body.password);
const ret = await userModule.create({
...req.body,
salt,
password: passwordHash,
});
res.sendData(ret);
} catch (error) {
next(error);
}
}
// 登录
async function login(req, res, next) {
try {
const { mobile, password } = req.body;
const user = await userModule.findUserByMobile(mobile);
if (!user) {
res.sendError(errorMessage.loginError);
}
const check = utils.checkUserPassword({
reqPw: password,
salt: user.salt,
userPw: user.password,
});
if (!check) {
res.sendError(errorMessage.loginError)
}
// 生成一个串 返回前端
let token = crypto.randomUUID();
user.token = token;
let userStr = JSON.stringify(user);
await ioRedis.set(`token:${token}`, userStr, 'EX', sysConfig.tokenEx);
let ret = _.omit(user, ['password', 'salt']);
let menus = await userModule.getRoleMenus(ret.roles);
ret.menus = menus;
res.sendData(ret);
} catch (error) {
next(error);
}
}
/**
* 后台管理 翻页查询用户
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function listUser(req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
// search.name = { $regex: req.body.name };
search.$or = [
{ name: { $regex: req.body.name } },
{ mobile: { $regex: req.body.name } }
]
}
if (req.body.departId) {
search.depart = req.body.departId;
}
let ret = await userModule.findList(search, ['-password', '-salt'], { skip, limit: pageSize });
res.sendData(ret);
} catch (error) {
next(error);
}
}
/**
* 后台 添加用户
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function addUser(req, res, next) {
try {
const { salt, passwordHash } = utils.saltHashPassword(req.body.password);
const ret = await userModule.create({
...req.body,
salt,
password: passwordHash
});
res.sendData(ret);
} catch (error) {
next(error);
}
}
/**
* 更新用户 不能更新密码
* @param {*} req
* @param {*} res
* @param {*} next
*/
async function updateUser(req, res, next) {
try {
let updateObj = {
...req.body,
_id: undefined
}
const ret = await userModule.findOneAndUpdate({ _id: req.body._id }, updateObj);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function getUser(req, res, next) {
try {
const ret = await userModule.findOne({ _id: req.body._id }, ['-password', '-salt']);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteUser(req, res, next) {
try {
const ret = await DB.User.findOneAndUpdate({ _id: req.body._id }, { del: 1 });
res.sendData(ret)
} catch (error) {
next(error)
}
}
/* ------------Role--------------- */
async function getRole(req, res, next) {
try {
let ret = await DB.Role.findOne({ _id: req.body._id }).lean().exec();
if (!(ret && ret._id)) {
res.sendError(errorMessage.resourceNotFound);
}
/**
* 将role拥有的menus、buttons标记(permission)到菜单树结构中 返回给前端
*/
// 1. 处理当前角色自己的menus、buttons并建立map
let roleMenuMap = {}, roleButMap = {};
ret.menus = ret.menus || [];
ret.bottons = ret.bottons || [];
ret.menus.map(o => {roleMenuMap[o] = true});
ret.bottons.map(o => {roleButMap[o] = true});
// 2. 拿到所有的菜单\按钮
let allMenus = await DB.Menu.find({del: 0}).lean().exec();
let allButtons = await DB.Button.find({del: 0}).lean().exec();
let allButMap = {};
for (let i = 0; i < allButtons.length; i++) {
const element = allButtons[i];
element.permission = !!roleButMap[element._id];
allButMap[element.menuId] = allButMap[element.menuId] || [];
allButMap[element.menuId].push(element);
}
let menNodes = [];
for (let i = 0; i < allMenus.length; i++) {
const element = allMenus[i];
element.permission = !!roleMenuMap[element._id];
element.buttons = allButMap[element._id];
menNodes.push(element);
}
let tree = utils.buildTree(menNodes);
ret.menus = tree;
delete ret.buttons;
res.sendData(ret);
} catch (error) {
next(error)
}
}
async function listRole(req, res, next) {
try {
let search = { del: 0 };
let page = req.body.page || 1;
let pageSize = req.body.pageSize || 10;
let skip = (page - 1) * pageSize;
if (req.body.name) {
search.name = { $regex: req.body.name };
}
const count = await DB.Role.countDocuments(search);
const list = await DB.Role.find(search).skip(skip).limit(limit);
res.sendData({ list, count });
} catch (error) {
next(error);
}
}
async function createRole(req, res, next) {
try {
let obj = {
...req.body,
menus: [],
buttons: []
}
// 1. 创建角色时同步设置角色权限, 这里让前端直接将有选中状态的菜单tree传递到后端
let menus = req.body.menus || [];
let menusNodes = utils.disTree(menus);
//选中状态 permission: true 将menus buttons平行存入role中.
for (let i = 0; i < menusNodes.length; i++) {
const element = menusNodes[i];
if (element.permission) {
obj.menus.push(element._id);
}
element.buttons = element.buttons || [];
for (let i = 0; i < element.buttons.length; i++) {
const but = element.buttons[i];
if (but.permission) {
obj.buttons.push(but._id);
}
}
}
let ret = await DB.Role.create(obj);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function updateRole(req, res, next) {
try {
let obj = {
...req.body,
_id: undefined,
menus: [],
buttons: []
};
let menus = req.body.menus || [];
let menusNodes = utils.disTree(menus);
//选中状态 permission: true 将menus buttons平行存入role中.
for (let i = 0; i < menusNodes.length; i++) {
const element = menusNodes[i];
if (element.permission) {
obj.menus.push(element._id);
}
element.buttons = element.buttons || [];
for (let i = 0; i < element.buttons.length; i++) {
const but = element.buttons[i];
if (but.permission) {
obj.buttons.push(but._id);
}
}
}
let ret = await roleModule.findOneAndUpdate({ _id: req.body._id }, obj);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteRole(req, res, next) {
try {
const ret = await DB.Role.findOneAndUpdate({ _id: req.body._id }, { del: 1 });
res.sendData(ret)
} catch (error) {
next(error)
}
}
module.exports = {
regist,
login,
listUser,
addUser,
getUser,
updateUser,
getRole,
deleteUser,
createRole,
listRole,
updateRole,
deleteRole
}
\ No newline at end of file
const httpRequest = require('../utils/httpRequest');
const deviceModule = require('../module/deviceModule');
// 土壤
const collectSMCModule = require('../module/collectSMCModule');
// 虫情
const collectIPSModule = require('../module/collectIPSModule');
// 气象站
const collectWSModule = require('../module/collectWSModule');
const _ = require('lodash');
/**
* 获取协议 :
* 1 土壤温湿度、土壤氮磷钾,
* 2 土壤ph、土壤电导率,
* 3 气象站三大类设备
*/
async function getDeviceList() {
const url = sysConfig.device.getDeviceList;
const secretKey = sysConfig.device.secretKey;
let result = await httpRequest({
url,
method: "GET",
params: { secretKey },
});
console.log(result);
if (result && result.data.state == "success") {
let datas = result.data.datas || [];
await deviceModule.insertHQDevice(datas);
}
}
/**
* 虫情协议 4 获取虫情设备
*/
async function getAllDevice() {
const url = sysConfig.device.getAllDevice;
const token = sysConfig.device.token;
const userName = sysConfig.device.userName;
const password = sysConfig.device.password;
let result = await httpRequest({
url,
method: "POST",
params: { token, userName, password },
});
if (result && result.data.state == "success") {
let datas = result.data.data || [];
await deviceModule.insertHQDevice(datas, 4);
}
}
/* -------------------------------------------有诸多不确定因素,暂时分开,后续 请求日志需要分别按照不同设备种类区分类型------------------------------------------------------------------ */
/**
* 采集上述设备 1 的信息
*/
async function collectDeviceInfo1({ deviceHQType }) {
if (!deviceHQType) {
return;
}
const url = sysConfig.device.getDeviceInfo;
const secretKey = sysConfig.device.secretKey;
// 查询有效状态、类型的设备信息
const devices = await deviceModule.findAll({ deviceHQType: deviceHQType || 1, deviceHQState: 1, deviceNumber: { $exists: true } }, ['deviceNumber', 'deviceHQType', 'name']);
for (let index = 0; index < devices.length; index++) {
const dev = devices[index];
const result = await httpRequest({
url,
method: "GET",
params: { secretKey, deviceNumber: dev.deviceNumber }
});
if (result && result.data && result.data.state == "success") {
let colInfo = result.data.data;
if (colInfo && colInfo.deviceNumber) {
// 1. 处理 type 和 data
let handleData = await handleCJData(colInfo);
let obj = { ...colInfo, ...handleData };
obj.name = obj.name || dev.name;
console.log(obj, "==========================")
// 2. 入库
await collectSMCModule.insertHQData(obj);
// 3. 处理阈值报警通知
handleDeviceThreshold(obj);
// 4. 处理设备在线状态
handleDeviceOnLine({deviceNumber: obj.deviceNumber, online: obj.onLineState}); //onLineState 1在线0离线
} else {
//出错
}
}
}
}
/**
* 采集上述设备 2 的信息
*/
async function collectDeviceInfo2({ deviceHQType }) {
const url = sysConfig.device.getDeviceInfo;
const secretKey = sysConfig.device.secretKey;
// 查询有效状态、类型的设备信息
const devices = await deviceModule.findAll({ deviceHQType: deviceHQType || 2, deviceHQState: 1, deviceNumber: { $exists: true } }, ['deviceNumber', 'deviceHQType', 'name']);
for (let index = 0; index < devices.length; index++) {
const dev = devices[index];
const result = await httpRequest({
url,
method: "GET",
params: { secretKey, deviceNumber: dev.deviceNumber }
});
if (result && result.data && result.data.state == "success") {
let colInfo = result.data.data;
if (colInfo && colInfo.deviceNumber) {
// 1. 处理 type 和 data
let handleData = await handleCJData(colInfo);
let obj = { ...colInfo, ...handleData };
obj.name = obj.name || dev.name;
await collectSMCModule.insertHQData(obj);
// 处理设备在线状态
} else {
//出错
}
}
}
}
/**
* 采集上述设备 3 的信息
*/
async function collectDeviceInfo3({ deviceHQType }) {
if (!deviceHQType) {
return;
}
// 查询有效状态、类型的设备信息
const devices = await deviceModule.findAll({ deviceHQType: deviceHQType || 3, deviceHQState: 1, deviceNumber: { $exists: true } }, ['deviceNumber', 'deviceHQType']);
// if (col.includes("温度") && data[i]) {
// const dataArr = data[i].trim().split(' ');
// obj.soilTemperature = String(dataArr[0]).trim();
// obj.soilTemperatureUnit = String(dataArr[1]).trim();
// }
// if (col.includes("湿度")) {
// const dataArr = data[i].trim().split(' ');
// obj.soilMoisture = String(dataArr[0]).trim();
// obj.soilMoistureUnit = String(dataArr[1]).trim();
// }
// if (col.includes("氮")) {
// const dataArr = data[i].trim().split(' ');
// obj.nitrogen = String(dataArr[0]).trim();
// obj.nitrogenUnit = String(dataArr[1]).trim();
// }
// if (col.includes("磷")) {
// const dataArr = data[i].trim().split(' ');
// obj.phosphorus = String(dataArr[0]).trim();
// obj.phosphorusUnit = String(dataArr[1]).trim();
// }
// if (col.includes("钾")) {
// const dataArr = data[i].trim().split(' ');
// obj.potassium = String(dataArr[0]).trim();
// obj.potassiumUnit = String(dataArr[1]).trim();
// }
// if (col.includes("信号强度")) {
// const dataArr = data[i].trim().split(' ');
// obj.signalSterngth = String(dataArr[0]).trim();
// obj.signalSterngthUnit = String(dataArr[1]).trim();
// }
// if (col.includes("错误码")) {
// obj.errorCode = data[i].trim();
// }
// if (col.includes("版本号")) {
// obj.version = data[i].trim();
// }
}
/**
* 采集上述设备 4 的信息
*/
async function collectDeviceInfo4({ deviceHQType }) {
if (!deviceHQType) {
return;
}
const url = sysConfig.device.getInsectNewCollectionResult;
const token = sysConfig.device.token;
const userName = sysConfig.device.userName;
// const password = sysConfig.device.password;
// 查询有效状态、类型的设备信息
const devices = await deviceModule.findAll({ deviceHQType: '4', deviceHQState: 1 }, ['deviceNumber', 'deviceHQType']);
console.log(devices.length)
for (let index = 0; index < devices.length; index++) {
const dev = devices[index];
// console.log(dev);
const result = await httpRequest({
url,
method: "POST",
params: { token, userName, deviceNumber: dev.deviceNumber }
});
// console.log(result);
if(result && result.data && result.data.state == "success") {
let obj = result.data.data || {};
obj.name = obj.name || dev.name;
await collectIPSModule.insertHQData(obj);
console.log(obj);
// 3. 处理虫情每日种类数量记录
// handleIPS(obj);
// 4. 处理设备在线状态
handleDeviceOnLine({deviceNumber: obj.deviceNumber, online: obj.online}); //onLineState 1在线0离线
}
}
}
/**-------------数据处理---------------- */
// colInfo是一个硬件设备的一条信息
async function handleCJData(colInfo) {
let handleData = {};
//1. 先获取到attr配置
let attrs = await DB.CollectAttribute.find({del: 0, enable: true});
let types = colInfo.type.split('/');
let data = colInfo.data.split('|');
for (let i = 0; i < types.length; i++) {
const col = types[i];
for (let j = 0; j < attrs.length; j++) {
const attr = attrs[j];
if(col.includes(attr.deviceKey)) {
if(['errorCode', 'version'].includes(attr.dbKey)) {
handleData[attr.dbKey] = data[i].trim();
} else {
const dataArr = data[i].trim().split(' ');
handleData[attr.dbKey] = Number(String(dataArr[0]).trim());
handleData[`${attr.dbKey}Unit`] = String(dataArr[1]).trim();
}
}
}
}
return handleData;
}
async function handleDeviceOnLine({deviceNumber, online}) {
// 虫情 online = 0;//在线状态 0false/1true
// 土壤 onLineState 1在线0离线
if(!deviceNumber) {
return;
}
//该方式待定
let key = `device_online`;
if(online == 0) {
await ioRedis.hdel(key, deviceNumber);
} else {
let obj = {};
obj[deviceNumber] = 1;
await ioRedis.hset(key, obj)
}
}
async function handleDeviceThreshold(obj) {
let ths = await DB.CollectThreshold.find({del: 0, enable: true, deviceNumber: obj.deviceNumber}).lean().exec();
let exceeds = [];
for (let i = 0; i < ths.length; i++) {
const element = ths[i];
console.log(element, "====", obj[element.dbKey], _.isNumber(obj[element.dbKey]), _.gt(obj[element.dbKey], element.max), _.isNumber(element.max))
if(_.isNumber(obj[element.dbKey])) {
if(_.isNumber(element.max) && _.gt(obj[element.dbKey], element.max)) {
// 采集值 > 最大设置值
exceeds.push({...element, collectValue: obj[element.dbKey], deviceNumber: obj.deviceNumber});
}
if(_.isNumber(element.min) && _.lt(obj[element.dbKey], element.min)) {
exceeds.push({...element, collectValue: obj[element.dbKey], deviceNumber: obj.deviceNumber});
}
}
}
console.log(exceeds);
// 处理通知模板
}
/**-------------数据处理---------------- */
// collectDeviceInfo1({deviceHQType:1});
// getDeviceList()
module.exports = {
getDeviceList,
getAllDevice,
collectDeviceInfo1,
collectDeviceInfo2,
collectDeviceInfo3,
collectDeviceInfo4,
}
\ No newline at end of file
const nodeCron = require('node-cron');
const config = require('../config');
const deviceCron = require('./deviceCron');
/**
根据config cron 配置 定时处理
# ┌────────────── second (optional)
# │ ┌──────────── minute
# │ │ ┌────────── hour
# │ │ │ ┌──────── day of month
# │ │ │ │ ┌────── month
# │ │ │ │ │ ┌──── day of week
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * *
*/
const cron = () => {
// 1 土壤温湿度、土壤氮磷钾, 2 土壤ph、土壤电导率, 3 气象站
if (sysConfig && sysConfig.cron && sysConfig.cron.getDeviceList) {
console.log("getDeviceList:", new Date());
// 每天10点30分 处理 1 30 10 * * *
new nodeCron.schedule('1 30 10 * * *', async () => {
await deviceCron.getDeviceList();
}, { timezone: "Asia/Shanghai" });
}
// 4 虫情
if (sysConfig && sysConfig.cron && sysConfig.cron.getAllDevice) {
console.log("getAllDevice:", new Date());
new nodeCron.schedule('1 30 10 * * *', async () => {
await deviceCron.getAllDevice();
}, { timezone: "Asia/Shanghai" });
}
/*-----------------------------采集设备信息-------------------------------------*/
// 获取设备上述设备 1 采集信息 以数据库表里面的设备为准备
// if (sysConfig && sysConfig.cron && sysConfig.cron.collectDeviceInfo) {
// console.log("collectDeviceInfo1:", new Date());
// // 每10分钟
// new nodeCron.schedule('0 */3 * * * *', async () => {
// await deviceCron.collectDeviceInfo1({ deviceHQType: 1 });
// }, { timezone: "Asia/Shanghai" });
// }
// // 获取设备上述设备 2 采集信息
// if (sysConfig && sysConfig.cron && sysConfig.cron.collectDeviceInfo) {
// console.log("collectDeviceInfo2:", new Date());
// new nodeCron.schedule('* */3 * * * *', async () => {
// await deviceCron.collectDeviceInfo2({ deviceHQType: 2 });
// }, { timezone: "Asia/Shanghai" });
// }
// // 获取设备上述设备 3 采集信息
// if (sysConfig && sysConfig.cron && sysConfig.cron.collectDeviceInfo) {
// console.log("collectDeviceInfo3:", new Date());
// new nodeCron.schedule('* */3 * * * *', async () => {
// await deviceCron.collectDeviceInfo3({ deviceHQType: 3 });
// }, { timezone: "Asia/Shanghai" });
// }
// // 获取设备上述设备 4 采集信息
if (sysConfig && sysConfig.cron && sysConfig.cron.collectDeviceInfo) {
console.log("collectDeviceInfo4:", new Date());
new nodeCron.schedule('* */3 * * * *', async () => {
await deviceCron.collectDeviceInfo4({ deviceHQType: 4 });
}, { timezone: "Asia/Shanghai" });
}
}
module.exports = cron;
\ No newline at end of file
const mongoose = require('mongoose');
// 连接字符串,格式为 mongodb://用户名:密码@地址:端口/数据库名
const dbURI = sysConfig.dbURI || 'mongodb://localhost:27017/letian';
// 连接数据库
console.log(dbURI, "000-0-0-0-0-0-0")
mongoose.connect(dbURI, {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// 连接断开时的监听
mongoose.connection.on('disconnected', () => {
console.log('MongoDB Disconnected');
});
/*------------------------------*/
/**
1. 由于硬件提供的API返回参数皆为驼峰命名,为了对接方便,本系统数据库字段设计按照驼峰命名
如 templateId deviceNumber
2. 特殊情况下 允许字段使用数字作为区分,数字直接与字母相连
如 智壤仪温度1 soilTemperature1 智壤仪温度2 soilTemperature2
3. 数据库表名按照第一条规则,也采用驼峰命名
4. 单词尽量使用翻译器翻译之后考虑使用,要求简洁、见名知义
*/
const User = require('./models/systemUser');
const Role = require('./models/systemRole');
const Menu = require('./models/systemMenu');
const Button = require('./models/systemButton');
const Depart = require('./models/systemDepart');
const File = require('./models/systemFile');
const Land = require('./models/letianLand');
const AgrInRecord = require('./models/letianAgrInRecord');
const Device = require('./models/collectDevice');
const CollectSMC = require('./models/collectSMC');
const CollectIPS = require('./models/collectIPS');
const CollectIPSResult = require('./models/collectIPSResult');
const CollectIPSType = require('./models/collectIPSType');
const CollectIPSPlan = require('./models/collectIPSPlan');
const CollectWS = require('./models/collectWS');
const CollectAttribute = require('./models/collectAttribute');
const CollectThreshold = require('./models/collectThreshold');
const RequestLog = require('./models/systemRequestLog');
global.DB = {
User,
Role,
Menu,
Button,
Device,
Depart,
File,
Land,
AgrInRecord,
CollectThreshold,
CollectSMC,
CollectIPS,
CollectIPSResult,
CollectIPSType,
CollectIPSPlan,
CollectAttribute,
CollectWS,
RequestLog,
}
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 采集数据 有哪些属性 在硬件上设置的key是什么
*/
const collectAttributeSchema = new Schema({
deviceKey: {
type: String,
comment: "在硬件上设置的key 如:土壤湿度"
},
dbKey: {
type: String,
comment: "数据库里面的key 如:windSpeed"
},
name: {
type: String,
comment: "名称 如: 湿度"
},
enable: {
type: Boolean,
default: true,
comment: "true: 启用, false: 不启用"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const CollectAttribute = mongoose.model('CollectAttribute', collectAttributeSchema, 'collectAttribute'); // model名字 schema 数据库表名
module.exports = CollectAttribute;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
const deviceModule = require('../../module/deviceModule');
/**
* 硬件设备
*/
const deviceSchema = new Schema({
id: {
type: Number,
// required: true,
comment: "硬件方提供的设备id",
// unique: true
},
name: {
type: String,
required: true,
set: setNameToDevice,
comment: "设备名称"
},
deviceNumber: {
type: String,
required: true,
unique: true,
index: true
},
creatTime: {
type: Date,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
connectType: {
type: String,
},
/*--虫情设备独有--- */
leader: {
type: String,
comment: "虫情站负责人",
},
phone: {
type: String,
comment: "负责人联系方式",
},
position: {
type: String,
comment: "所处位置:汉字",
},
latitudeAndLongitude: {
type: String,
comment: "所在位置:坐标点(高德地图)",
},
latestCollectionCount: {
type: Number,
comment: "最新一次识图识别到的数量",
},
latestCollectionTime: {
type: Date,
comment: "最新一次识别时间",
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
typeCount: {
type: Number,
comment: "最新一次识别的种类数量",
},
imgUrl: {
type: String,
comment: "最新一次采集的图片",
},
online: {
type: Number,
comment: "在线状态0false/1true",
},
dayEarlyCount: {
type: Number,
comment: "日预警次数",
},
clearTime: {
type: Date,
comment: "设备上次清洁时间",
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
/* -------------设备与地块的信息----------------- */
land: {
type: mongoose.Types.ObjectId,
ref: "Land",
},
/* -------------------------------------------------- */
deviceHQState: {
type: Number,
default: 1,
comment: "通过http接口获取到的设备状态, 默认有效:1,某次获取若设备消失,则状态置为失效:0",
},
deviceHQType: {
type: Number,
comment: "获取的设备类型 1.土壤温湿度、土壤氮磷钾, 2土壤ph、土壤电导率, 3 气象站, 4虫情",
},
deviceType: {
type: Number,
comment: "1 采集设备 2 气象站 3 全景相机 4 细节相机"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true
}
});
function setNameToDevice(v) {
deviceModule.setNameToDevice(this._update.deviceNumber, v);
return v;
}
const Device = mongoose.model('collectDevice', deviceSchema, 'collectDevice');
module.exports = Device;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 虫情 采集信息
*/
const collectInsectPestSituationSchema = new Schema({
// name: {
// type: String,
// required: true,
// comment: "设备名称"
// },
deviceNumber: {
type: String,
required: true,
index: true
},
time: {
type: Date,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
comment: "采集时间"
},
downloadUrl: {
type: String,
comment: "摄像头采集原图下载URL",
},
downloadUrlCompress: {
type: String,
comment: "摄像头采集原图下载URL(压缩后)",
},
newTime: {
type: Date,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
comment: "最新一次识别时间",
},
results: {
type: String,
comment: "最新一次识别结果",
},
newCount: {
type: Number,
comment: "最新一次识别数量",
},
typeCount: {
type: Number,
comment: "最新一次识别的种类数量",
},
oldCount: {
type: Number,
comment: "上一次识别数量",
},
oldTime: {
type: Date,
comment: "上一次识别时间",
},
oldResults: {
type: String,
comment: "上一次识别结果",
},
oldTypeCount: {
type: Number,
comment: "上一次识别种类数量",
},
oldDownloadUrl: {
type: String,
comment: "上一次摄像头采集原图下载URL",
},
oldDownloadUrlCompress: {
type: String,
comment: "上一次摄像头采集原图下载URL(压缩后)",
},
taggingImgUrl: {
type: String,
comment: "标注后的图片",
},
taggingImgUrlCompress: {
type: String,
comment: "标注后图片(压缩后)",
},
oldDownloadUrl: {
type: String,
comment: "上一次标注后的图片",
},
oldDownloadUrlCompress: {
type: String,
comment: "上一次标注后的图片(压缩后)",
},
/* 图片识别结果 */
cameraRecognition: {
type: String
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true,
}
});
const CollectIPS = mongoose.model('CollectIPS', collectInsectPestSituationSchema, 'collectIPS');
module.exports = CollectIPS;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 虫情 采集信息
*/
const collectIPSPlanSchema = new Schema({
name: {
type: String,
comment: "虫子名称"
},
createTime: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
id: {
type: Number,
},
controlPlan: {
type: String,
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true,
}
});
const CollectIPSPlan = mongoose.model('CollectIPSPlan', collectIPSPlanSchema, 'collectIPSPlan');
module.exports = CollectIPSPlan;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 虫情 图片识别结果
*/
const collectIPSResultSchema = new Schema({
deviceNumber: {
type: String,
required: true,
index: true
},
cameraRecognition: {
type: "String",
comment: "识别的原始结果",
},
name: {
type: String,
comment: "虫子名称"
},
count: {
type: Number,
comment: "数量"
},
time: {
type: Date,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
comment: "采集时间"
},
type: {
type: mongoose.Types.ObjectId,
ref: "CollectIPSType",
comment: "虫子种类表id",
},
plan: {
type: mongoose.Types.ObjectId,
comment: "防治建议表id",
},
data: {
type: mongoose.Types.ObjectId,
comment: "硬件采集数据的id",
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true,
}
});
const CollectIPSResult = mongoose.model('CollectIPSResult', collectIPSResultSchema, 'collectIPSResult');
module.exports = CollectIPSResult;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 虫情 采集信息
*/
const collectIPSTypeSchema = new Schema({
name: {
type: String,
comment: "虫子名称"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true,
}
});
const CollectIPSType = mongoose.model('CollectIPSType', collectIPSTypeSchema, 'collectIPSType');
module.exports = CollectIPSType;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 墒情监测预警 采集信息
*/
const soilMoistureContentSchema = new Schema({
id: {
type: Number,
comment: "硬件方提供的设备id",
},
name: {
type: String,
required: true,
comment: "设备名称"
},
deviceNumber: {
type: String,
required: true,
index: true
},
/* 接口返回的数据原始存储 */
type: {
type: String,
},
data: {
type: String,
},
/* --------------------- */
time: {
type: Date,
comment: "采集时间",
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
soilTemperature: {
type: Number,
// get: v => String(v) + "℃",
comment: "土壤温度",
},
soilTemperatureUnit: {
type: String,
comment: "土壤温度单位",
},
soilMoisture: {
type: Number,
comment: "土壤湿度",
},
soilMoistureUnit: {
type: String,
comment: "土壤湿度 单位",
},
nitrogen: {
type: Number,
comment: "氮",
},
nitrogenUnit: {
type: String,
comment: "氮 单位",
},
phosphorus: {
type: Number,
comment: "磷",
},
phosphorusUnit: {
type: String,
comment: "磷 单位",
},
potassium: {
type: Number,
comment: "钾",
},
potassiumUnit: {
type: String,
comment: "钾 单位",
},
soilPH: {
type: Number,
comment: "土壤PH",
},
soilPHUnit: {
type: String,
comment: "土壤PH 单位",
},
soilConductivity: {
type: Number,
comment: "土壤电导率",
},
soilConductivityUnit: {
type: String,
comment: "土壤电导率 单位",
},
signalSterngth: {
type: Number,
comment: "信号强度",
},
soilConductivityUnit: {
type: String,
comment: "信号强度 单位",
},
errorCode: {
type: String,
comment: "错误码",
},
version: {
type: String,
comment: "版本号",
},
creatTime: {
type: Date,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
connectType: {
type: String,
},
onLineState: {
type: String,
comment: "在线状态,该字段不记录到db,后期采集数据时将状态更新到redis里面即可"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true,
}
});
const CollectSMC = mongoose.model('CollectSMC', soilMoistureContentSchema, 'collectSMC');
module.exports = CollectSMC;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 针对采集数据里面的各类属性设置阈值
* 阈值表
*
*/
const collectThresholdSchema = new Schema({
deviceNumber: {
type: String,
},
dbKey: {
type: String,
comment: "CollectAttribute存的信息"
},
max: {
type: Number,
comment: "最大值"
},
min: {
type: Number,
comment: "最小值"
},
attrId: {
type: mongoose.Types.ObjectId,
required: true,
ref: 'CollectAttribute',
comment: "对应的属性id"
},
enable: {
type: Boolean,
default: true,
comment: "true: 启用, false: 不启用"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const CollectThreshold = mongoose.model('CollectThreshold', collectThresholdSchema, 'collectThreshold');
module.exports = CollectThreshold;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 气象站 采集信息
*/
const collectWeatherStationSchema = new Schema({
id: {
type: Number,
comment: "硬件方提供的设备id",
},
name: {
type: String,
required: true,
comment: "设备名称"
},
deviceNumber: {
type: String,
required: true,
index: true
},
/* 接口返回的数据原始存储 */
type: {
type: String,
},
data: {
type: String,
},
/* -------------------------- */
time: {
type: Date,
comment: "采集时间",
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
windSpeed: {
type: Number,
comment: "风速",
},
windSpeedUnit: {
type: String,
comment: "风速单位",
},
windDirection: {
type: Number,
comment: "风向",
},
windDirectionUnit: {
type: String,
comment: "风向单位",
},
rainfall: {
type: Number,
comment: "雨量",
},
rainfallUnit: {
type: String,
comment: "雨量单位",
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true,
}
});
const CollectWS = mongoose.model('CollectWS', collectWeatherStationSchema, 'collectWS');
module.exports = CollectWS;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 乐田 农业投入品 出入库记录表
*/
const letianAgrInRecordSchema = new Schema({
name: {
type: String,
required: true,
commnet: "品名",
},
total: {
type: Number,
comment: "库存总量"
},
inNum: {
type: Number,
default: 0,
comment: "入库"
},
outNum: {
type: Number,
default: 0,
comment: "出库"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const AgrInRecord = mongoose.model('AgrInRecord', letianAgrInRecordSchema, 'letianAgrInRecord');
module.exports = AgrInRecord;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 地块
*/
const landSchema = new Schema({
name: {
type: String,
required: true,
comment: "地块名称"
},
landNumber: {
type: String,
required: true,
comment: "地块编号",
},
area: {
type: Number,
comment: "面积",
},
areaUnit: {
type: String,
comment: "面积单位",
},
varieties: {
type: String,
comment: "品种",
},
/* -----地理信息----- */
/* -----地理信息----- */
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true
}
});
const Land = mongoose.model('Land', landSchema, 'letianLand');
module.exports = Land;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 乐田 农业投入品 采购
*/
const letianAgrInRecordSchema = new Schema({
purchaseDate: {
type: Date,
// default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
comment: "购买日期"
},
name: {
type: String,
required: true,
commnet: "产品名称",
},
specifications: {
type: String,
comment: "规 格"
},
ingredients: {
type: String,
comment: "成分"
},
shipmentQuantity: {
type: Number,
default: 0,
comment: "出货数量"
},
unit: {
type: String,
comment: "单位"
},
shippingPrice: {
type: String,
comment: "出货价格(元)"
},
totalAmount : {
type: String,
comment: "合计金额(元)"
},
consumption : {
type: String,
comment: "用量"
},
agent : {
type: String,
comment: "代理商"
},
remarks : {
type: String,
comment: "备注"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const AgrInRecord = mongoose.model('AgrInRecord', letianAgrInRecordSchema, 'letianAgrInRecord');
module.exports = AgrInRecord;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 按钮 与菜单关联 字段按前端需要增删
*/
const buttonSchema = new Schema({
name: {
type: String,
required: true,
commnet: "按钮名称",
},
key: {
type: String,
required: true,
commnet: "按钮标志",
},
menuId: {
type: mongoose.Types.ObjectId,
required: true,
comment: "所属哪一个菜单",
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const Button = mongoose.model('Button', buttonSchema, 'systemButton');
module.exports = Button;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 部门
*/
const departSchema = new Schema({
name: {
type: String,
required: true,
// unique: true,
commnet: "部门名称",
},
/**------------- */
parentId: {
type: mongoose.Types.ObjectId,
ref: 'Depart',
default: null,
},
parentIds: {
type: [mongoose.Types.ObjectId],
ref: 'Depart',
default: [],
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const Depart = mongoose.model('Depart', departSchema, 'systemDepart');
module.exports = Depart;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 用户
*/
const fileSchema = new Schema({
originalname: {
type: String,
comment: "原始名称"
},
filename: {
type: String,
comment: "存储的文件名"
},
size: {
type: Number,
},
mimietype: {
type: String
},
url: {
type: String,
},
path: {
type: String,
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const File = mongoose.model('File', fileSchema, 'systemFile');
module.exports = File;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 权限
*/
const menuSchema = new Schema({
name: {
type: String,
},
// level: Number,
url: {
type: String,
},
order: {
type: Number,
default: 100,
},
parentId: {
type: mongoose.Types.ObjectId,
ref: 'Menu',
default: null,
},
parentIds: {
type: [mongoose.Types.ObjectId],
ref: 'Menu',
default: [],
},
buttons: {
type: [mongoose.Types.ObjectId],
ref: 'Button',
default: [],
},
enable: {
type: Boolean,
default: true,
comment: "true: 启用, false: 不启用"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const Menu = mongoose.model('Menu', menuSchema, 'systemMenu');
module.exports = Menu;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 用户
*/
const Noticechema = new Schema({
sendUser: {
},
receiveUser: {
},
content: String,
sendTime: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const Notice = mongoose.model('Notice', Noticechema, 'systemNotice');
module.exports = Notice;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 系统接口访问日志
*/
const requestLogSchema = new Schema({
reqId: {
type: String,
comment: "给每一个请求分配一个id"
},
user: {
type: String,
},
url: {
type: String,
},
params: {
type: String,
comment: "请求参数"
},
headers: {
type: String,
comment: "请求头"
},
method: {
type: String,
comment: "请求方法"
},
result: {
type: String,
comment: "返回结果"
},
status: {
type: String,
comment: "http请求状态"
},
msg: {
type: String,
comment: "http请求错误信息"
},
type: {
type: String,
comment: "日志类型 调用外部硬件接口日志:device, 系统内部请求日志:system",
default: "system"
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
}
}, {
toJSON: {
getters: true
}
});
const RequestLog = mongoose.model('RequestLog', requestLogSchema, 'systemRequestLog');
module.exports = RequestLog;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 角色
*/
const roleSchema = new Schema({
name: {
type: String,
required: true,
commnet: "角色名称",
},
key: {
type: String,
required: true,
commnet: "角色标识",
},
menus: {
type: [mongoose.Types.ObjectId],
ref: "Menu",
},
buttons: {
type: [mongoose.Types.ObjectId],
ref: "Button",
},
/* -------------------------------------- */
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const Role = mongoose.model('Role', roleSchema, 'systemRole');
module.exports = Role;
\ No newline at end of file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 用户
*/
const userSchema = new Schema({
mobile: {
type: String,
required: true,
unique: true,
commnet: "手机号",
},
password: {
type: String,
required: true,
comment: "密码"
},
name: {
type: String,
required: true,
comment: "姓名"
},
gender: {
type: String,
comment: "性别 男 女"
},
salt: {
type: String,
required: true,
commnet: "加密密钥"
},
roles: {
type: [mongoose.Types.ObjectId],
ref: "Role",
},
/**------------- */
depart: {
type: mongoose.Types.ObjectId,
ref: "Depart",
comment: "一个人只有一个部门 ,若存在一个人多个部门的情况,需要重新设计"
},
enable: {
type: Boolean,
default: true,
comment: "true: 启用, false: 不启用"
},
status: {
type: Number,
comment: "状态 1:正常, 2:.....",
default: 1
},
createdAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
updatedAt: {
type: Date,
default: Date.now,
get: v => moment(v).format("YYYY-MM-DD HH:mm:ss"),
},
del: {
type: Number,
default: 0,
comment: '默认0 , 1:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
id: false,
toJSON: {
getters: true,
}
});
const User = mongoose.model('User', userSchema, 'systemUser');
module.exports = User;
\ No newline at end of file
const Redis = require('ioredis');
const redis = new Redis({
host: "localhost",
port: 6379,
});
module.exports = redis;
\ No newline at end of file
const Joi = require('joi');
/**
* 参数校验 https://joi.dev/api/?v=17.13.0
* @param {*} req
* @param {*} res
* @param {*} next
* @returns
*/
module.exports = (req, res, next) => {
console.log(req.headers, req.url, req.method, req.path, req.baseUrl, req.originalUrl);
// const schema = schemas[req.originalUrl];
// if (schema) {
// const { error } = schema.validate({
// ...req.body,
// ...req.query
// });
// console.log(error); //eslint-disable-line
// if (error) {
// return res.status(400).send({
// code: 402,
// message: error.details[0].message,
// success: false
// });
// }
// }
next();
}
const schemas = {
//用户
'/api/user/register': Joi.object({
phone: Joi.string().regex(/^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$/).required(),
password: Joi.string().regex(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/).required(),
full_name: Joi.string(),
department: Joi.string(),
position: Joi.string()
}),
}
const createError = require('http-errors');
const requestLogModule = require("../module/requestLogModule");
const mongoose = require('mongoose');
//
module.exports = async (req, res, next) => {
req.reqId = new mongoose.Types.ObjectId();
/* 1. 处理token */
// if (!checkPath(req.path)) {
// if (!req.headers.Authorization) {
// next(createError(401));
// }
// const userStr = await ioRedis.get(`token:${req.headers.Authorization}`);
// if (userStr) {
// try {
// req.user = JSON.parse(userStr);
// // 刷新token时间
// await ioRedis.expire(`token:${req.headers.Authorization}`, sysConfig.tokenEx)
// } catch (error) {
// //解析有误
// next(createError(401));
// }
// } else {
// //过期
// next(createError(401));
// }
// }
/* --------------3. 记录所有进来的日志,是否记录响应的值有待 */
requestLogModule.createRequestLog({
url: req.baseUrl + req.path,
params: JSON.stringify({
...req.body,
...req.query,
...req.params,
}),
reqId: req.reqId,
user: req.user,
method: req.method,
headers: JSON.stringify(req.headers),
});
next();
}
function checkPath(path) {
if (['/user/login', '/user/regist'].includes(path)) {
return true;
} else {
return false;
}
}
\ No newline at end of file
const requestLogModule = require("../module/requestLogModule");
module.exports = (req, res, next) => {
res['sendData'] = (data) => {
res.status(200).send({
code: 0,
data: data,
message: 'success',
});
requestLogModule.updateRequestLog({
reqId: req.reqId,
result: JSON.stringify(data),
msg: "success",
status: 200,
});
};
res['sendError'] = (error) => {
// 除404 500以外 其他均归类为业务错误 以http 200返回,具体错误在返回内容里面根据code来区分。
res.status(200).send({
code: error.code,
message: error.message,
});
requestLogModule.updateRequestLog({
reqId: req.reqId,
result: JSON.stringify(error.message),
msg: "error",
status: 200,
});
};
next();
}
\ No newline at end of file
const _ = require('lodash');
const httpRequest = require('../utils/httpRequest');
const FormData = require('form-data');
// 更新单个
async function updateOne(filter, updateObj) {
return DB.CollectIPS.findOneAndUpdate(filter, updateObj);
}
// 查询单个
async function findOne(search) {
return DB.CollectIPS.findOne(search);
}
// 翻页查询
async function findList(search, options) {
if (!(_.isNumber(options.skip) && _.isNumber(options.limit))) {
return [];
}
return DB.CollectIPS.find(search).skip(options.skip).limit(options.limit).sort({ time: -1 });
}
// 总量
async function count(search) {
console.log(DB.CollectIPS)
return DB.CollectIPS.countDocuments(search);
}
async function insertHQData(data) {
if (!(data.deviceNumber && data.newTime)) {
return;
}
data.time = data.newTime;
let check = await DB.CollectIPS.findOne({ newTime: data.newTime });
if (!check) {
let ret = await DB.CollectIPS.create(data);
handleIPSResult(ret);
}
}
async function handleIPSResult(data) {
try {
const url = sysConfig.device.getInsectNewCollectionResult;
const token = sysConfig.device.token;
const userName = sysConfig.device.userName;
// 1. 上传结果照片 获取结果
let formData = new FormData();
let imgUrl = sysConfig.device.fileBaseUrl + data.downloadUrl;
formData.append('token', token);
formData.append('userName', userName);
formData.append('deviceNumber', data.deviceNumber);
let imgStream = await httpRequest({ url: imgUrl, method: 'GET', responseType: "stream" });
if (imgStream.status) {
formData.append('img', imgStream);
const result = await httpRequest({
url,
method: "POST",
headers: { "Content-Type": "mutipart/form-data" },
data: formData
});
if (result.status) {
// 需要处理一张识别的种类表 获取其对应的方案 成功
// await DB.CollectIPS.updateOne({_id: data._id}, {cameraRecognition});
let retData = result.data;
let retArr = retData.split(',');
for (let index = 0; index < retArr.length; index++) {
const element = retArr[index];
let eleArr = element.split(':');
let name = String(eleArr[0]).trim();
// 记录虫子类型
let bugType = await DB.CollectIPSType.findOneAndUpdate({ name }, { name }, { upsert: true });
//获取防止建议---此处建议不从远端取,在本系统根据虫子种类维护建议即可
let preInRet = await httpRequest({
url: sysConfig.device.getPreventionToInsectName,
method: "POST",
data: { token, userName, name },
});
let plan;
if (preInRet && preInRet.status) {
preInRet.data = preInRet.data || [];
for (let pi = 0; pi < preInRet.data.length; pi++) {
const pir = preInRet.data[pi];
plan = await DB.CollectIPSPlan.findOneAndUpdate({ name }, pir, { upsert: true });
}
}
// 记录识别的每一次识别的 虫子 的种类 和 数量
// 此处暂时 每一次单独记录 不是对每一天做累加
await DB.CollectIPSResult.create({
name,
// $inc: {count: 11},
count: element.newCount,
time: data.time || data.newTime,
type: bugType && bugType._id,
plan: plan && plan._id,
data: data._id,
});
}
}
}
} catch (error) {
console.log(error)
}
}
setTimeout(() => {
handleIPSResult({
downloadUrl: 'pictures/FF355138D5C3/2024-05-29-05-59-43.jpg',
taggingImgUrl: 'picturesResult/FF355138D5C3/2024-05-29-05-59-43.jpg',
downloadUrlCompress: 'picturesCompress/FF355138D5C3/orgin_2024-05-29-05-59-43.jpg',
taggingImgUrlCompress: 'picturesCompress/FF355138D5C3/result_2024-05-29-05-59-43.jpg',
deviceNumber: 'FF355138D5C3',
newTime: '2024-05-29 05:59:43',
results: '飞蛾:2',
newCount: 2,
typeCount: 1,
oldCount: 0,
oldTime: null,
oldResults: null,
oldTypeCount: 0,
oldDownloadUrl: 'pictures/FF355138D5C3/2024-05-29-05-59-43.jpg',
oldTaggingImgUrl: 'picturesResult/FF355138D5C3/2024-05-29-05-59-43.jpg',
oldDownloadUrlCompress: null,
oldTaggingImgUrlCompress: 'picturesCompress/FF355138D5C3/result_2024-05-29-05-59-43.jpg',
name: undefined,
time: '2024-05-29 05:59:43'
})
}, 5000)
module.exports = {
insertHQData,
findList,
count,
findOne,
updateOne,
}
\ No newline at end of file
const _ = require('lodash');
// 更新单个
async function updateOne(filter, updateObj) {
return DB.CollectSMC.findOneAndUpdate(filter, updateObj);
}
// 查询单个
async function findOne(search) {
return DB.CollectSMC.findOne(search);
}
// 翻页查询
async function findList(search, options) {
if(!(_.isNumber(options.skip) && _.isNumber(options.limit))) {
return [];
}
return DB.CollectSMC.find(search).skip(options.skip).limit(options.limit).sort({time:-1});
}
// 总量
async function count(search) {
console.log(DB.CollectSMC)
return DB.CollectSMC.countDocuments(search);
}
async function insertHQData(data) {
if(!(data.deviceNumber && data.time)) {
return;
}
return await DB.CollectSMC.findOneAndUpdate({time: data.time}, data, {upsert: true})
}
module.exports = {
insertHQData,
findList,
count,
findOne,
updateOne,
}
\ No newline at end of file
const _ = require('lodash');
// 更新单个
async function updateOne(filter, updateObj) {
return DB.CollectWS.findOneAndUpdate(filter, updateObj);
}
// 查询单个
async function findOne(search) {
return DB.CollectWS.findOne(search);
}
// 翻页查询
async function findList(search, options) {
if(!(_.isNumber(options.skip) && _.isNumber(options.limit))) {
return [];
}
return DB.CollectWS.find(search).skip(options.skip).limit(options.limit).sort({time:-1});
}
// 总量
async function count(search) {
console.log(DB.CollectWS)
return DB.CollectWS.countDocuments(search);
}
async function insertHQData(data) {
if(!(data.deviceNumber && data.time)) {
return;
}
let check = await DB.CollectWS.findOne({time: data.time});
if(!check) {
await DB.CollectWS.create(data);
}
}
module.exports = {
insertHQData,
findList,
count,
findOne,
updateOne,
}
\ No newline at end of file
const errorMessage = require('../utils/errorMessage');
const _ = require('lodash');
async function findOne(search) {
if(_.isEmpty(search)) {
return null;
}
return DB.Depart.findOne(search);
}
async function create(obj) {
return DB.Depart.create(obj);
}
async function findOneAndUpdate(filter, updateObj) {
return DB.Depart.findOneAndUpdate(filter, updateObj);
}
async function count(search) {
return DB.Depart.countDocuments(search);
}
async function findList(search, options) {
if(!(_.isNumber(options.skip) && _.isNumber(options.limit))) {
return [];
}
return DB.Depart.find(search).skip(options.skip).limit(options.limit).populate({
path: "parentId parentIds",
// select: {name: 1, parentId: 1},
});
}
async function findAll(search) {
return DB.Depart.find(search)
.populate({
path: "parentIds",
// select: {name: 1, parentId: 1},
}).lean().exec();
}
module.exports = {
findOne,
create,
findOneAndUpdate,
findList,
count,
findAll,
}
\ No newline at end of file
const _ = require('lodash');
const httpRequest = require('../utils/httpRequest');
// 按设备编号查询
async function findDeviceByDeviceNumber(deviceNumber) {
if(!deviceNumber) {
return null;
}
return DB.Device.findOne({deviceNumber});
}
// 查询所有设备 数量不多
async function findAll(search, fields = [], ) {
search = _.isObject(search) ? search : {};
//注意 若数量超出一定数额 需改动做法
// let count = await DB.Device.count(search);
return DB.Device.find(search).select(fields.join(' '));
}
/**
* 用来插入通过 "HTTP数据获取-设备接口" 获取的设备插入
* 1. 检查是否存在,存在则更新设备信息,不存在则插入系统
* 2. 如果之前出现,后续没有出现的需要去掉
* ----
* 按照最新沟通的结果,设备可能是固定的,或许不需要实时更新设备列表
*/
async function insertHQDevice(datas, deviceHQType) {
let devNumArr = [];
for (let i = 0; i < datas.length; i++) {
const element = datas[i];
if(element.deviceNumber) {
devNumArr.push(element.deviceNumber);
await DB.Device.findOneAndUpdate({deviceNumber: element.deviceNumber}, {...element, deviceHQType, deviceHQState: 1 }, {upsert: true})
}
}
//将不在返回列表里的设备更新状态
// await DB.Device.updateMany({deviceNumber: {$in: devNumArr}}, {deviceHQState: 0})
}
// 获取设备的在线状态
async function getDeviceOnlineMap () {
let ioRedis = require('../db/redis')
let onlineArr = await ioRedis.hkeys('device_online');
return onlineArr;
}
async function setNameToDevice(deviceNumber, deviceName) {
if(!deviceNumber || !deviceName) {
return;
}
const url = sysConfig.device.upDeviceInfo;
const secretKey = sysConfig.device.secretKey;
const result = await httpRequest({
url,
method: "POST",
params: { secretKey, deviceNumber, deviceName }
});
console.log(result)
}
module.exports = {
findDeviceByDeviceNumber,
insertHQDevice,
findAll,
getDeviceOnlineMap,
setNameToDevice,
}
\ No newline at end of file
// class Log {
// constructor(moduleName) {
// this.module = DB[`${moduleName}`]
// }
// createLog() {
// return this.module.create(data);
// }
// }
async function createRequestLog(data) {
return DB.RequestLog.create(data);
}
async function updateRequestLog(data) {
return DB.RequestLog.findOneAndUpdate({reqId: data.reqId}, data);
}
module.exports = {
createRequestLog,
updateRequestLog,
}
\ No newline at end of file
const _ = require('lodash')
async function create(obj) {
const ret = await DB.User.create(obj);
return ret;
}
async function findUserByMobile(mobile) {
if (!mobile) {
return null;
}
const user = await DB.User.findOne({ mobile }).populate({ path: "roles depart" }).lean();
return user;
}
async function findList(search, fields, options) {
if (!(_.isNumber(options.skip) && _.isNumber(options.limit))) {
return [];
}
console.log(search)
return DB.User.find(search).skip(options.skip).limit(options.limit).select(fields.join(" ")).populate({ path: "roles depart" });
}
async function findOne(search, fields) {
const user = await DB.User.findOne(search).select(fields.join(" "));
return user;
}
async function findOneAndUpdate(filter, updateObj) {
return DB.User.findOneAndUpdate(filter, updateObj);
}
async function getRoleMenus(roles) {
let menuIds = [], buttonIds = [];
for (let index = 0; index < roles.length; index++) {
const element = roles[index];
element.menus = element.menus || [];
element.buttons = element.buttons || [];
menuIds = menuIds.concat(element.menus);
buttonIds = buttonIds.concat(element.buttons);
}
console.log(menuIds)
let buts = await DB.Button.find({ del: 0, _id: { $in: buttonIds } }).lean().exec();
let bMap = {};
buts.map(o => { bMap[o.menuId] = bMap[o.menuId] || []; o.permission = true; bMap[o.menuId].push(o) });
let mes = await DB.Menu.find({ del: 0, enable: true, _id: { $in: menuIds } }).populate({ path: "parentIds" }).lean().exec();
console.log(mes)
let nodes = [], nodeMap = {};
for (let index = 0; index < mes.length; index++) {
const element = mes[index];
element.parentIds = element.parentIds || [];
for (let i = 0; i < element.parentIds.length; i++) {
const par = element.parentIds[i];
if (!nodeMap[par._id]) {
par.buttons = bMap[par._id];
par.permission = true
nodes.push(par);
nodeMap[par._id] = 1;
}
}
if (!nodeMap[element._id]) {
element.parentIds = _.keys(_.groupBy(element.parentIds, '_id'));
element.buttons = bMap[element._id];
element.permission = true
nodes.push(element);
nodeMap[element._id] = 1;
}
}
console.log(nodes, "================");
let tree = utils.buildTree(nodes);
return tree;
}
module.exports = {
create,
findUserByMobile,
findList,
findOne,
findOneAndUpdate,
getRoleMenus,
}
\ No newline at end of file
{
"name": "letian",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"production": "NODE_ENV=production node server.js",
"dev": "cross-env NODE_ENV=dev nodemon server.js",
"local": "cross-env NODE_ENV=local nodemon server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.7.4",
"compression": "^1.7.4",
"crypto": "^1.0.1",
"eslint": "^9.4.0",
"express": "^4.19.2",
"form-data": "^4.0.0",
"ioredis": "^5.4.1",
"joi": "^17.13.1",
"lodash": "^4.17.21",
"moment": "^2.30.1",
"mongoose": "^8.5.3",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
"node-cron": "^3.0.3"
}
}
const express = require('express');
const router = express.Router();
const agrController = require('../controller/agrController');
router.post('/list', agrController.list);
// router.post('/create', agrController.create);
// router.post('/update', fileController.update);
// router.post('/upload', fileController.list);
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const collectIPSController = require('../controller/collectIPSController');
const collectSMCController = require('../controller/collectSMCController');
const collectWSController = require('../controller/collectWSController');
/* -----数据采集相关接口,可以用类简化 暂时---- */
/**
* 虫情
*/
router.post('/IPS/list', collectIPSController.list); // 翻页列表
router.post('/IPS/show', collectIPSController.queryInfo); // 查询详情
router.post('/IPS/update', collectIPSController.updateInfo); // 更新
router.post('/IPS/del', collectIPSController.delInfo); // 删除
/**
* 土壤
*/
router.post('/SMC/list', collectSMCController.list); // 翻页列表
router.post('/SMC/show', collectSMCController.queryInfo); // 查询详情
router.post('/SMC/update', collectSMCController.updateInfo); // 更新
router.post('/SMC/del', collectSMCController.delInfo); // 删除
/**
* 气象站
*/
router.post('/WS/list', collectWSController.list); // 翻页列表
router.post('/WS/show', collectWSController.queryInfo); // 查询详情
router.post('/WS/update', collectWSController.updateInfo); // 更新
router.post('/WS/del', collectWSController.delInfo); // 删除
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const departController = require('../controller/departController');
router.post('/create', departController.createDepart);
router.post('/info', departController.getDepartInfo);
router.post('/update', departController.updateDepart);
router.post('/list', departController.list); //获取平行列表
router.post('/tree', departController.tree);
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const deviceController = require('../controller/deviceController');
// router.post('/create', deviceController.);
router.post('/info', deviceController.getDevice);
router.post('/update', deviceController.updateDevice);
router.post('/list', deviceController.list); //获取平行列表
// router.post('/tree', deviceController.tree);
router.post('/threshold/set', deviceController.setThreshold); //按照设备设置阈值
router.post('/threshold/list', deviceController.listThreshold); //获取设备阈值设置列表
// router.post('/threshold/info', deviceController.getDeviceThreshold); //
router.post('/attribute/list', deviceController.listAttribute); //获取可设置属性列表
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const moment = require('moment');
const mongoose = require('mongoose');
const fileController = require('../controller/fileController');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, sysConfig.file.storagePath || 'public/avatar'); //相对路径
},
filename: function (req, file, cb) {
let ext = path.extname(file.originalname); // 获取文件扩展名
let basename = path.basename(file.originalname, ext); // 获取文件名主体
file.originalname = Buffer.from(basename, 'latin1').toString('utf8') + ext;
basename = moment().format('YYYYMMDDHHmmss') + '_' + new mongoose.Types.ObjectId();
cb(null, basename + ext)
}
})
const upload = multer({ storage: storage })
router.post('/upload', upload.single('file'), fileController.upload);
// 文件访问: 起nginx用以处理文件服务器。
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const userRouter = require('./userRouter');
const departRouter = require('./departRouter');
const menuRouter = require('./menuRouter');
const fileRouter = require('./fileRouter');
const collectRouter = require('./collectRouter');
const deviceRouter = require('./deviceRouter');
const landRouter = require('./landRouter');
const agrRouter = require('./agrRouter');
const statisticsRouter = require('./statisticsRouter');
const initController = require('../controller/initController')
router.post('/init', initController.init); // 后续删除
router.use('/user', userRouter); // 用户 角色
router.use('/depart', departRouter); // 部门
router.use('/menu', menuRouter); //菜单 按钮
router.use('/file', fileRouter); // 文件
router.use('/collect', collectRouter); // 数据采集
router.use('/device', deviceRouter); // 硬件设备
router.use('/land', landRouter); //地块
router.use('/agr', agrRouter); // 农业投入品相关
router.use('/statistics', statisticsRouter); // 统计 大屏
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const landController = require('../controller/landController');
router.post('/create', landController.create);
router.post('/update', landController.update);
router.post('/delete', landController.deleteLand);
router.post('/list', landController.list);
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const menuController = require('../controller/menuController');
/**
* 菜单
*/
router.post('/create', menuController.createMenu);
// router.post('/info', menuController.getMenuInfo);
router.post('/update', menuController.updateMenu);
router.post('/list', menuController.listMenu); //获取平行列表
router.post('/tree', menuController.treeMenu);
/**
* 按钮
*/
router.post('/button/create', menuController.createButton);
router.post('/button/update', menuController.updateButton);
// router.post('/button/create', menuController.createButton);
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const statisticsController = require('../controller/statisticsController');
router.post('/getSMCChangeTrend', statisticsController.getSMCChangeTrend);
router.post('/getWSChangeTrend', statisticsController.getWSChangeTrend);
router.post('/getIPSChangeTrend', statisticsController.getIPSChangeTrend);
router.post('/getDeviceCount', statisticsController.getDeviceCount);
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const userController = require('../controller/userController');
router.post('/regist', userController.regist);
router.post('/login', userController.login);
router.post('/manage/list', userController.listUser);
router.post('/manage/create', userController.addUser);
router.post('/manage/update', userController.updateUser); //更新
router.post('/manage/info', userController.getUser);
router.post('/manage/delete', userController.deleteUser); // 删除
/**
* 角色
*/
router.post('/role/create', userController.createRole);
router.post('/role/update', userController.updateRole);
router.post('/role/delete', userController.deleteRole);
router.post('/role/list', userController.listRole);
router.post('/role/info', userController.getRole);
module.exports = router;
\ No newline at end of file
const express = require('express');
const createError = require('http-errors');
const compress = require('compression');
const router = require('./router');
const path = require('path');
const logger = require('morgan');
//中间件
const parameter = require('./middleware/parameter');
const request = require('./middleware/request');
const response = require('./middleware/response');
const requestLogModule = require("./module/requestLogModule");
//系统数据库
require('./config');
require('./db');
require('./cron')();
global.utils = require('./utils');
global.ioRedis = require('./db/redis');
const app = express();
app.all('*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With, Range");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
next();
});
app.use(compress());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
console.log(__dirname)
app.use(express.static(path.join(__dirname, 'public')));
app.use(logger('dev'));
app.use('/api', request, response, router);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
console.log(err)
// 记录下错误日志
requestLogModule.createRequestLog({
url: req.path,
params: JSON.stringify({
...req.body,
...req.query,
...req.params,
}),
user: req.user,
status: err.status || 500,
msg: err.message || 'server error'
});
return res.status(err.status || 500).send({code: err.status || 500, msg: err.message || 'server error'});
});
const server = require('http').createServer(app);
server.listen(process.env.PORT || 3000, function () {
console.log(`****** server is listening : ${process.env.PORT}`);
});
module.exports = {
loginError: {
code: 40001,
message: "登录失败"
},
resourceNotFound: {
code: 40002,
message: "资源不存在"
},
databaseQueryError: {
code: 50001,
message: "数据库操作错误"
}
}
\ No newline at end of file
const axios = require('axios');
const requestLogModule = require("../module/requestLogModule");
async function httpRequest ({url, method, data, params, headers, responseType}) {
console.log(`${url}, ${JSON.stringify(data)}, ${JSON.stringify(params)}`)
try {
let opt = {
url,
method,
params: params || {},
data: data || {},
headers,
}
if(responseType) {
opt.responseType = responseType;
}
const ret = await axios(opt);
requestLogModule.createRequestLog({
url,
method,
params: JSON.stringify(params) + JSON.stringify(data),
headers: JSON.stringify(headers),
type: "device",
status: ret && ret.status,
result: JSON.stringify(ret.data)
});
if(ret && ret.status == 200) {
return {data: ret.data, status: true};
} else {
return {data: null, status: false};
}
} catch (error) {
console.log(error);
requestLogModule.createRequestLog({
url,
method,
params: JSON.stringify(params) + JSON.stringify(data),
headers: JSON.stringify(headers),
type: "device",
msg: error.message,
});
return {data: null, status: false};
}
}
module.exports = httpRequest;
\ No newline at end of file
const crypto = require('crypto');
function genRandomString(length) {
return crypto.randomBytes(Math.ceil(length / 2))
.toString('hex')
.slice(0, length);
}
function saltHashPassword(password) {
const salt = genRandomString(16);
const passwordHash = crypto.createHmac('sha256', salt).update(password).digest('hex');
return {
salt,
passwordHash
}
}
function checkUserPassword({ reqPw, salt, userPw }) {
const passwordHash = crypto.createHmac('sha256', salt).update(reqPw).digest('hex');
if (userPw == passwordHash) {
return true;
} else {
return false;
}
}
function buildTree(nodes) {
// 创建一个映射,将节点ID映射到节点对象
const nodeMap = new Map(nodes.map(node => [String(node._id), { ...node, children: [] }]));
// 遍历所有节点,并将它们添加到对应父节点的children数组中
nodes.forEach(node => {
const parentId = String(node.parentId);
if (parentId !== null) {
// 确保父节点在映射中存在
if (nodeMap.has(parentId)) {
// 将当前节点添加到父节点的children数组中
nodeMap.get(parentId).children.push(nodeMap.get(String(node._id)));
}
}
});
// 从映射中提取顶级节点(parentId为null)
return Array.from(nodeMap.values()).filter(node => node.parentId === null);
}
function disTree(tree) {
let parallel = [];
function addToParallel(nodes) {
nodes.forEach(node => {
parallel.push({
...node,
children: undefined
});
if (node.children && node.children.length) {
addToParallel(node.children);
}
});
}
addToParallel(tree)
return parallel
}
module.exports = {
saltHashPassword,
checkUserPassword,
buildTree,
disTree,
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment