明树Git Lab

Commit df2f0f9b authored by zengfanpei's avatar zengfanpei

update

parent da915974
......@@ -17,8 +17,10 @@
# 记录
```
1. 待完成excel导出
2. 农业投入品表的增删改查
1. 待完成excel导出 -- 这个要看前端做管理端菜单管理,需要知道在那个菜单 对应哪个表
2. 农业投入品表的增删改查 已完成
```
......@@ -25,6 +25,12 @@
"2": "气象站",
"3": "全景相机",
"4": "细节相机"
},
"typeCount": {
"1": 100,
"2": 100,
"3": 100,
"4": 100
}
},
"cron": {
......
const ExcelJS = require('exceljs');
......@@ -26,6 +26,45 @@ async function upload(req, res, next) {
async function importExcel(req, res, next) {
try {
console.log(DB.AreaRecord.schema.obj);
let workbook = new ExcelJS.Workbook();
await workbook.xlsx.readFile(req.file.path);
let worksheet = workbook.getWorksheet(1);
console.log(worksheet.actualRowCount);
let values = worksheet.getRow(1).values; // 示例:‌读取第一行
// for (let index = 1; index < worksheet.actualRowCount; index++) {
// let values = worksheet.getRow(index + 1).values;
// await DB.AreaRecord.create({
// province: values[1],
// city: values[2],
// county: values[3],
// town: values[4],
// zone: values[5],
// plantArea: values[6],
// varieties: values[7],
// area: Number( values[8]),
// yield: Number(values[9]),
// yieldValue:Number(values[10]),
// year: values[11]
// })
// }
//1. 先通过参数获取对应的表字段对应关系
//2. 找到对应的表 写入
res.send(DB.AreaRecord.schema.obj);
} catch (error) {
next(error);
}
}
......@@ -33,5 +72,6 @@ async function upload(req, res, next) {
module.exports = {
upload
upload,
importExcel
}
\ No newline at end of file
const moment = require('moment');
const _ = require('lodash');
const errorMessage = require('../utils/errorMessage');
/**
* 获取墒情 时间段内变化趋势
......@@ -147,6 +149,7 @@ async function getDeviceCount(req, res, next) {
}
]);
let devMap = sysConfig.device.typeName; // { 1: "采集点", 2: "气象站", 3: "全景相机", 4: "细节相机" };
let devCount = sysConfig.device.typeCount; // { 1: "采集点", 2: "气象站", 3: "全景相机", 4: "细节相机" };
let retMap = {};
for (let i = 0; i < ret.length; i++) {
const element = ret[i];
......@@ -157,7 +160,8 @@ async function getDeviceCount(req, res, next) {
datas.push({
typeName: devMap[key],
_id: key,
count: retMap[key] || 0
count: devCount[key] || retMap[key] || 0,
online: 1, //在线
});
}
res.sendData(datas);
......@@ -167,6 +171,86 @@ async function getDeviceCount(req, res, next) {
}
async function getAreaDistribution(req, res, next) {
try {
// 跟前端约定 传递对应区域名称
let zonePre = await DB.Zone.findOne({name: req.body.name, del: 0});
if(!zonePre) {
res.sendError(errorMessage.resourceNotFound);
}
//往下取一层
let len = zonePre.parentIds && zonePre.parentIds.length || 0;
let zones = await DB.Zone.find({"parentIds": {$size: len + 1, $elemMatch: {$eq: zonePre._id}}}).lean().exec(); //查找所有子区域
let zoneIds = zones.map(o => {return o._id});
zoneIds.push(zonePre._id);
let lands = await DB.Land.aggregate([
{$match: {zone: {$in: zoneIds }}},
{$group: {
_id: "$varieties",
area: {$sum: "$area"},
latestYield: {$sum: "$latestYield"},
latestYieldValue: {$sum: "$latestYieldValue"},
}}
]);
let totalArea = _.sumBy(lands, 'area');
let totalYield = _.sumBy(lands, 'latestYield');
let totalYieldValue = _.sumBy(lands, 'latestYieldValue');
let data = [];
for (let index = 0; index < lands.length; index++) {
const element = lands[index];
if(totalArea != 0) {
element.areaPercentage = _.multiply(_.divide(element.area, totalArea), 100).toFixed(0) + '%';
} else {
element.areaPercentage = "0%"
}
if(totalYield != 0) {
element.yieldPercentage = _.multiply(_.divide(element.latestYield, totalYield), 100).toFixed(0) + '%';
} else {
element.yieldPercentage = "0%"
}
if(totalYieldValue != 0) {
element.yieldValuePercentage = _.multiply(_.divide(element.latestYieldValue, totalYieldValue), 100).toFixed(0) + '%';
} else {
element.yieldValuePercentage = "0%"
}
data.push(element);
}
res.sendData({
totalArea,
totalYield,
totalYieldValue,
data
});
} catch (error) {
next(error);
}
}
async function getAreaDistribution2(req, res, next) {
try {
let search = {
year: moment().format("YYYY")
}
// 跟前端约定 传递对应区域名称
if(req.body.name == "雷州半岛") {
search.county = "雷州市";
} else
if(req.body.name == "乐田农业") {
search.$or = [
{county: {$regex: "乐田"}},
{zone: {$regex: "乐田"}}
];
} else {
search.plantArea = req.body.name;
}
let areaReds = await DB.AreaRecord.find(search);
res.sendData(areaReds);
} catch (error) {
next(error);
}
}
......@@ -179,5 +263,7 @@ module.exports = {
getWSChangeTrend,
getIPSChangeTrend,
getDeviceCount,
getAreaDistribution,
getAreaDistribution2,
}
\ No newline at end of file
async function create(req, res, next) {
try {
let newZone = {
...req.body,
}
let parentIds = [];
if (req.body.parentId) {
let parentDepart = await DB.Zone.findOne({ _id: req.body.parentId });
if (!(parentDepart && parentDepart._id)) {
res.sendError(errorMessage.resourceNotFound);
}
parentIds = parentDepart.parentIds || [];
parentIds.push(parentDepart._id);
newZone.parentId = req.body.parentId;
newZone.parentIds = parentIds;
}
let ret = await DB.Zone.create(newZone);
res.sendData(ret);
} catch (error) {
next(error);
}
}
//
async function update(req, res, next) {
try {
let updateObj = {
...req.body,
_id: undefined,
}
// 处理父级数据
let parentIds = [];
if (req.body.parentId) {
let parentDepart = await DB.Zone.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.Zone.findOneAndUpdate({ _id: req.body._id }, updateObj);
res.sendData(ret);
} catch (error) {
next(error);
}
}
async function deleteLand(req, res, next) {
try {
let ret = await DB.Zone.findOneAndUpdate({ _id: req.body._id }, { del: 1 });
res.sendData(ret);
} 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 list = await DB.Zone.find(search).populate({
path: "parentIds",
match: {del: 0},
// select: {name:1}
}).lean().exec();
let nodes = [], nodeMap = {};
for (let i = 0; i < list.length; i++) {
const dep = list[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);
}
}
module.exports = {
create,
update,
deleteLand,
tree,
}
......@@ -36,7 +36,9 @@ const File = require('./models/systemFile');
const Notice = require('./models/systemNotice');
const Land = require('./models/letianLand');
const Zone = require('./models/letianZone');
const AgrInRecord = require('./models/letianAgrInRecord');
const AreaRecord = require('./models/letianAreaRecord');
const Device = require('./models/collectDevice');
......@@ -63,7 +65,9 @@ global.DB = {
Notice,
Land,
Zone,
AgrInRecord,
AreaRecord,
CollectThreshold,
CollectSMC,
......
File added
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 园区
* 结构设想是:省-市-县-乡镇-园区
*/
const letianAreaRecord = new Schema({
province: {
type: String,
comment: "省份",
},
city: {
type: String,
comment: "市/自治区",
},
county: {
type: String,
comment: "县/区",
},
town: {
type: String,
comment: "镇名",
},
zone: {
type: String,
comment: "种植园区",
},
plantArea: {
type: String,
comment: "种植区",
},
varieties: {
type: String,
comment: "品种",
},
area: {
type: Number,
comment: "面积",
},
yield: {
type: Number,
comment: "产量",
},
yieldValue: {
type: Number,
comment: "产值",
},
year: {
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 AreaRecord = mongoose.model('AreaRecord', letianAreaRecord, 'letianAreaRecord');
module.exports = AreaRecord;
\ No newline at end of file
......@@ -3,7 +3,7 @@ const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 地块
* 地块 --- 园区 ---- 乡镇(这个等级暂时不做)
*/
const landSchema = new Schema({
name: {
......@@ -28,6 +28,19 @@ const landSchema = new Schema({
type: String,
comment: "品种",
},
latestYield: {
type: Number,
comment: "最近一期的产量,通过产量表录入",
},
latestYieldValue: {
type: Number,
comment: "最近一期的产值,通过产值表录入",
},
zone: {
type: mongoose.Types.ObjectId,
comment: "地块隶属于哪一个园区, 理论上每一级都可以绑定地块, 建议只能选择zone的最后一级"
},
/* -----地理信息----- */
/* -----地理信息----- */
......
......@@ -19,7 +19,7 @@ const letianAgrInRecordSchema = new Schema({
},
specifications: {
type: String,
comment: "规 格"
comment: "规格"
},
ingredients: {
type: String,
......
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
/**
* 园区
* 结构设想是:省-市-县-乡镇-园区
*/
const ZoneSchema = new Schema({
name: {
type: String,
required: true,
comment: "园区名称"
},
parentId: {
type: mongoose.Types.ObjectId,
ref: 'Zone',
default: null,
},
parentIds: {
type: [mongoose.Types.ObjectId],
ref: 'Zone',
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:表示删除,若有其他隐藏业务 不要混用此字段。'
}
}, {
toJSON: {
getters: true
}
});
const Zone = mongoose.model('Zone', ZoneSchema, 'letianZone');
module.exports = Zone;
\ No newline at end of file
......@@ -12,7 +12,7 @@ module.exports = async (req, res, next) => {
}
req.headers.authorization = req.headers.authorization || req.headers.Authorization;
const userStr = await ioRedis.get(`token:${req.headers.authorization}`);
console.log(userStr)
// console.log(userStr)
if (userStr) {
try {
req.user = JSON.parse(userStr);
......
......@@ -51,6 +51,7 @@ async function findAll(search) {
return DB.Depart.find(search)
.populate({
path: "parentIds",
match: {del: 0},
// select: {name: 1, parentId: 1},
}).lean().exec();
}
......
......@@ -30,4 +30,10 @@ router.post('/upload', upload.single('file'), fileController.upload);
// 文件访问: 起nginx用以处理文件服务器。
/**
* excel导出
*/
router.post('/importExcel', upload.single('file'), fileController.importExcel);
module.exports = router;
\ No newline at end of file
......@@ -11,6 +11,8 @@ const fileRouter = require('./fileRouter');
const collectRouter = require('./collectRouter');
const deviceRouter = require('./deviceRouter');
const landRouter = require('./landRouter');
const zoneRouter = require('./zoneRouter');
const agrRouter = require('./agrRouter');
const statisticsRouter = require('./statisticsRouter');
......@@ -28,7 +30,10 @@ router.use('/file', fileRouter); // 文件
router.use('/collect', collectRouter); // 数据采集
router.use('/device', deviceRouter); // 硬件设备
router.use('/land', landRouter); //地块
router.use('/zone', zoneRouter); //区域--可扩展为行政区划
router.use('/agr', agrRouter); // 农业投入品相关
router.use('/statistics', statisticsRouter); // 统计 大屏
......
......@@ -4,12 +4,20 @@ const router = express.Router();
const statisticsController = require('../controller/statisticsController');
// 大屏 采集站 近7日数据变化趋势 --要看硬件是分开 还是集中返回
router.post('/getSMCChangeTrend', statisticsController.getSMCChangeTrend);
//大屏 气象 近7日数据变化趋势
router.post('/getWSChangeTrend', statisticsController.getWSChangeTrend);
// 大屏 虫情 历史趋势
router.post('/getIPSChangeTrend', statisticsController.getIPSChangeTrend);
// 大屏 设备数量展示
router.post('/getDeviceCount', statisticsController.getDeviceCount);
// 大屏 面积分布 这一种是按照数据库思路设计
router.post('/getAreaDistribution', statisticsController.getAreaDistribution);
// 大屏 面积分布2 这一种是按照给定汇总表设计
router.post('/getAreaDistribution2', statisticsController.getAreaDistribution2);
module.exports = router;
\ No newline at end of file
const express = require('express');
const router = express.Router();
const zoneController = require('../controller/zoneController');
router.post('/create', zoneController.create);
router.post('/update', zoneController.update);
router.post('/delete', zoneController.deleteLand);
router.post('/tree', zoneController.tree);
module.exports = router;
\ 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