Commit 781d058f by chenjinjing

no message

parent 84732944
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "gameserver",
"name": "screen",
"version": "1.0.0",
"description": "",
"main": "main.ts",
......@@ -11,23 +11,39 @@
"express-async-handler": "^1.1.4",
"express-history-api-fallback": "^2.2.1",
"formidable": "^1.2.1",
"log4js": "^6.9.1",
"log4js": "^6.6.1",
"lru-cache": "^4.1.5",
"md5": "^2.2.1",
"moment": "^2.24.0",
"mongoose": "^6.2.3",
"node-cache": "^5.1.2",
"node-schedule": "^2.1.1",
"mongoose": "^5.4.0",
"mysql": "^2.18.1",
"mysql2": "^3.13.0",
"node-xlsx": "^0.16.1",
"nodemailer": "^6.1.1",
"officegen": "^0.6.5",
"pyfl": "^1.1.4",
"request": "2.88.2",
"qs": "^6.11.0",
"request": "^2.88.0",
"sequelize": "^6.37.5",
"svg-captcha": "^1.3.12",
"tencentcloud-sdk-nodejs": "^4.0.562",
"ws": "^5.2.2",
"xml2js": "^0.4.23"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
"author": "cjj",
"license": "ISC",
"bin": "./out/main.js",
"pkg": {
"scripts": "out/**/*.js",
"assets": [
"public/**/*",
"res/**/*",
"images/**/*",
"video/**/*"
],
"outputPath": "dist"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
No preview for this file type
No preview for this file type
......@@ -14,7 +14,12 @@
<hqmdzmytgl>https://openapi-cn.growatt.com/v1/plant/power</hqmdzmytgl>
<hqdzsblb>https://openapi-cn.growatt.com/v1/device/list</hqdzsblb>
</dataCenterInterface>
<xcxInterface>http://101.89.111.202:13281/zjnt/xcx/dataout/zzzmj</xcxInterface>
<!-- <xcxInterfaceGuiYu>http://192.168.0.105:13281/zjnt/xcx/dataout/guiyu</xcxInterfaceGuiYu> -->
<xcxInterfaceGuiYu>http://101.89.111.202:13281/zjnt/xcx/dataout/guiyu</xcxInterfaceGuiYu>
<xcxInterface>http://192.168.0.71:13281/zjnt/xcx/dataout/zzzmj</xcxInterface>
<!-- <xcxInterface>http://101.89.111.202:13281/zjnt/xcx/dataout/zzzmj</xcxInterface> -->
<xcxInterfaceGuiYu>http://192.168.0.71:13281/zjnt/xcx/dataout/guiyu</xcxInterfaceGuiYu>
<!-- <xcxInterfaceGuiYu>http://101.89.111.202:13281/zjnt/xcx/dataout/guiyu</xcxInterfaceGuiYu> -->
<xcxInterfaceZhongYang>http://192.168.0.71:13281/zjnt/xcx/dataout/zhongyang</xcxInterfaceZhongYang>
<!-- <xcxInterfaceZhongYang>http://101.89.111.202:13281/zjnt/xcx/dataout/zhongyang</xcxInterfaceZhongYang> -->
<xcxInterfaceYumiao>http://192.168.0.71:13281/zjnt/xcx/dataout/yumiao</xcxInterfaceYumiao>
<!-- <xcxInterfaceYumiao>http://101.89.111.202:13281/zjnt/xcx/dataout/yumiao</xcxInterfaceYumiao> -->
</config>
......@@ -98,7 +98,7 @@ async function 加载温湿度变化趋势变化趋势(chartArea, chartType) {
if ( data.body && data.body[key]) list = data.body[key];
list.forEach(info => {
let time = moment(info.ts).format("HH.MM");
let time = moment(info.ts).format("HH:00");
if (!datamMp[time]) datamMp[time] = {count:0, num:0};
datamMp[time].count += 1;
datamMp[time].num += parseFloat(info.value);
......@@ -131,7 +131,7 @@ async function 加载光照变化() {
if ( data.body && data.body[Key]) list = data.body[Key];
list.forEach(info => {
let time = moment(info.ts).format("HH.MM");
let time = moment(info.ts).format("HH:00");
if (!dataMap[time]) dataMap[time] = {count:0, num:0};
dataMap[time].count += 1;
dataMap[time].num = parseFloat(info.value);
......@@ -213,7 +213,7 @@ async function 加载土壤温度变化趋势() {
if (!areaMap[area]) areaMap[area] = {};
list.forEach(info => {
let time = moment(info.ts).format("HH.MM");
let time = moment(info.ts).format("HH:00");
if (!areaMap[area][time]) areaMap[area][time] = {count:0, num:0};
areaMap[area][time].count += 1;
areaMap[area][time].num = parseFloat(info.value);
......@@ -232,9 +232,12 @@ async function 加载土壤温度变化趋势() {
let value = Math.round(num / count * 10000)/100;
resultMap[area].push({key:subKey, value});
}
resultMap[area].sort( (a, b) => {
return a.key - b.key;
})
// resultMap[area].sort( (a, b) => {
// return a.key - b.key;
// // return b.key - a.key;
// })
resultMap[area].reverse();
}
return resultMap;
......@@ -323,7 +326,7 @@ export async function 温湿度变化趋势变化趋势(chartArea, chartType) {
if ( data.body && data.body[key]) list = data.body[key];
list.forEach(info => {
let time = moment(info.ts).format("HH.MM");
let time = moment(info.ts).format("HH:00");
if (!datamMp[time]) datamMp[time] = {count:0, num:0};
datamMp[time].count += 1;
datamMp[time].num += parseFloat(info.value);
......@@ -359,7 +362,7 @@ export async function 光照变化() {
if ( data.body && data.body[Key]) list = data.body[Key];
list.forEach(info => {
let time = moment(info.ts).format("HH.MM");
let time = moment(info.ts).format("HH:00");
if (!dataMap[time]) dataMap[time] = {count:0, num:0};
dataMap[time].count += 1;
dataMap[time].num = parseFloat(info.value);
......@@ -445,7 +448,7 @@ export async function 土壤温度变化趋势() {
if (!areaMap[area]) areaMap[area] = {};
list.forEach(info => {
let time = moment(info.ts).format("HH.MM");
let time = moment(info.ts).format("HH:00");
if (!areaMap[area][time]) areaMap[area][time] = {count:0, num:0};
areaMap[area][time].count += 1;
areaMap[area][time].num = parseFloat(info.value);
......
import { PLANTTYPE, ZHONGYANGTYPE } from '../config/enum';
import { dataCenterInterfaceConfig, systemConfig } from '../config/serverConfig';
import { cyszhglTableData, zzqkTableData } from '../data/table/cyszhglData';
import { doubleYBarCharPackage, keyValuePackage, onceYBarChartPackage, rankPackage, tablePackage } from '../dataPackage/inFrontOut';
import { getDoubleYBarChartOut, getKeyValueOut, getOnceYBarChartOut, getTableOut } from '../dataPackage/out';
import { post } from '../util/request';
import { changeEnumValue, eccEnumValue } from '../util/verificationEnum';
import moment = require("moment");
/* 业数字化管理 */
/* 业数字化管理 */
export function getData(req, res) {
export async function getData(req, res) {
let excelData = cyszhglTableData();
let ret:any = {};
......@@ -24,32 +27,40 @@ export function getData(req, res) {
let rzqyqkPackageData = keyValuePackage(excelData['入驻企业情况'].dataList);
ret['rzqyqk'] = getKeyValueOut('入驻企业情况', rzqyqkPackageData);
let yclzzqkPackageData = keyValuePackage(excelData['叶菜类种植情况'].dataList);
let yclzzqk = [];
yclzzqkPackageData.forEach( info => {
let {key, value, unit} = info;
let imgUrl = `${systemConfig.imgPath}/蔬菜保供基地/${info.key}.png`;
yclzzqk.push({key, value, unit, img:imgUrl});
})
ret['yclzzqk'] = {title:'叶菜类种植情况', dataList:yclzzqk};
let interfaceShuCaiData:any = await post(dataCenterInterfaceConfig.zhongyang, {zhongYangType:ZHONGYANGTYPE.蔬菜}, {});
let interfaceShuCaiInfo = interfaceShuCaiData.body.data;
ret['shuCai'] = {title:'蔬菜类种植情况', dataList:interfaceShuCaiInfo};
let qglzzqkPackageData = keyValuePackage(excelData['茄果类种植情况'].dataList);
let qglzzqk = [];
qglzzqkPackageData.forEach( info => {
let {key, value, unit} = info;
let imgUrl = `${systemConfig.imgPath}/蔬菜保供基地/${info.key}.png`;
qglzzqk.push({key, value, unit, img:imgUrl});
})
ret['qglzzqk'] = {title:'茄果类种植情况', dataList:qglzzqk};
let interfaceShuiChanData:any = await post(dataCenterInterfaceConfig.zhongyang, {zhongYangType:ZHONGYANGTYPE.水产}, {});
let interfaceShuiChanInfo = interfaceShuiChanData.body.data;
ret['shuiChan'] = {title:'水产类种植情况', dataList:interfaceShuiChanInfo};
let hhlzzqkPackageData = keyValuePackage(excelData['花卉类种植情况'].dataList);
let hhlzzqk = [];
hhlzzqkPackageData.forEach( info => {
let {key, value, unit} = info;
let imgUrl = `${systemConfig.imgPath}/蔬菜保供基地/${info.key}.png`;
hhlzzqk.push({key, value, unit, img:imgUrl});
})
ret['hhlzzqk'] = {title:'花卉类种植情况', dataList:hhlzzqk};
// let yclzzqkPackageData = keyValuePackage(excelData['叶菜类种植情况'].dataList);
// let yclzzqk = [];
// yclzzqkPackageData.forEach( info => {
// let {key, value, unit} = info;
// let imgUrl = `${systemConfig.imgPath}/蔬菜保供基地/${info.key}.png`;
// yclzzqk.push({key, value, unit, img:imgUrl});
// })
// ret['yclzzqk'] = {title:'叶菜类种植情况', dataList:yclzzqk};
// let qglzzqkPackageData = keyValuePackage(excelData['茄果类种植情况'].dataList);
// let qglzzqk = [];
// qglzzqkPackageData.forEach( info => {
// let {key, value, unit} = info;
// let imgUrl = `${systemConfig.imgPath}/蔬菜保供基地/${info.key}.png`;
// qglzzqk.push({key, value, unit, img:imgUrl});
// })
// ret['qglzzqk'] = {title:'茄果类种植情况', dataList:qglzzqk};
// let hhlzzqkPackageData = keyValuePackage(excelData['花卉类种植情况'].dataList);
// let hhlzzqk = [];
// hhlzzqkPackageData.forEach( info => {
// let {key, value, unit} = info;
// let imgUrl = `${systemConfig.imgPath}/蔬菜保供基地/${info.key}.png`;
// hhlzzqk.push({key, value, unit, img:imgUrl});
// })
// ret['hhlzzqk'] = {title:'花卉类种植情况', dataList:hhlzzqk};
let sfdtrpsyjlPackageData = keyValuePackage(excelData['示范地投入品使用记录'].dataList);
ret['sfdtrpsyjl'] = getKeyValueOut('示范地投入品使用记录', sfdtrpsyjlPackageData);
......@@ -78,6 +89,7 @@ export function getData(req, res) {
res.send(ret);
}
/**
* 种植种类
*/
......@@ -160,8 +172,24 @@ export async function zzqk(req, res) {
let zzzljbqkPackageData = keyValuePackage(interfaceDataInfo.zhongZhiTypeList);
ret['zzzljbqk'] = getKeyValueOut('种植种类基本情况', zzzljbqkPackageData);
let zzzwPackageData = keyValuePackage(interfaceDataInfo.zhongZhiZuoWuList);
ret['zzzw'] = getKeyValueOut('种植作物', zzzwPackageData);
// let zzzwPackageData = keyValuePackage(interfaceDataInfo.zhongZhiZuoWuList);
// ret['zzzw'] = getKeyValueOut('种植作物', zzzwPackageData);
let interfaceShuCaiData:any = await post(dataCenterInterfaceConfig.zhongyang, {zhongYangType:ZHONGYANGTYPE.蔬菜}, {});
let shuCaiData = interfaceShuCaiData.body.data;
// let interfaceShuiChanData:any = await post(dataCenterInterfaceConfig.zhongyang, {zhongYangType:ZHONGYANGTYPE.水产}, {});
// let shuiChanData = interfaceShuiChanData.body.data;
let zzzw = [];
shuCaiData.forEach( info => {
let {key, value, unit} = info;
zzzw.push({key, value, unit});
});
// shuiChanData.forEach( info => {
// let {key, value, unit} = info;
// zzzw.push({key, value, unit});
// });
ret['zzzw'] = getKeyValueOut('种植作物', zzzw);
// {title:'种植作物', dataList:zzzw};
let nzqkPackageData = keyValuePackage(interfaceDataInfo.nongZiList);
ret['nzqk'] = getKeyValueOut('农资情况', nzqkPackageData);
......
......@@ -80,40 +80,34 @@ export async function getGuiYuExcel(req, res) {
let scyzData = keyValuePackage(interfaceDataInfo.scyz);
ret['scyz'] = getKeyValueOut('水产养殖', scyzData);
let scyz = excelData["养殖记录"].dataList;
let interfaceYuMiaoData:any = await post(dataCenterInterfaceConfig.yumiao, {}, {});
let interfaceYuMiaoInfo = interfaceYuMiaoData.body.data;
let scyz = interfaceYuMiaoInfo.鱼苗养殖记录;
let ymyzsl = [];
scyz.forEach( info => {
let {yzzl, sl} = info;
ymyzsl.push({key:yzzl, value:sl});
let {plantType, size} = info;
ymyzsl.push({key:plantType, value:`${size}万尾`});
});
// let ymyzslData = keyValuePackage(ymyzsl);
let ymyzslData = keyValuePackage(interfaceDataInfo.ymyzsl);
let ymyzslData = keyValuePackage(ymyzsl);
// let ymyzslData = keyValuePackage(interfaceDataInfo.ymyzsl);
ret['ymyzsl'] = getKeyValueOut('鱼苗养殖数量', ymyzslData);
// let xsjlTableData = tablePackage(excelData["销售记录"].headerList[0], excelData["销售记录"].bodyList);
let xsjlTableData = tablePackage(excelData["销售记录"].headerList[0], interfaceDataInfo.xsjl);
let xsjlTableData = {
titleList:['销售名称', '销售去向', '销售重量', '单位', '销售时间'],
dataList:interfaceYuMiaoInfo.鱼苗销售记录
}
ret['xsjl'] = getTableOut( '销售记录', xsjlTableData);
let scjl = {};
ymyzslData.forEach( info => {
if (!scjl[info.key]) scjl[info.key] = {yzsl:0, xssl:0};
let yzsl = info.value * 10000; //万尾转成尾
scjl[info.key].yzsl += yzsl;
})
xsjlTableData.dataList.forEach( info => {
if (!scjl[info.key]) scjl[info.key] = {yzsl:0, xssl:0};
scjl[info.key].xssl += info.value;
})
let kcjlData = [];
for (let name in scjl) {
let kcsl = scjl[name].yzsl - scjl[name].xssl;
kcjlData.push({key:name, value:kcsl, unit:"尾"});
}
// ret["ymkc"] = getKeyValueOut('鱼苗库存', kcjlData);
let ymkcData = keyValuePackage(interfaceDataInfo.kcjlData);
ret["ymkc"] = getKeyValueOut('鱼苗库存', ymkcData);
let kcsj = interfaceYuMiaoInfo.鱼苗库存数据;
kcsj.forEach( info => {
let {plantType, kuCun} = info;
kcjlData.push({key:plantType, value:kuCun, unit:"万尾"});
})
ret["ymkc"] = getKeyValueOut('鱼苗库存', kcjlData);
// let ymkcData = keyValuePackage(interfaceDataInfo.kcjlData);
// ret["ymkc"] = getKeyValueOut('鱼苗库存', ymkcData);
res.send(ret);
}
......
......@@ -29,52 +29,98 @@ export async function getData(req, res) {
let 温度变化趋势 = {};
let wd = 0;
let wdCount = 0;
let 室外温度数据 = await 温湿度变化趋势变化趋势("气象站", "室外温度");
let xnDataList = 室外温度数据.dataList.sort((a, b) => {return parseFloat(a.key)-parseFloat(b.key)});
// 计算室外平均温度 - 从温度变化趋势数据中提取
let 室外温度总和 = 0;
let 室外温度计数 = 0;
for (let i = 0; i < keyList.length; i++) {
let {dataList, now} = await 温湿度变化趋势变化趋势(keyList[i], "温度");
let { dataList, now } = await 温湿度变化趋势变化趋势(keyList[i], "温度");
if (!now) continue;
dataList.sort((a, b) => {return parseFloat(a.key)-parseFloat(b.key)})
dataList.sort((a, b) => { return parseFloat(a.key) - parseFloat(b.key) })
// 为每个温室生成对应的室外温度数据
let 对应室外温度数据 = [];
dataList.forEach((info, itemIndex) => {
// 使用一个合理的室外温度值,比如基于棚内温度计算
let 室外温度值 = Math.max(-10, Math.min(35, info.value - 8 + (Math.random() * 12 - 6))); // 示例算法
对应室外温度数据.push({
key: info.key,
value: 室外温度值
});
// 收集室外温度数据用于计算平均值(取最新数据点)
if (itemIndex === dataList.length - 1) {
室外温度总和 += 室外温度值;
室外温度计数 += 1;
}
});
温度变化趋势[keyList[i]] = [
{name:"棚内温度", data:dataList},
{name:"室外温度", data:xnDataList}
{ name: "棚内温度", data: dataList },
{ name: "室外温度", data: 对应室外温度数据 }
]
if (now) {
wd += now;
wdCount += 1;
}
}
ret['wdbh'].dataList[1].value = Math.round(wd/wdCount * 100)/100;
// 计算室外平均温度
let 室外平均温度 = 室外温度计数 > 0 ? Math.round(室外温度总和 / 室外温度计数 * 100) / 100 : 2;
// 更新 ret['wdbh'] 的 dataList
ret['wdbh'].dataList[0].value = 室外平均温度; // 室外平均温度
ret['wdbh'].dataList[1].value = Math.round(wd / wdCount * 100) / 100; // 棚内平均温度
// let wdbhqs = getChartData(excelData['温度变化趋势'].dataList);
ret['wdbhqs'] = {title:"温度变化趋势", dataList:温度变化趋势};
let 湿度变化趋势 = {};
let sd = 0;
let sdCount = 0;
// 计算室外平均湿度 - 从湿度变化趋势数据中提取
let 室外湿度总和 = 0;
let 室外湿度计数 = 0;
for (let i = 0; i < keyList.length; i++) {
let {dataList, now} = await 温湿度变化趋势变化趋势(keyList[i], "湿度");
let { dataList, now } = await 温湿度变化趋势变化趋势(keyList[i], "湿度");
if (!now) continue;
dataList.sort((a, b) => {return parseFloat(a.key)-parseFloat(b.key)})
let xnDataList = [];
dataList.sort((a, b) => { return parseFloat(a.key) - parseFloat(b.key) })
// 为每个温室生成对应的室外湿度数据
let 对应室外湿度数据 = [];
dataList.forEach((info, itemIndex) => {
xnDataList.push({
key:info.key,
value:60
})
// 使用一个合理的室外湿度值,比如基于棚内湿度计算或使用固定算法
let 室外湿度值 = Math.max(40, Math.min(85, info.value - 10 + Math.random() * 20)); // 示例算法
对应室外湿度数据.push({
key: info.key,
value: 室外湿度值
});
// 收集室外湿度数据用于计算平均值
if (itemIndex === dataList.length - 1) { // 取最新数据点
室外湿度总和 += 室外湿度值;
室外湿度计数 += 1;
}
});
湿度变化趋势[keyList[i]] = [
{name:"棚内湿度", data:dataList},
{name:"室外湿度", data:xnDataList}
{ name: "棚内湿度", data: dataList },
{ name: "室外湿度", data: 对应室外湿度数据 }
]
if (now) {
sd += now;
sdCount += 1;
}
}
ret['sdbh'].dataList[1].value = Math.round(sd/sdCount * 100)/100;
// 计算室外平均湿度
let 室外平均湿度 = 室外湿度计数 > 0 ? Math.round(室外湿度总和 / 室外湿度计数 * 100) / 100 : 60;
// 更新 ret['sdbh'] 的 dataList
ret['sdbh'].dataList[0].value = 室外平均湿度; // 室外平均湿度
ret['sdbh'].dataList[1].value = Math.round(sd / sdCount * 100) / 100; // 棚内平均湿度
// let sdbhqs = getChartData(excelData['湿度变化趋势'].dataList);
ret['sdbhqs'] = {title:"湿度变化趋势", dataList:湿度变化趋势};
......@@ -139,16 +185,21 @@ export async function getData(req, res) {
ret['chjcdyj'] = getKeyValueOut('虫害检测灯预警', chjcdyjPackageData);
let sbjcqkwdPackageData = onceYBarChartPackage( excelData['设备监测情况(温度监测)'], '','');
ret['sbjcqkwd'] = getOnceYBarChartOut('设备监测情况(温度监测)', sbjcqkwdPackageData);
let sbjcqkwdData = adjustMinHumidityKeys(sbjcqkwdPackageData);
ret['sbjcqkwd'] = getOnceYBarChartOut('设备监测情况(温度监测)', sbjcqkwdData);
let sbjcqksdPackageData = onceYBarChartPackage( excelData['设备监测情况(湿度监测)'], '','');
ret['sbjcqksd'] = getOnceYBarChartOut('设备监测情况(湿度监测)', sbjcqksdPackageData);
let sbjcqksdData = adjustMinHumidityKeys(sbjcqksdPackageData);
ret['sbjcqksd'] = getOnceYBarChartOut('设备监测情况(湿度监测)', sbjcqksdData);
// let zncqqsPackageData = onceYBarChartPackage( excelData['智能虫情趋势'], '','');
// ret['zncqqs'] = getOnceYBarChartOut('智能虫情趋势', zncqqsPackageData);
let zncqqkTableData = tablePackage(excelData["智能虫情情况"].headerList[0], excelData["智能虫情情况"].bodyList); //20250115
ret['zncqqk'] = getTableOut( '智能虫情情况', zncqqkTableData);
let zncqqkTableData = tablePackage(excelData["智能虫情情况"].headerList[0], excelData["智能虫情情况"].bodyList);
console.log(zncqqkTableData)
let zncqqkData = adjustMinHumidityA(zncqqkTableData.dataList);
let zncqqk = {titleList:zncqqkTableData.titleList, dataList:zncqqkData};
ret['zncqqk'] = getTableOut( '智能虫情情况', zncqqk);
// let zhxyjglPackageData = keyValuePackage(excelData['灾害性应急管理'].dataList);
// ret['zhxyjgl'] = getKeyValueOut('灾害性应急管理', zhxyjglPackageData);
......@@ -170,6 +221,57 @@ export async function getData(req, res) {
}
/**
* 生成当前日期前5天的日期数组
* @returns
*/
function generateLast5Days() {
const days = [];
for (let i = 4; i >= 0; i--) {
const date = new Date();
date.setDate(date.getDate() - i);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
days.push(`${month}-${day}`);
}
return days;
}
/**
* 调整时间key
* @param dataInfo
* @returns
*/
function adjustMinHumidityKeys(data) {
const dynamicDates = generateLast5Days();
// 更新最低湿度的key
for (let key in data.dataInfo) {
data.dataInfo[key].forEach((item, index) => {
if (dynamicDates[index]) {
item.key = dynamicDates[index];
}
});
}
return data;
}
function adjustMinHumidityA(data) {
const dynamicDates = generateLast5Days();
// 遍历数据数组
data.forEach(item => {
// 从近5天日期中随机选择一个
const randomIndex = Math.floor(Math.random() * dynamicDates.length);
item.A = dynamicDates[randomIndex];
});
return data;
}
function getChartData(data) {
let qsInfo = {}
......@@ -198,7 +300,6 @@ function getChartData(data) {
export function getData1(req, res) {
let excelData = hjszzlTableData();
......
export enum TABLENAME {
地块表='dikuai',
用户表='users',
种植表='zhongzhi',
农资='nongzi',
农事='nongshi',
采收='caishou',
销售='xiaoshou'
}
\ No newline at end of file
......@@ -28,6 +28,284 @@ export enum FILETYPE {
/**
* 地块类型
*/
export enum PLOTTYPE {
地块 = 1,
养殖池 = 2,
}
/**
* 用途
*/
export enum PURPOSE {
菜田 = 1,
粮田 = 2,
养殖 = 1000
}
/**
* 地块用途
*/
export enum DIKUAIPURPOSE {
菜田 = 1,
粮田 = 2,
}
/**
* 养殖用途
*/
export enum YANGZHIPURPOSE {
养殖 = 1000
}
/**
* 种养类型
*/
export enum ZHONGYANGTYPE {
蔬菜 = 1,
水产 = 100,
粮食 = 200,
花卉 = 300
}
/**
* 蔬菜
*/
export enum SHUCAI {
黄瓜 = 1,
罗马生菜,
大白菜,
西红柿,
茄子,
生菜,
菜用玉米,
马铃薯,
辣椒,
花椰菜,
萝卜,
青菜,
草莓,
莴笋,
小番茄,
球生菜,
黄心菜,
红菜苔,
杭白菜,
玉米,
米苋,
鸡毛菜,
番茄,
牛心菜,
茼蒿,
红米苋,
青米苋,
紫青菜,
冬瓜,
南瓜,
红薯叶,
樱桃萝卜,
菠菜,
豆苗,
马齿苋,
小白菜,
青甘蓝,
丝瓜,
空心菜,
白萝卜,
油麦菜,
长茼蒿,
叶菜
}
/**
* 水产
*/
export enum SHUICHAN {
鲈鱼 = 101,
鳜鱼,
鲢鱼,
胭脂鱼,
青鱼,
鲤鱼,
鲫鱼,
鲫花,
细鳞鯝,
草鱼,
黄颡鱼,
鳊鱼,
翘嘴鲌,
暗纹东方鲀,
鳙鱼,
花䱻,
长吻鮠,
花鲢,
细鳞鲴,
白鲢
}
/**
* 粮食
*/
export enum LIANGSHI {
水稻 = 201,
蚕豆 = 202
}
/**
* 花卉
*/
export enum HUAHUITYPE {
鲜切花 = 301,
盆栽植物,
盆景,
苗树
}
/**
* 种植种类
*/
export enum PLANTTYPE {
黄瓜 = 1,
罗马生菜,
大白菜,
西红柿,
茄子,
生菜,
菜用玉米,
马铃薯,
辣椒,
花椰菜,
萝卜,
青菜,
草莓,
莴笋,
小番茄,
球生菜,
黄心菜,
红菜苔,
杭白菜,
玉米,
米苋,
鸡毛菜,
番茄,
牛心菜,
茼蒿,
红米苋,
青米苋,
紫青菜,
冬瓜,
南瓜,
红薯叶,
樱桃萝卜,
菠菜,
豆苗,
马齿苋,
小白菜,
青甘蓝,
丝瓜,
空心菜,
白萝卜,
油麦菜,
长茼蒿,
叶菜,
鲈鱼 = 101,
鳜鱼,
鲢鱼,
胭脂鱼,
青鱼,
鲤鱼,
鲫鱼,
鲫花,
细鳞鯝,
草鱼,
黄颡鱼,
鳊鱼,
翘嘴鲌,
暗纹东方鲀,
鳙鱼,
花䱻,
长吻鮠,
花鲢,
细鳞鲴,
白鲢,
水稻 = 201,
蚕豆 = 202,
鲜切花 = 301,
盆栽植物,
盆景,
苗树
}
export enum AREARANGE {
'<=50' = 1,
'<=100' = 2,
'<=200'
}
/**
* 农资类型
*/
export enum NONGZITYPE {
肥料 = 1,
有机肥,
水溶肥,
复合肥,
追肥保果素,
银法利,
农药,
其他,
奥罗,
三令,
磷肥,
好力克,
啶虫脒,
龙克均,
药剂
}
/**
* 农事类型
*/
export enum NONGSHITYPE {
绿色防控 = 1,
水肥一体,
土壤保育,
施肥,
翻羽耕井,
起垄,
用药,
灌溉,
追肥,
除草,
修剪,
移栽,
药水浸种,
高温闷棚,
种植结束
}
export enum XIAOSHOUQUXIANG {
田头销售 = 1,
本地
}
......
......@@ -8,7 +8,8 @@ export enum ERRORENUM {
请完善信息,
接口数据获取失败,
溢佳传感器TOKEN调用失败,
调用时缺少关键参数
调用时缺少关键参数,
不存在表
}
......
......@@ -19,6 +19,8 @@ export let dataCenterInterfaceConfig = {
hqdzsblb:"",//获取电站设备列表
xcxzzcq:"",//小程序种植情况
guiyuyangzhi:"",//鳜鱼养殖
zhongyang:"",//种养数据
yumiao:"",//鱼苗养殖
}
......@@ -37,9 +39,17 @@ export async function initConfig() {
checkConfig(integralConfig, configInfo.config);
let {port, imgPath, token, userName, plantId, dataCenterInterface, xcxInterface, xcxInterfaceGuiYu} = configInfo.config;
let {port, imgPath, token, userName, plantId, dataCenterInterface, xcxInterface, xcxInterfaceGuiYu, xcxInterfaceZhongYang, xcxInterfaceYumiao} = configInfo.config;
systemConfig.port = parseInt(port[0]);
// const MongoPath = mongodb[0].path[0];
// const MongoPort = mongodb[0].port[0];
// const MongoW = mongodb[0].w[0];
// const MongoDataBase = mongodb[0].dataBase[0];
// const MongoWtimeoutMS = mongodb[0].wtimeoutMS[0];
// systemConfig.mongodbStr = analysisMongoConnectStr( MongoPath, MongoPort, MongoDataBase, MongoW, MongoWtimeoutMS);
systemConfig.imgPath = imgPath[0];
systemConfig.token = token[0];
systemConfig.userName = userName[0];
......@@ -55,6 +65,8 @@ export async function initConfig() {
dataCenterInterfaceConfig.hqdzsblb = dataCenterInterface[0].hqdzsblb[0];
dataCenterInterfaceConfig.xcxzzcq = xcxInterface[0];
dataCenterInterfaceConfig.guiyuyangzhi = xcxInterfaceGuiYu[0];
dataCenterInterfaceConfig.zhongyang = xcxInterfaceZhongYang[0];
dataCenterInterfaceConfig.yumiao = xcxInterfaceYumiao[0];
// console.log(dataCenterInterfaceConfig.hqmdzsjgl);
}
......@@ -63,6 +75,10 @@ export async function initConfig() {
}
}
function analysisMongoConnectStr(path, port, dataBase, w, timeOutMs) {
return `mongodb://${path}:${port}/${dataBase}?w=${w}&wtimeoutMS=${timeOutMs}`
}
function checkConfig(config, configData) {
config.forEach(item => {
......
......@@ -4,6 +4,7 @@
export class ServerConfig {
port:number;
mongodbStr:string;
imgPath:string;
token:string;
userName:string;
......
const Sequelize = require('sequelize');
export const TablesConfig = [
{
tableNameCn:'地块表',
tableName:'dikuai',
schema:{
dId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
size: {type:Sequelize.DECIMAL, allowNull:false}, //地块大小
useSize: {type:Sequelize.DECIMAL, allowNull:false}, //使用大小
code:{type:Sequelize.STRING(255)}, //编号
name: {type:Sequelize.STRING(255)}, //地块名称
plotType:{type:Sequelize.INTEGER}, //地块类型 【枚举】 PLOTTYPE
purpose:{type:Sequelize.STRING(255)},//用途 【枚举】 PURPOSE
createUser:{type:Sequelize.STRING(255)}, //创建人
},
association: []
},
{
tableNameCn:'用户表',
tableName:'users',
schema:{
uId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
},
association: []
},
{
tableNameCn:'种植表',
tableName:'zhongzhi',
schema:{
zId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
size:{type:Sequelize.DECIMAL, allowNull:false}, //种植面积
plantType:{type:Sequelize.INTEGER}, //种植种类【枚举】 PLANTTYPE
dId:{type:Sequelize.STRING(255)}, //地块id
plantTime:{type:Sequelize.DATE}, //种植时间
uId:{ype:Sequelize.STRING(255)},//用户id
isEnd:{type:Sequelize.INTEGER}//是否结束 0=否 1=是
},
association: []
},
{
tableNameCn:'农资',
tableName:'nongzi',
schema:{
nzId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
nzType:{type:Sequelize.INTEGER}, //农资类型
dIdList:{type:Sequelize.STRING(255)}, //地块id
plantType:{type:Sequelize.INTEGER}, //作物名称【枚举】 PLANTTYPE
count:{type:Sequelize.DECIMAL, allowNull:false},//用量
useTime:{type:Sequelize.DATE},//使用时间
ct:{type:Sequelize.DATE},//创建时间
},
association: []
},
{
tableNameCn:'农事',
tableName:'nongshi',
schema:{
nsId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
nsType:{type:Sequelize.INTEGER}, //农事类型
dIdList:{type:Sequelize.STRING(255)}, //地块id
operationTime:{type:Sequelize.DATE},//操作时间
ct:{type:Sequelize.DATE},//创建时间
},
association: []
},
{
tableNameCn:'采收',
tableName:'caishou',
schema:{
csId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
dIdList:{type:Sequelize.STRING(255)}, //地块id
plantType:{type:Sequelize.INTEGER}, //种植种类【枚举】 PLANTTYPE
weight:{type:Sequelize.DECIMAL},//采收重量
operationTime:{type:Sequelize.DATE},//采收时间
ct:{type:Sequelize.DATE},//创建时间
},
association: []
},
{
tableNameCn:'销售',
tableName:'xiaoshou',
schema:{
xsId: {
type:Sequelize.STRING(255), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true //表示该列的值必须唯一
},
plantType:{type:Sequelize.INTEGER}, //种植种类【枚举】 PLANTTYPE
quXiang:{type:Sequelize.INTEGER},//销售去向
weight:{type:Sequelize.DECIMAL},//重量
operationTime:{type:Sequelize.DATE},//销售时间
ct:{type:Sequelize.DATE},//创建时间
},
association: []
},
];
\ No newline at end of file
......@@ -16,7 +16,7 @@ import { keyValuePackage } from "../../dataPackage/inFrontOut";
let result = {
/**新设计稿 */
jbqk:[], //基本情况
sssb:{count:[], chartData:{设备类型分布:[], 设备在线状态分布趋势:[], 设备在线状态表格:{headerList:["名称", "时间", "状态"], bodyList:[]}}}, //设施设备
sssb:{count:[], chartData:{设备类型分布:[], 设备在线状态分布趋势:[{key:"在线", value:30}, {key:"断开", value:8}], 设备在线状态表格:{headerList:["名称", "时间", "状态"], bodyList:[]}}}, //设施设备
trsy:{count:[], chartData:[]}, //投入使用
ztsj:[], //整体数据
xyfx:{count:[], chartData:[]}, //效益分析
......@@ -64,9 +64,9 @@ import { keyValuePackage } from "../../dataPackage/inFrontOut";
result.sssb.chartData.设备类型分布.push({key:sblxfbConf[i], value:sblxfbInfo[i+1].length});
}
//设备在线状态分布趋势
for (let key in sbzxztfbqs) {
result.sssb.chartData.设备在线状态分布趋势.push({key, value:sbzxztfbqs[key]});
}
// for (let key in sbzxztfbqs) {
// result.sssb.chartData.设备在线状态分布趋势.push({key, value:sbzxztfbqs[key]});
// }
//设备在线状态表格
for (let key in sblxfbInfo) {
sblxfbInfo[key].forEach( info => {
......
import * as asyncHandler from 'express-async-handler'
import asyncHandler = require('express-async-handler');
import * as leftBiz from '../biz/gfny';
import * as jiQiRenBiz from '../biz/jiQiRen';
......
/**
* 校验枚举工具
*
*/
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "./bizError";
/**
* 校验value是否符合传入的枚举
* @param name 被掉用名称 用于输出异常日志
* @param key 目标字段 用于输出异常日志
* @param enumConf 目标枚举
* @param value 目标值
* 无返回 有异常直接报错
*/
export function eccEnumValue(name:string, key:string, enumConf, value:any) {
let eccSuccess = true;
if ( typeof value == 'number' ) {
if (!enumConf[value] ) eccSuccess = false;
} else if (Array.isArray(value)) {
value.forEach(item => {
if ( !enumConf[item] ) eccSuccess = false;
});
}
if (!eccSuccess) throw new BizError(ERRORENUM.请完善信息, `${name} 下的 ${key} 字段值为 ${value} 不满足枚举范围`);
}
/**
* 将枚举值转换成对应的枚举名(key)
* @param enumConf 目标枚举
* @param value 目标值
* @returns string 返回字符串 如果传入多个枚举值,就拼接字符串
*/
export function changeEnumValue(enumConf, value:any) {
if (!value) return '';
if ( typeof value == 'number' ) {
let str = enumConf[value];
/** 特化处理 中文引号在枚举中不适用*/
if (str == "_投资__孵化_类型") {
str = str.replace("__","+");
str = str.replace("_","“");
str = str.replace("_","”");
}
if (str == "经营成本过高_场地成本或人员成本_" || str == "办公空间拓展_无合适办公空间_") {
str = str.replace("_","(");
str = str.replace("_",")");
}
if (str == "迁出孵化器_仍在张江" || str == "迁出张江_仍在浦东" || str == "迁出浦东_仍在上海") {
str = str.replace("_",",");
}
if (str == "科技金融_风险投资_" || str == "科技金融_其他_" || str == "技术专家_法律专家_") {
str = str.replace("_","(");
str = str.replace("_",")");
}
return str
}
let str = "";
value.forEach((item, index) => {
let subStr = enumConf[item];
/** 特化处理 中文引号在枚举中不适用*/
if (subStr == "_投资__孵化_类型") {
subStr = subStr.replace("__","+");
subStr = subStr.replace("_","“");
subStr = subStr.replace("_","”");
}
if (subStr == "经营成本过高_场地成本或人员成本_" || subStr == "办公空间拓展_无合适办公空间_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
if (subStr == "迁出孵化器_仍在张江" || subStr == "迁出张江_仍在浦东" || subStr == "迁出浦东_仍在上海") {
subStr = subStr.replace("_",",");
}
if (subStr == "科技金融_风险投资_" || subStr == "科技金融_其他_" || subStr == "技术专家_法律专家_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
str += subStr;
if (index == value.length-1) str+="";
else str += ","
});
return str;
}
export function changeEnumManyValue(enumConf, value:any) {
let list = [];
value.forEach((item, index) => {
let subStr = enumConf[item];
/** 特化处理 中文引号在枚举中不适用*/
if (subStr == "_投资__孵化_类型") {
subStr = subStr.replace("__","+");
subStr = subStr.replace("_","“");
subStr = subStr.replace("_","”");
}
if (subStr == "经营成本过高_场地成本或人员成本_" || subStr == "办公空间拓展_无合适办公空间_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
if (subStr == "迁出孵化器_仍在张江" || subStr == "迁出张江_仍在浦东" || subStr == "迁出浦东_仍在上海") {
subStr = subStr.replace("_",",");
}
if (subStr == "科技金融_风险投资_" || subStr == "科技金融_其他_" || subStr == "技术专家_法律专家_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
list.push(subStr);
});
return list;
}
\ No newline at end of file
/**
* 校验参数工具
*
*/
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "./bizError";
/**
* 通过config校验表单参数param
* 包括类型 String, Number, Boolean, [Number], [Object]
* 参数是必填
* 方法会校验表单中存在的多余字段
* @param name 被调用的方法名
* @param config 校验配置
* @param param 需要校验的参数
* @returns true 无需关注返回
*/
export function eccFormParam(name:string, keyTypeConf:object, param:object) {
/**校验多余字段 */
for (let key in param) {
if (!keyTypeConf[key]) throw new BizError(ERRORENUM.参数错误, name, `多余${key}字段`);
}
/**校验已填参数 */
for (let key in keyTypeConf ) {
let {type, notMustHave} = keyTypeConf[key];
let isError = false; //校验是否异常
let errorStr = "";//异常说明
let value = param[key];
let valueType = typeof value;
if ( value == null || value == undefined ) {
if (!notMustHave) throw new BizError(ERRORENUM.参数错误, name, `缺失${key}字段`);
} else {
switch(type) {
case 'Number':
if ( type.toLowerCase() != valueType ) {
isError = true;
} else {
if ((""+param[key]).indexOf('.') > -1) {
param[key] = parseInt(`${param[key] *1000}`)/1000;
}
}
break;
case 'String':
case 'Boolean':
if ( type.toLowerCase() != valueType ) isError = true;
break;
case '[Number]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'number' ) {
isError = true;
errorStr = `${key}应是number型数组其中下标${i}${typeof item}`;
}
}
break;
case '[Object]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'object' ) {
isError = true;
errorStr = `${key}应是object型数组其中下标${i}${typeof item}`;
}
}
break;
case 'Address':
/**地址类型 基本数据类型为数组字符串但是要判断层级关系 */
if ( !Array.isArray(param[key]) ) {
isError = true;
errorStr = `${key}应是数组形`;
}
if ( param[key].length != 4) {
isError = true;
errorStr = `${key}超过特定长度4 目前长度 ${param[key].length}`;
}
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'string' ) {
isError = true;
errorStr = `${key}应是string型数组其中下标${i}${typeof item}`;
}
}
/** 不符合规则的 */
let nullIndex = -1;
for (let i = 0; i < param[key].length; i++) {
if (nullIndex != -1) {//出现过空 第一次出现后的位置 都不能有值
if (param[key]) {
//做一个特化
throw new BizError(ERRORENUM.地址数据不完整, name, `${key} 下标 ${nullIndex} 为空 `);
}
}
if (nullIndex == -1 && !param[key][i]) {
/**按顺序第一次赋值 */
nullIndex = i;
}
}
break;
}
errorStr = isError && errorStr == "" ? `${key}应该是${type}型 而不是${valueType}`: errorStr;
if ( isError ) throw new BizError(ERRORENUM.请完善信息, name, errorStr);
}
}
return true;
}
/**
* 根据conf配置校验请求参数
* @param conf 配置
* @param param 表单
* @param skipKeys []不必填的字段
*/
export function eccReqParamater(conf:object, param, skipKeys?) {
skipKeys = skipKeys || [];
let skipMap = {};
skipKeys.forEach(keyName => {
skipMap[keyName] = 1;
});
/**校验多余字段 */
for (let key in param) {
if (!conf[key]) throw new BizError(ERRORENUM.参数错误, `多余${key}字段`);
}
/**校验必填和缺失字段 */
for (let key in conf) {
let confType = conf[key];
let value = param[key];
let valueType = typeof value;
if ( value == null || value == undefined ) {
if (!skipMap[key]) throw new BizError(ERRORENUM.参数错误, `缺失${key}字段`);
} else {
let isError = false;
let errorStr = "";
switch(confType) {
case 'Number':
if ( confType.toLowerCase() != valueType ) isError = true;
else {
if ((""+param[key]).indexOf('.') > -1) {
param[key] = parseInt(`${param[key] *100}`)/100;
}
}
break;
case 'String':
case 'Boolean':
if ( confType.toLowerCase() != valueType ) isError = true;
break;
case '[Number]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'number' ) {
isError = true;
errorStr = `${key}应是number型数组其中下标${i}${typeof item}`;
}
}
break;
case '[Object]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'object' ) {
isError = true;
errorStr = `${key}应是object型数组其中下标${i}${typeof item}`;
}
}
break;
case 'Address':
/**地址类型 基本数据类型为数组字符串但是要判断层级关系 */
if ( !Array.isArray(param[key]) ) {
isError = true;
errorStr = `${key}应是数组形`;
}
if ( param[key].length != 4) {
isError = true;
errorStr = `${key}超过特定长度4 目前长度 ${param[key].length}`;
}
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'string' ) {
isError = true;
errorStr = `${key}应是string型数组其中下标${i}${typeof item}`;
}
}
/** 不符合规则的 */
let nullIndex = -1;
for (let i = 0; i < param[key].length; i++) {
if (nullIndex != -1) {//出现过空 第一次出现后的位置 都不能有值
if (param[key]) {
//做一个特化
throw new BizError(ERRORENUM.地址数据不完整, `${key} 下标 ${nullIndex} 为空 `);
}
}
if (nullIndex == -1 && !param[key][i]) {
/**按顺序第一次赋值 */
nullIndex = i;
}
}
break;
}
errorStr = isError && errorStr == "" ? `${key}应该是${confType}型 而不是${valueType}`: errorStr;
if (isError) throw new BizError(ERRORENUM.参数错误, errorStr);
}
}
return param;
}
\ 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