Commit 29377e3c by chenjinjing

no message

parents
.idea
/out
/node_modules
/test
/public
/logs
/video
/files
/img
*test*
*.logs
*.zip
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"program": "${workspaceFolder}/src/main.ts",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
}
]
}
\ No newline at end of file
{
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "screen",
"version": "1.0.0",
"description": "",
"main": "main.ts",
"dependencies": {
"@alicloud/sms-sdk": "^1.1.6",
"@types/node": "^10.12.18",
"axios": "^1.13.6",
"compression": "^1.7.4",
"express": "^4.17.1",
"express-async-handler": "^1.1.4",
"express-history-api-fallback": "^2.2.1",
"formidable": "^1.2.1",
"install": "^0.13.0",
"log4js": "^6.6.1",
"lru-cache": "^4.1.5",
"md5": "^2.2.1",
"moment": "^2.24.0",
"mongoose": "^5.4.0",
"mysql": "^2.18.1",
"node-xlsx": "^0.16.1",
"nodemailer": "^6.1.1",
"officegen": "^0.6.5",
"pyfl": "^1.1.4",
"qs": "^6.11.0",
"request": "^2.88.0",
"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": "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.
<config>
<port>40019</port>
<!-- <imgIp>http://172.16.3.98:40019</imgIp> -->
<imgIp>http://192.168.0.71:40019</imgIp>
<!-- <imgIp>https://map.shatim.com.cn:40019</imgIp> 正式环境 -->
<!-- <imgIp>http://tim.shatim.com.cn:8081</imgIp> 测试环境 -->
<ledger>
<ywyfledger>http://114.94.20.112:81/spa/cube/index.html#/main/cube/search?customid=841</ywyfledger>
<srledger>http://114.94.20.112:81/spa/cube/index.html#/main/cube/search?customid=899</srledger>
</ledger>
<TIM>
<resourceAnalyse>https://terminal.hqterminal.com/api/bussiness/floor/resource/analyse</resourceAnalyse>
<terminalInfo>https://terminal.hqterminal.com/api/bussiness/terminal/info</terminalInfo>
<roomInfo>https://terminal.hqterminal.com/api/bussiness/room/room/info</roomInfo>
</TIM>
<TIM2>
<!-- 首页 -->
<homepage>http://114.94.20.112:81/api/bussiness/analyse/homepage</homepage>
<!-- 业务用房 -->
<rolesList>http://114.94.20.112:81/api/bussiness/analyse/roles/list</rolesList>
<rolesEdit>http://114.94.20.112:81/api/bussiness/analyse/roles/edit</rolesEdit>
<total>http://114.94.20.112:81/api/bussiness/analyse/total</total>
<analyse>http://114.94.20.112:81/api/bussiness/analyse/analyse</analyse>
<terminal>http://114.94.20.112:81/api/bussiness/analyse/terminal</terminal>
<room>http://114.94.20.112:81/api/bussiness/analyse/room</room>
</TIM2>
<zy>
<total>http://114.94.20.112:81/api/seat/analyse/total</total>
<terminal>http://114.94.20.112:81/api/seat/analyse/terminal</terminal>
<floor>http://114.94.20.112:81/api/seat/analyse/floor</floor>
<seat>http://114.94.20.112:81/api/seat/analyse/seat</seat>
</zy>
<bzbs>
<total>http://114.94.20.112:81/api/sign/analyse/total</total>
<terminal>http://114.94.20.112:81/api/sign/analyse/terminal</terminal>
<floor>http://114.94.20.112:81/api/sign/analyse/floor</floor>
<sign>http://114.94.20.112:81/api/sign/analyse/sign</sign>
</bzbs>
</config>
<config>
<config>
<port>40019</port>
<!-- <imgIp>http://172.16.3.98:40019</imgIp> -->
<!-- <imgIp>http://192.168.0.71:40019</imgIp> -->
<imgIp>https://map.shatim.com.cn:40019</imgIp> 正式环境
<!-- <imgIp>http://tim.shatim.com.cn:8081</imgIp> 测试环境 -->
<ledger>
<ywyfledger>https://tim.shatim.com.cn/spa/cube/index.html#/main/cube/search?customid=841&amp;_key=cfiju7</ywyfledger>
<srledger>https://tim.shatim.com.cn/spa/cube/index.html#/main/cube/search?customid=899&amp;_key=jzqwlk</srledger>
</ledger>
<TIM>
<resourceAnalyse>https://terminal.hqterminal.com/api/bussiness/floor/resource/analyse</resourceAnalyse>
<terminalInfo>https://terminal.hqterminal.com/api/bussiness/terminal/info</terminalInfo>
<roomInfo>https://terminal.hqterminal.com/api/bussiness/room/room/info</roomInfo>
</TIM>
<TIM2>
<!-- 首页 -->
<homepage>https://tim.shatim.com.cn/api/bussiness/analyse/homepage</homepage>
<!-- 当前用户角色列表 -->
<rolesList>https://tim.shatim.com.cn/api/bussiness/analyse/roles/list</rolesList>
<!-- 当前用户角色编辑 -->
<rolesEdit>https://tim.shatim.com.cn/api/bussiness/analyse/roles/edit</rolesEdit>
<!-- 全部业务用房 -->
<total>https://tim.shatim.com.cn/api/bussiness/analyse/total</total>
<!-- 业务用房楼层分析 -->
<analyse>https://tim.shatim.com.cn/api/bussiness/analyse/analyse</analyse>
<!-- 业务用房楼栋分析 -->
<terminal>https://tim.shatim.com.cn/api/bussiness/analyse/terminal</terminal>
<!-- 房间业务用房数据 -->
<room>https://tim.shatim.com.cn/api/bussiness/analyse/room</room>
</TIM2>
<zy>
<total>https://tim.shatim.com.cn/api/seat/analyse/total</total>
<terminal>https://tim.shatim.com.cn/api/seat/analyse/terminal</terminal>
<floor>https://tim.shatim.com.cn/api/seat/analyse/floor</floor>
<seat>https://tim.shatim.com.cn/api/seat/analyse/seat</seat>
</zy>
<bzbs>
<total>https://tim.shatim.com.cn/api/sign/analyse/total</total>
<terminal>https://tim.shatim.com.cn/api/sign/analyse/terminal</terminal>
<floor>https://tim.shatim.com.cn/api/sign/analyse/floor</floor>
<sign>https://tim.shatim.com.cn/api/sign/analyse/sign</sign>
</bzbs>
</config>
import { systemConfig } from "../config/serverConfig";
import { roomPointDjTableData, roomPointT1TableData, roomPointT2TableData } from "../data/table/roomPoint";
import { get, post, postAxios, postParmiss } from "../util/request";
import { convertTIMDataToModelFormat } from "../dataPackage/tool";
let fs = require("fs");
let https = require('https');
let path = require('path');
/**
* 1、资源可视化楼层资源分析
* @param req
* @param res
*/
export async function getResourceAnalyse(req, res) {
let ret:any = {};
let {lc} = req.body;
console.log(lc);
let url = `${systemConfig.resourceAnalyse}?lc=${lc}`;
let resourceAnalyse = await postAxios(url, {}, {});
ret = resourceAnalyse.body;
res.send(ret);
}
/**
* 2、航站楼下拉选项
* @param req
* @param res
*/
export async function getTerminalInfo(req, res) {
let ret:any = {};
let {model} = req.body;
let url = `${systemConfig.terminalInfo}?model=${model}`;
let terminalInfo = await postAxios(url, {}, {});
ret['terminalInfo'] = terminalInfo.body;
res.send(ret);
}
/**
* 3、各房间信息
* @param req
* @param res
*/
export async function getRoomInfo(req, res) {
let ret:any = {};
let {fjh} = req.body;
let url = `${systemConfig.roomInfo}?fjh=${fjh}`;
let roomInfo = await postAxios(url, {}, {});
let imgurl = roomInfo.body.fj.img;
let imgName = await downloadImage(imgurl, path.join(__dirname.substring(0,__dirname.indexOf("out")), "img/downloads" )); // 下载到downloads目录
roomInfo.body.fj.img = `${systemConfig.imgIp}/downloads/${imgName}`;
ret['roomInfo'] = roomInfo.body;
res.send(ret);
}
function downloadImage(url, outputPath) {
const protocol = url.startsWith('https') ? https : require('http');
return new Promise((resolve, reject) => {
protocol.get(url, (response) => {
// 检查响应状态
if (response.statusCode !== 200) {
reject(new Error(`请求失败,状态码: ${response.statusCode}`));
return;
}
// 获取文件扩展名
const contentType = response.headers['content-type'];
let extension = '.jpg'; // 默认扩展名
if (contentType) {
if (contentType.includes('jpeg') || contentType.includes('jpg')) {
extension = '.jpg';
} else if (contentType.includes('png')) {
extension = '.png';
} else if (contentType.includes('gif')) {
extension = '.gif';
} else if (contentType.includes('webp')) {
extension = '.webp';
}
}
// 如果outputPath是目录,自动生成文件名
let finalPath = outputPath;
let finalName = "";
if (fs.existsSync(outputPath) && fs.lstatSync(outputPath).isDirectory()) {
const filename = `image_${Date.now()}${extension}`;
finalName = filename;
finalPath = path.join(outputPath, filename);
}
// 创建可写流
const fileStream = fs.createWriteStream(finalPath);
// 管道传输数据
response.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close();
console.log(`图片已下载: ${finalPath}`);
resolve(finalName);
});
fileStream.on('error', (err) => {
fs.unlink(finalName, () => {}); // 删除不完整的文件
reject(err);
});
}).on('error', (err) => {
reject(err);
});
});
}
export async function getRoomPoint(req, res) {
let ret = {};
let excelT1Data = roomPointT1TableData();
let excelT2Data = roomPointT2TableData();
let excelDjData = roomPointDjTableData();
let TIMData = {
"T1": excelT1Data["T1"],
"T2": excelT2Data["T2"],
"Dj": excelDjData["东郊"]
}
/**
* imgName:配置图片名称
* floorName:表格对应楼层名称
* displayName:页面显示楼层名称
* altitude:米数
*/
const configs = {
'T1': [
{ imgName: 'dxs', floorName: 'B1半地下室', displayName: 'B1', altitude: '(-8.85M)', includeEmpty: true },
{ imgName: 'F1', floorName: '1F', displayName: '1F', altitude: '(0.0M)', includeEmpty: true },
{ imgName: 'F2', floorName: '2F', displayName: '2F', altitude: '(5.4M)', includeEmpty: true },
{ imgName: 'F3', floorName: '3F', displayName: '3F', altitude: '(10.9M)', includeEmpty: true },
{ imgName: 'F4', floorName: '4F', displayName: '4F', altitude: '(16.4M)', includeEmpty: true },
// { imgName: 'B1', floorName: 'B1', displayName: 'B1', altitude: '', includeEmpty: true },
// { imgName: 'B1', floorName: 'B1', displayName: 'B1', altitude: '(-8.85M)', includeEmpty: true }
],
'T2': [
{ imgName: 'B1', floorName: 'B1', displayName: 'B1', altitude: '(-7.95M)', includeEmpty: true },
{ imgName: 'F1', floorName: '1F', displayName: '1F', altitude: '(0.0M)', includeEmpty: true },
{ imgName: 'F2', floorName: '2F', displayName: '2F', altitude: '(4.2M)', includeEmpty: true },
{ imgName: 'M2', floorName: 'M2', displayName: 'M2', altitude: '(8.55M)', includeEmpty: true },
{ imgName: 'F3-1', floorName: '3F-1', displayName: '3F-1', altitude: '(12.15M)', includeEmpty: true },
{ imgName: 'F3-2', floorName: '3F-2', displayName: '3F-2', altitude: '(13.55M)', includeEmpty: true },
{ imgName: 'M3', floorName: 'M3', displayName: 'M3', altitude: '(17.15M)', includeEmpty: true },
{ imgName: 'F4', floorName: '4F', displayName: '4F', altitude: '(21.65M)', includeEmpty: true },
{ imgName: 'F5', floorName: '5F', displayName: '5F', altitude: '(24.65M)', includeEmpty: true },
{ imgName: 'F6', floorName: '6F', displayName: '6F', altitude: '(28.65M)', includeEmpty: true },
{ imgName: 'F7', floorName: '7F', displayName: '7F', altitude: '(32.65M)', includeEmpty: true },
{ imgName: 'F8', floorName: '8F', displayName: '8F', altitude: '(36.65M)', includeEmpty: true }
],
'Dj': [
{ imgName: 'B1', floorName: 'B1', displayName: 'B1', altitude: '(-7.95M)', includeEmpty: true },
// { imgName: 'F1-1', floorName: 'F1-1', displayName: 'F1-1', altitude: '', includeEmpty: true },
// { imgName: 'F1-2', floorName: 'F1-2', displayName: 'F1-2', altitude: '', includeEmpty: true },
// { imgName: 'F2', floorName: 'F2', displayName: 'F2', altitude: '', includeEmpty: true },
// { imgName: 'F2-1', floorName: 'F2-1', displayName: 'F2-1', altitude: '', includeEmpty: true },
{ imgName: 'F3', floorName: '3F', displayName: '3F', altitude: '(12.15M)', includeEmpty: true },
// { imgName: 'F4', floorName: '4F', displayName: '4F', altitude: '(19.05M)', includeEmpty: true },
{ imgName: 'F5', floorName: '5F', displayName: '5F', altitude: '(24.15M)', includeEmpty: true },
{ imgName: 'F6', floorName: '6F', displayName: '6F', altitude: '(29.25M)', includeEmpty: true },
{ imgName: 'F7', floorName: '7F', displayName: '7F', altitude: '(34.2M)', includeEmpty: true }
]
};
// 转换TIMData为model格式
let modelTabs = convertTIMDataToModelFormat(TIMData, "room", configs);
// ret['TIMData'] = TIMData;
ret['modelTabs'] = modelTabs;
res.send(ret);
}
import * as enumConfig from "../config/enum";
import { systemConfig } from "../config/serverConfig";
import { seatPointDjTableData, seatPointT1TableData, seatPointT2TableData } from "../data/table/roomPoint";
import { changeEnumNameByCode, changeEnumValue } from "../tools/eccEnum";
import { postAxios, postJsonAxios } from "../util/request";
/**
* 台账地址返回
* @param req
* @param res
*/
export async function ledgerUrl(req, res) {
let ret:any = {};
let ywyf = systemConfig.ywyfledger;
let sr = systemConfig.srledger;
ret = {
ywyfLedger: ywyf,
srLedger: sr
};
res.send(ret);
}
/**
* 1、当前用户角色列表
* @param req
* @param res
*/
export async function getRolesList(req, res) {
let ret:any = {};
let {yh} = req.body;
console.log(yh);
let url = `${systemConfig.rolesList}?yh=${yh}`;
let rolesList = await postAxios(url, {}, {});
console.log(JSON.stringify(rolesList));
ret = rolesList.body;
console.log(JSON.stringify(ret));
res.send(ret);
}
/**
* 2、当前用户角色编辑
* @param req
* @param res
*/
export async function getRolesEdit(req, res) {
let ret:any = {};
let {userid, role, permissions, module} = req.body;
let url = `${systemConfig.rolesEdit}`;
let query = { userid, role, permissions, module };
let rolesList = await postJsonAxios(url, query, {});
ret = rolesList.body;
res.send(ret);
}
/**
* 3、全部业务用房
* @param req
* @param res
*/
export async function getTotal(req, res) {
let ret:any = {};
let url = `${systemConfig.total}`;
let totalInfo = await postAxios(url, {}, {});
ret = totalInfo.body;
res.send(ret);
}
/**
* 4、业务用房楼栋分析
* @param req
* @param res
*/
export async function getTerminal(req, res) {
let ret:any = {};
let {ld} = req.body;
let url = `${systemConfig.terminal}?ld=${ld}`;
let terminalInfo = await postAxios(url, {}, {});
ret = terminalInfo.body;
res.send(ret);
}
/**
* 5、业务用房楼层分析
* @param req
* @param res
*/
export async function getAnalyse(req, res) {
let ret:any = {};
let {ld, lc} = req.body;
let ldStr = ld;
if (ld == "东交") ldStr = "DJ";
let lcStr = enumConfig[`${ldStr}_ywyf`][lc];
let url = `${systemConfig.analyse}?ld=${ld}&lc=${lcStr}`;
let analyseInfo = await postAxios(url, {}, {});
ret = analyseInfo.body;
res.send(ret);
}
/**
* 6、房间业务用房数据
* @param req
* @param res
*/
export async function getRoom(req, res) {
let ret:any = {};
let {fj} = req.body;
let url = `${systemConfig.room}?fj=${fj}`;
let roomInfo = await postAxios(url, {}, {});
ret = roomInfo.body;
res.send(ret);
}
/**
* 辅助函数:对 fjzy 数组按枚举顺序排序
* @param fjzyArray 需要排序的数组
* @param enumObj 枚举对象(如 enumConfig.T1, enumConfig.T2)
* @returns 排序后的数组
*/
function sortFjzyByEnumOrder(fjzyArray: any[], enumObj: any): any[] {
if (!fjzyArray || !Array.isArray(fjzyArray)) return [];
// 获取枚举的顺序映射(按照枚举定义顺序)
const enumOrderMap = new Map();
const enumKeys = Object.keys(enumObj);
enumKeys.forEach((key, index) => {
enumOrderMap.set(key, index); // key 是 "1F", "2F" 等
});
// 对数组进行排序
return [...fjzyArray].sort((a, b) => {
const orderA = enumOrderMap.get(a.lc) ?? Number.MAX_SAFE_INTEGER;
const orderB = enumOrderMap.get(b.lc) ?? Number.MAX_SAFE_INTEGER;
return orderA - orderB;
});
}
/**
* 7、首页
* @param req
* @param res
*/
export async function getHomePage(req, res) {
let ret:any = {};
let url = `${systemConfig.homepage}`;
let homepageInfo = await postJsonAxios(url, {}, {});
/**业务用房 */
let ywyf = homepageInfo.body.ywyf;
let djywyfInfo = {zs:0, fjzy:[]};
let T1ywyfInfo = {zs:0, fjzy:[]};
let T2ywyfInfo = {zs:0, fjzy:[]};
if (Object.keys(ywyf).length) {
let dj = ywyf.dj;
djywyfInfo.zs = dj.zs;
djywyfInfo.fjzy = dj.fjzy;
// 对 DJ 的 fjzy 按 DJ 枚举顺序排序
djywyfInfo.fjzy = sortFjzyByEnumOrder(djywyfInfo.fjzy, enumConfig.DJ);
let T1 = ywyf.T1;
T1ywyfInfo.zs = T1.zs;
let T1Fjzy = T1.fjzy;
T1Fjzy.forEach( info => {
let {xz, lc, zy} = info;
let lcStr = changeEnumNameByCode(enumConfig.T1, lc);
let item = {
lc: lcStr,
zy,
xz
};
T1ywyfInfo.fjzy.push(item);
})
// 对 T1 的 fjzy 按 T1 枚举顺序排序
T1ywyfInfo.fjzy = sortFjzyByEnumOrder(T1ywyfInfo.fjzy, enumConfig.T1);
let T2 = ywyf.T2;
T2ywyfInfo.zs = T2.zs;
let T2Fjzy = T2.fjzy;
T2Fjzy.forEach( info => {
let {xz, lc, zy} = info;
let lcStr = changeEnumNameByCode(enumConfig.T2, lc);
let item = {
lc: lcStr,
zy,
xz
};
T2ywyfInfo.fjzy.push(item);
})
// 对 T2 的 fjzy 按 T2 枚举顺序排序
T2ywyfInfo.fjzy = sortFjzyByEnumOrder(T2ywyfInfo.fjzy, enumConfig.T2);
}
ret["ywyf"] = {
jcsj: { zs: ywyf.zs || 0, syl: ywyf.syl || "" },
dj: djywyfInfo,
T1: T1ywyfInfo,
T2: T2ywyfInfo
}
/**商铺用房 */
let spyf = homepageInfo.body.spyf;
let djspyfInfo = {zs:0, fjzy:[]};
let T1spyfInfo = {zs:0, fjzy:[]};
let T2spyfInfo = {zs:0, fjzy:[]};
if (Object.keys(spyf).length) {
let dj = spyf.dj;
djspyfInfo.zs = dj.zs;
djspyfInfo.fjzy = dj.fjzy;
// 对 DJ 的 fjzy 按 DJ 枚举顺序排序
djspyfInfo.fjzy = sortFjzyByEnumOrder(djspyfInfo.fjzy, enumConfig.DJ);
let T1 = spyf.T1;
T1spyfInfo.zs = T1.zs;
let T1Fjzy = T1.fjzy;
T1Fjzy.forEach( info => {
let {xz, lc, zy} = info;
let lcStr = changeEnumNameByCode(enumConfig.T1, lc);
let item = {
lc: lcStr,
zy,
xz
};
T1spyfInfo.fjzy.push(item);
})
// 对 T1 的 fjzy 按 T1 枚举顺序排序
T1spyfInfo.fjzy = sortFjzyByEnumOrder(T1spyfInfo.fjzy, enumConfig.T1);
let T2 = spyf.T2;
T2spyfInfo.zs = T2.zs;
let T2Fjzy = T2.fjzy;
T2Fjzy.forEach( info => {
let {xz, lc, zy} = info;
let lcStr = changeEnumNameByCode(enumConfig.T2, lc);
let item = {
lc: lcStr,
zy,
xz
};
T2spyfInfo.fjzy.push(item);
})
// 对 T2 的 fjzy 按 T2 枚举顺序排序
T2spyfInfo.fjzy = sortFjzyByEnumOrder(T2spyfInfo.fjzy, enumConfig.T2);
}
ret["spyf"] = {
jcsj: { zs: spyf.zs || 0, syl: spyf.syl || "" },
dj: djspyfInfo,
T1: T1spyfInfo,
T2: T2spyfInfo
}
res.send(ret);
}
/**标志标识 */
import { systemConfig } from "../config/serverConfig";
import { postAxios } from "../util/request";
import * as enumConfig from "../config/enum";
import { convertTIMDataToModelFormat } from "../dataPackage/tool";
import { signPointDjTableData, signPointT1TableData, signPointT2TableData } from "../data/table/roomPoint";
/**
* 1、全部标志标识数据
* @param req
* @param res
*/
export async function getTotal(req, res) {
let ret:any = {};
let url = `${systemConfig.totalBZBS}`;
let totalInfo = await postAxios(url, {}, {});
ret = totalInfo.body;
res.send(ret);
}
/**
* 2、楼栋标志标识数据
* @param req
* @param res
*/
export async function getTerminal(req, res) {
let ret:any = {};
let {ld} = req.body;
let url = `${systemConfig.terminalBZBS}?ld=${ld}`;
let terminalInfo = await postAxios(url, {}, {});
ret = terminalInfo.body;
res.send(ret);
}
/**
* 3、楼层标志标识数据
* @param req
* @param res
*/
export async function getFloor(req, res) {
let ret:any = {};
let {ld, lc} = req.body;
let ldStr = ld;
if (ld == "东交") ldStr = "DJ";
let lcStr = enumConfig[`${ldStr}_ywyf`][lc];
let url = `${systemConfig.floorBZBS}?ld=${ld}&lc=${lcStr}`;
let floorInfo = await postAxios(url, {}, {});
ret = floorInfo.body;
res.send(ret);
}
/**
* 4、标志标识信息
* @param req
* @param res
*/
export async function getSign(req, res) {
let ret:any = {};
let {bsmc} = req.body;
let url = `${systemConfig.signBZBS}?bsmc=${bsmc}`;
let signInfo = await postAxios(url, {}, {});
ret = signInfo.body;
res.send(ret);
}
/**
* 标志标识地图撒点
* @param req
* @param res
*/
export async function getSignPoint(req, res) {
let ret = {};
let excelT1Data = signPointT1TableData();
let excelT2Data = signPointT2TableData();
let excelDjData = signPointDjTableData();
let TIMData = {
"T1": excelT1Data["T1"],
"T2": excelT2Data["T2"],
"Dj": excelDjData["东郊"]
}
const configs = {
'T1': [
{ imgName: '1F', floorName: '1F', displayName: '1F', altitude: '(0.0M)', includeEmpty: true },
{ imgName: '2F', floorName: '2F', displayName: '2F', altitude: '(5.4M)', includeEmpty: true },
],
'T2': [
{ imgName: 'B1', floorName: 'B1', displayName: 'B1', altitude: '(-7.95M)', includeEmpty: true },
{ imgName: '1F', floorName: '1F', displayName: '1F', altitude: '(0.0M)', includeEmpty: true },
{ imgName: '2F', floorName: '2F', displayName: '2F', altitude: '(4.2M)', includeEmpty: true },
{ imgName: 'M2', floorName: 'M2', displayName: 'M2', altitude: '(8.55M)', includeEmpty: true },
{ imgName: '3F', floorName: '3F', displayName: '3F', altitude: '(12.15M)', includeEmpty: true },
{ imgName: '4F', floorName: '4F', displayName: '4F', altitude: '(21.65M)', includeEmpty: true },
],
'Dj': [
{ imgName: 'B1', floorName: 'B1', displayName: 'B1', altitude: '(-4.8M)', includeEmpty: true },
{ imgName: '1F', floorName: '1F', displayName: '1F', altitude: '(0.0M)', includeEmpty: true },
{ imgName: '2F', floorName: '2F', displayName: '2F', altitude: '(6.6M)', includeEmpty: true },
{ imgName: '3F', floorName: '3F', displayName: '3F', altitude: '(12.15M)', includeEmpty: true },
{ imgName: '4F', floorName: '4F', displayName: '4F', altitude: '(19.05M)', includeEmpty: true },
{ imgName: '5F', floorName: '5F', displayName: '5F', altitude: '(24.15M)', includeEmpty: true },
{ imgName: '6F', floorName: '6F', displayName: '6F', altitude: '(29.25M)', includeEmpty: true },
]
};
// 转换TIMData为model格式
let modelTabs = convertTIMDataToModelFormat(TIMData, "sign", configs);
ret['modelTabs'] = modelTabs;
res.send(ret);
}
This diff is collapsed. Click to expand it.
import * as nodeCrypto from 'crypto';
// 对应 HQSysConfig 枚举的配置
const HQSysConfig = {
TimDevSysId: {
configName: 'SYSTEMID',
configValue: 'TIM'
},
TimDevSysPassword: {
configName: 'PASSWORD',
configValue: 'CD0832C695E245D791514B3B421B9C47'
}
};
/**
* 生成签名
*/
function generateSign(systemId: string, password: string, currentTime: string): string {
const beforeSecret = systemId + password + currentTime;
console.log(`systemId:${systemId}, password:${password}, currentTime:${currentTime}`);
const sign = nodeCrypto.createHash('md5').update(beforeSecret).digest('hex').toLowerCase();
console.log(`sign:${sign}, beforeSecret:${beforeSecret}`);
return sign;
}
/**
* 检查参数有效性
*/
function checkParam(authInfo: { systemId?: string; currentTime?: string; sign?: string }): string {
// 校验系统标识
const requestSystemId = authInfo.systemId || '';
if (HQSysConfig.TimDevSysId.configValue !== requestSystemId) {
return '系统标识不存在';
}
// 校验时间戳
const currentTime = authInfo.currentTime || '';
if (!currentTime) {
return 'currentTime is NULL';
}
// 时间格式验证和间隔检查
const now = new Date();
// 解析时间字符串 yyyyMMddHHmmss
const year = parseInt(currentTime.substring(0, 4));
const month = parseInt(currentTime.substring(4, 6)) - 1;
const day = parseInt(currentTime.substring(6, 8));
const hour = parseInt(currentTime.substring(8, 10));
const minute = parseInt(currentTime.substring(10, 12));
const second = parseInt(currentTime.substring(12, 14));
const inputTime = new Date(year, month, day, hour, minute, second);
const minutesDiff = Math.abs(now.getTime() - inputTime.getTime()) / (1000 * 60);
if (minutesDiff > 10) {
return '时间戳间隔不能大于20分钟,请重新提交!';
}
// 验签操作
const getSign = authInfo.sign || '';
const systemId = HQSysConfig.TimDevSysId.configValue;
const password = HQSysConfig.TimDevSysPassword.configValue;
const sign = generateSign(systemId, password, currentTime);
if (sign !== getSign) {
return '验签失败,请检查参数重新提交!';
}
return '';
}
/**
* 认证中间件 - 用于验证接口签名
*/
export function authMiddleware(req: any, res: any, next: any) {
const authInfo = {
systemId: req.body.systemId || req.query.systemId,
currentTime: req.body.currentTime || req.query.currentTime,
sign: req.body.sign || req.query.sign
};
const authResult = checkParam(authInfo);
if (authResult !== '') {
return res.status(200).json({
success: false,
code: 401,
message: authResult
});
}
next();
}
/**
* 生成签名接口 - 用于校验前端传来的sign是否正确
*/
export function generateSignApi(req: any, res: any) {
try {
const { systemId, currentTime, sign } = req.body;
if (!systemId || !currentTime || !sign) {
return res.status(200).json({
success: false,
code: 400,
message: 'systemId、currentTime 和 sign 参数不能为空'
});
}
const password = HQSysConfig.TimDevSysPassword.configValue;
// 使用同样的规则生成MD5签名
const generatedSign = generateSign(systemId, password, currentTime);
// 等值校验
if (generatedSign === sign) {
res.status(200).json({
success: true,
code: 200,
data: {
isValid: true,
generatedSign: generatedSign,
receivedSign: sign
},
message: '签名验证通过'
});
} else {
res.status(200).json({
success: false,
code: 400,
data: {
isValid: false,
generatedSign: generatedSign,
receivedSign: sign
},
message: '签名验证失败'
});
}
} catch (error) {
console.error('签名验证失败:', error);
res.status(200).json({
success: false,
code: 500,
message: '签名验证失败'
});
}
}
/**
* 生成签名接口 - 仅生成签名(供调试使用)
*/
export function createSignApi(req: any, res: any) {
try {
const { systemId, currentTime } = req.body;
if (!systemId || !currentTime) {
return res.status(200).json({
success: false,
code: 400,
message: 'systemId 和 currentTime 参数不能为空'
});
}
const password = HQSysConfig.TimDevSysPassword.configValue;
const sign = generateSign(systemId, password, currentTime);
res.status(200).json({
success: true,
code: 200,
data: {
sign,
systemId,
currentTime,
beforeSecret: systemId + password + currentTime
},
message: '签名生成成功'
});
} catch (error) {
console.error('生成签名失败:', error);
res.status(200).json({
success: false,
code: 500,
message: '生成签名失败'
});
}
}
export {
generateSign,
checkParam
};
let TIMData = {
"T1": {
"dataList": [
{
"lc": "B2地下室",
"fjh": "T1-A-B1-B1",
"xzzb": 2000,
"yzzb": 968,
"dwdx": "default",
"zfjh": undefined,
},
{
"lc": "B2地下室",
"fjh": "T1-A-B1-B2",
"xzzb": 2188,
"yzzb": 968,
"dwdx": "default",
"zfjh": undefined,
},
{
"lc": "B2地下室",
"fjh": "T1-A-B1-B3",
"xzzb": 2276,
"yzzb": 968,
"dwdx": "default",
"zfjh": undefined,
},
{
"lc": "F1",
"fjh": "T1-A-1-B1",
"xzzb": 2971,
"yzzb": 874,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F1",
"fjh": "T1-A-1-B1A",
"xzzb": 2955,
"yzzb": 901,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F2",
"fjh": "T1-A-2-B35",
"xzzb": 2265,
"yzzb": 333,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F2",
"fjh": "T1-A-2-B36",
"xzzb": 2085,
"yzzb": 424,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F2",
"fjh": "T1-A-2-B37",
"xzzb": 2347,
"yzzb": 360,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F2",
"fjh": "T1-A-2-B41",
"xzzb": 2627,
"yzzb": 519,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F2",
"fjh": "T1-A-2-B41A",
"xzzb": 2253,
"yzzb": 308,
"dwdx": "small",
"zfjh": undefined,
},
{
"lc": "F3",
"fjh": "T1-F3套房1号-5间房",
"xzzb": 1285,
"yzzb": 524,
"dwdx": "medium",
"zfjh": undefined,
},
{
"lc": "F3",
"fjh": "T1-B-3-B22A",
"xzzb": 1285,
"yzzb": 524,
"dwdx": "small",
"zfjh": "T1-F3套房1号-5间房",
},
{
"lc": "F3",
"fjh": "T1-B-3-B22B",
"xzzb": 1285,
"yzzb": 524,
"dwdx": "small",
"zfjh": "T1-F3套房1号-5间房",
},
{
"lc": "F3",
"fjh": "T1-B-3-B22C",
"xzzb": 1285,
"yzzb": 524,
"dwdx": "small",
"zfjh": "T1-F3套房1号-5间房",
},
{
"lc": "F3",
"fjh": "T1-B-3-B22D",
"xzzb": 1285,
"yzzb": 524,
"dwdx": "small",
"zfjh": "T1-F3套房1号-5间房",
},
{
"lc": "F3",
"fjh": "T1-B-3-B22E",
"xzzb": 1285,
"yzzb": 524,
"dwdx": "small",
"zfjh": "T1-F3套房1号-5间房",
},
],
"titleList": [
"lc",
"fjh",
"xzzb",
"yzzb",
"dwdx"
]
},
"T2": {
"dataList": [
{
"lc": "B1",
"fjh": "B3-B1-B1",
"xzzb": 2093,
"yzzb": 819,
"dwdx": "small"
},
{
"lc": "B1",
"fjh": "B3-B1-B1",
"xzzb": 1973,
"yzzb": 819,
"dwdx": "small"
},
{
"lc": "F1",
"fjh": "A5-1-B4",
"xzzb": 1276,
"yzzb": 402,
"dwdx": "small"
},
{
"lc": "F1",
"fjh": "A5-1-B5",
"xzzb": 1281,
"yzzb": 390,
"dwdx": "small"
},
{
"lc": "F1",
"fjh": "A3-1-B25",
"xzzb": 1334,
"yzzb": 798,
"dwdx": "small"
},
{
"lc": "F1",
"fjh": "A3-1-B39",
"xzzb": 1426,
"yzzb": 789,
"dwdx": "small"
},
{
"lc": "F2",
"fjh": "C3-2-B2",
"xzzb": 2836,
"yzzb": 778,
"dwdx": "small"
},
{
"lc": "F2",
"fjh": "C3-2-B1",
"xzzb": 2858,
"yzzb": 789,
"dwdx": "small"
},
{
"lc": "F2",
"fjh": "C2-2-B7",
"xzzb": 2869,
"yzzb": 827,
"dwdx": "small"
},
{
"lc": "F2",
"fjh": "C2-2-B6",
"xzzb": 2890,
"yzzb": 809,
"dwdx": "small"
},
{
"lc": "M2",
"fjh": "C3-M2-B6",
"xzzb": 2660,
"yzzb": 827,
"dwdx": "small"
},
{
"lc": "M2",
"fjh": "C3-M2-B7",
"xzzb": 2645,
"yzzb": 827,
"dwdx": "small"
},
{
"lc": "M2",
"fjh": "C3-M2-B8",
"xzzb": 2636,
"yzzb": 811,
"dwdx": "small"
},
{
"lc": "M2",
"fjh": "C3-M2-B9",
"xzzb": 2630,
"yzzb": 827,
"dwdx": "small"
},
{
"lc": "M2",
"fjh": "C3-M2-B10",
"xzzb": 2618,
"yzzb": 811,
"dwdx": "small"
},
{
"lc": "M2",
"fjh": "C3-M2-B15",
"xzzb": 2557,
"yzzb": 820,
"dwdx": "small"
},
],
"titleList": [
"lc",
"fjh",
"xzzb",
"yzzb",
"dwdx"
]
},
"Dj": {
"dataList": [
{
"lc": "F3",
"fjh": "DF317",
"xzzb": 1836,
"yzzb": 479,
"dwdx": "default"
},
{
"lc": "F3",
"fjh": "DF319A",
"xzzb": 1727,
"yzzb": 479,
"dwdx": "default"
},
{
"lc": "F3",
"fjh": "DF319B",
"xzzb": 1771,
"yzzb": 479,
"dwdx": "default"
},
{
"lc": "F7",
"fjh": "DF709",
"xzzb": 1178,
"yzzb": 356,
"dwdx": "default"
},
{
"lc": "F7",
"fjh": "DF710",
"xzzb": 1897,
"yzzb": 356,
"dwdx": "default"
},
{
"lc": "F7",
"fjh": "DF711",
"xzzb": 2360,
"yzzb": 356,
"dwdx": "default"
}
],
"titleList": [
"lc",
"fjh",
"xzzb",
"yzzb",
"dwdx"
]
}
}
\ No newline at end of file
This diff is collapsed. Click to expand it.
// ========================= 正式环境 ===============================
// ========================= 正式环境 ===============================
<ledger>
<ywyfledger>https://tim.shatim.com.cn/spa/cube/index.html#/main/cube/search?customid=841&amp;_key=cfiju7</ywyfledger>
<srledger>https://tim.shatim.com.cn/spa/cube/index.html#/main/cube/search?customid=899&amp;_key=jzqwlk</srledger>
</ledger>
<TIM2>
<!-- 首页 -->
<homepage>https://tim.shatim.com.cn/api/bussiness/analyse/homepage</homepage>
<!-- 当前用户角色列表 -->
<rolesList>https://tim.shatim.com.cn/api/bussiness/analyse/roles/list</rolesList>
<!-- 当前用户角色编辑 -->
<rolesEdit>https://tim.shatim.com.cn/api/bussiness/analyse/roles/edit</rolesEdit>
<!-- 全部业务用房 -->
<total>https://tim.shatim.com.cn/api/bussiness/analyse/total</total>
<!-- 业务用房楼层分析 -->
<analyse>https://tim.shatim.com.cn/api/bussiness/analyse/analyse</analyse>
<!-- 业务用房楼栋分析 -->
<terminal>https://tim.shatim.com.cn/api/bussiness/analyse/terminal</terminal>
<!-- 房间业务用房数据 -->
<room>https://tim.shatim.com.cn/api/bussiness/analyse/room</room>
</TIM2>
<zy>
<total>https://tim.shatim.com.cn/api/seat/analyse/total</total>
<terminal>https://tim.shatim.com.cn/api/seat/analyse/terminal</terminal>
<floor>https://tim.shatim.com.cn/api/seat/analyse/floor</floor>
<seat>https://tim.shatim.com.cn/api/seat/analyse/seat</seat>
</zy>
<bzbs>
<total>https://tim.shatim.com.cn/api/sign/analyse/total</total>
<terminal>https://tim.shatim.com.cn/api/sign/analyse/terminal</terminal>
<floor>https://tim.shatim.com.cn/api/sign/analyse/floor</floor>
<sign>https://tim.shatim.com.cn/api/sign/analyse/sign</sign>
</bzbs>
// ========================= 测试环境 ===============================
<TIM2>
<homepage>http://10.134.3.1:81/api/bussiness/analyse/homepage</homepage>
<rolesList>http://10.134.3.1:81/api/bussiness/analyse/roles/list</rolesList>
<rolesEdit>http://10.134.3.1:81/api/bussiness/analyse/roles/edit</rolesEdit>
<total>http://10.134.3.1:81/api/bussiness/analyse/total</total>
<analyse>http://10.134.3.1:81/api/bussiness/analyse/analyse</analyse>
<terminal>http://10.134.3.1:81/api/bussiness/analyse/terminal</terminal>
<room>http://10.134.3.1:81/api/bussiness/analyse/room</room>
</TIM2>
<zy>
<total>http://10.134.3.1:81/api/seat/analyse/total</total>
<terminal>http://10.134.3.1:81/api/seat/analyse/terminal</terminal>
<floor>http://10.134.3.1:81/api/seat/analyse/floor</floor>
<seat>http://10.134.3.1:81/api/seat/analyse/seat</seat>
</zy>
<bzbs>
<total>http://10.134.3.1:81/api/sign/analyse/total</total>
<terminal>http://10.134.3.1:81/api/sign/analyse/terminal</terminal>
<floor>http://10.134.3.1:81/api/sign/analyse/floor</floor>
<sign>http://10.134.3.1:81/api/sign/analyse/sign</sign>
</bzbs>
/**-----------------------------接口枚举------------------------------- */
/**
* 接口更新类型
*/
export enum INTERFACEREQUESTTYPEENUM {
即时更新 = 1,
定时更新
}
export enum TYPEENUM {
string = 1,
number,
object,
array,
boolean,
}
/**上传文件类型 */
export enum FILETYPE {
word = 1,
pdf,
图片,
视频,
多类型
}
export enum T1_ywyf {
"B1" = "-8.85M",
"1F" = "0.0M",
"2F" = "5.4M",
"3F" = "10.9M",
"4F" = "16.4M",
}
export enum T2_ywyf {
"B1" = "-7.95M",
"1F" = "0.0M",
"2F" = "4.2M",
"M2" = "8.55M",
"3F-1" = "12.15M",
"3F-2" = "13.55M",
"M3" = "17.15M",
"4F" = "21.65M",
"5F" = "24.65M",
"6F" = "28.65M",
"7F" = "32.65M",
"8F" = "36.65M",
}
export enum DJ_ywyf {
"B1" = "B1",
"3F" = "F3",
"4F" = "F4",
"5F" = "F5",
"6F" = "F6",
"7F" = "F7",
// "3F" = "12.15M", //F3
// "4F" = "19.05M", //F4
// "5F" = "24.15M", //F5
// "6F" = "29.25M", //F6
// "7F" = "34.2M", //F7
}
export enum T1 {
"B1" = "-8.85M",
"1F" = "0.0M",
"2F" = "5.4M",
"3F" = "10.9M",
"4F" = "16.4M",
}
export enum T2 {
"B1" = "-7.95M",
"1F" = "0.0M",
"2F" = "4.2M",
"M2" = "8.55M",
"3F-1" = "12.15M",
"3F-2" = "13.55M",
"M3" = "17.15M",
"4F" = "21.65M",
"5F" = "24.65M",
"6F" = "28.65M",
"7F" = "32.65M",
"8F" = "36.65M",
}
export enum DJ {
"东交B1" = "-4.8M",
"东交3F" = "12.15M",
"东交4F" = "19.05M",
"东交5F" = "24.15M",
"东交6F" = "29.25M",
"东交7F" = "34.2M",
}
export enum ERRORENUM {
未找到数据,
数据操作失败,
暂无对应数据,
文件不存在,
参数错误,
地址数据不完整,
请完善信息,
接口数据获取失败
}
export enum SYSTEMERRORENUM {
参数错误 = 1,
您的登录已失效,
您的账户没有访问权限,
请求参数错误,
文件解析失败,
文件写入失败,
获取企业微信access_token失败,
获取企业微信用户信息失败,
请先绑定用户,
TOKEN失效,
该微信用户已绑定过账号,
存在TOKEN并没有绑定角色,
初始化配置失败,
暂无对应数据
}
export enum INTERFACEERRORENUM {
"系统错误" = 10001,
"服务暂停" = 10002,
"远程服务调用失败" = 10003,
"IP地址受限,不能访问此接口" = 10004,
"APP Key 不存在" = 10005,
"签名错误" = 10006,
"缺少 POST 参数" = 10007,
"POST 参数错误" = 10008,
"数据类别标识不存在" = 10009,
"数据对象标识不存在" = 10010,
"对数据对象没有写的权限" = 10011,
"对数据对象没有读的权限" = 10012,
"数据记录不存在" = 10013,
"数据记录的 id 已存在" = 10014,
"应用程序内部错误" = 10099,
}
let bizErrorMsgMap = {};
for (let key in ERRORENUM) {
bizErrorMsgMap[ERRORENUM[key]] = key;
}
let systemErrorMsgMap = {};
for (let key in SYSTEMERRORENUM) {
systemErrorMsgMap[SYSTEMERRORENUM[key]] = key;
}
export function getBizMsg(param) {
return bizErrorMsgMap[param];
}
export function getSysMsg(param) {
return systemErrorMsgMap[param];
}
\ No newline at end of file
const path = require('path');
import * as fs from "fs";
import { BizError, SysError } from "../util/bizError";
import { analysisXml } from "../util/myXML";
import {ServerConfig} from "../config/systemClass";
import { SYSTEMERRORENUM } from "./errorEnum";
export let systemConfig = new ServerConfig;
const ConfigName = "serverConfig.xml";
export async function initConfig() {
try {
let buff = fs.readFileSync(path.join(__dirname.substring(0,__dirname.indexOf("out")), ConfigName));
let configStr = buff.toString();
let configInfo:any = await analysisXml(configStr);
if (!configInfo || !configInfo.config) console.log("xml中无配置加载");
else {
//必要配置
let integralConfig = ["port", "imgIp", "TIM", "TIM2", "zy", "bzbs", "ledger"];
checkConfig(integralConfig, configInfo.config);
let {port, imgIp, TIM, TIM2, zy, bzbs, ledger} = configInfo.config;
systemConfig.port = parseInt(port[0]);
systemConfig.imgIp = imgIp[0];
//?fjh=${TIM[0].fjh[0]}
systemConfig.resourceAnalyse = TIM[0].resourceAnalyse[0];
systemConfig.terminalInfo = TIM[0].terminalInfo[0];
systemConfig.roomInfo = TIM[0].roomInfo[0];
systemConfig.rolesList = TIM2[0].rolesList[0];
systemConfig.rolesEdit = TIM2[0].rolesEdit[0];
systemConfig.total = TIM2[0].total[0];
systemConfig.analyse = TIM2[0].analyse[0];
systemConfig.terminal = TIM2[0].terminal[0];
systemConfig.room = TIM2[0].room[0];
systemConfig.homepage = TIM2[0].homepage[0];
// 座椅
systemConfig.totalZY = zy[0].total[0];
systemConfig.terminalZY = zy[0].terminal[0];
systemConfig.floorZY = zy[0].floor[0];
systemConfig.seatZY = zy[0].seat[0];
// 标志标识
systemConfig.totalBZBS = bzbs[0].total[0];
systemConfig.terminalBZBS = bzbs[0].terminal[0];
systemConfig.floorBZBS = bzbs[0].floor[0];
systemConfig.signBZBS = bzbs[0].sign[0];
// 台账地址跳转
systemConfig.ywyfledger = ledger[0].ywyfledger[0];
systemConfig.srledger = ledger[0].srledger[0];
}
} catch(err) {
throw new BizError("服务器配置解析错误 请检查根目录下 serverConfig.xml 文件是否正确");
}
}
function checkConfig(config, configData) {
config.forEach(item => {
if (typeof item == "object") {
for (let key in item) {
if (!configData[key] || !configData[key][0]) {
throw new SysError(SYSTEMERRORENUM.初始化配置失败, `serverConfig.xml中 缺少 ${key}`);
}
item[key].forEach( subItem => {
if (!configData[key][0][subItem] || !configData[key][0][subItem][0]) {
throw new SysError(SYSTEMERRORENUM.初始化配置失败, `serverConfig.xml中 ${key}缺少 ${subItem}`);
}
});
}
} else {
if (!configData[item] || !configData[item][0]) {
throw new SysError(SYSTEMERRORENUM.初始化配置失败, `serverConfig.xml中 缺少 ${item}`);
}
}
});
}
/**
* 系统配置类
*/
export class ServerConfig {
port:number;
imgIp:string;
TIMUrl:string;
resourceAnalyse:string;
terminalInfo:string;
roomInfo:string;
TIM2Url:string;
rolesList:string;
rolesEdit:string;
total:string;
analyse:string;
terminal:string;
room:string;
homepage:string;
// 座椅
totalZY:string;
terminalZY:string;
floorZY:string;
seatZY:string;
// 标志标识
totalBZBS:string;
terminalBZBS:string;
floorBZBS:string;
signBZBS:string;
// 台账地址跳转
ywyfledger:string;
srledger:string;
}
//接口任务 定期更新
import * as request from 'request';
import { INTERFACEREQUESTTYPEENUM } from "../../config/enum";
import { BizError } from "../../util/bizError";
import { Config } from './interfaceConfig';
const http = require('http');
//初始化接口数据
export async function initInterfaceData() {
const InitTaskSuccess = await taskUpdate();
// if (!InitTaskSuccess) throw new BizError("服务器启动失败: 初始化定时接口数据时出现问题 请检查目标服务器或本地请求配置");
const InitRealTimeSuccess = await initRealTime();
// if (!InitRealTimeSuccess) throw new BizError("服务器启动失败: 初始化实时接口数据时出现问题 请检查目标服务器或本地请求配置");
console.log("初始化接口数据成功");
setInterval(() => {
taskUpdate();
}, 10000);
}
//异常接口 不更新数据
let errorInterfaceInfo = {};
//定时接口 数据更新情况
let updateInfo = {
"接口名称":{lastTime:0, updateUseTime:0},//使用时间是毫秒
};
//定时接口 缓存数据
let dataQueue = {};
async function taskUpdate() {
let thisTaskInfo = [];//此次任务
let defaultUseTime = 60000;
let thisTime = new Date().valueOf();
let initSuccess = true;
for (let interfaceName in Config) {
const LastReqError = errorInterfaceInfo[interfaceName];
if (LastReqError) {
console.log(`${interfaceName} 请求时出现过 ${LastReqError} 异常 保险起见此次更新不再请求`);
continue;
}
const ThisConfig = Config[interfaceName];
if (ThisConfig.type == INTERFACEREQUESTTYPEENUM.即时更新) continue;
let lastTaskInfo = updateInfo[interfaceName];
if ( !lastTaskInfo ) thisTaskInfo.push({name:defaultUseTime, useTime:defaultUseTime});
else if ( lastTaskInfo && (thisTime - lastTaskInfo) > ThisConfig.time ) {
thisTaskInfo.push({name:defaultUseTime, useTime:lastTaskInfo.updateUseTime});
}
defaultUseTime += 1;
}
thisTaskInfo.sort((a, b) => {return a.useTime - b.useTime});//耗时短的优先
for (let i = 0; i < thisTaskInfo.length; i++) { //更新数据
let {name} = thisTaskInfo[i];
const ThisConfig = Config[name];
const StartTime = new Date().valueOf();
let reqRes;
switch(ThisConfig.reqType) {
case "get": reqRes = await get(ThisConfig.url, ThisConfig.body, ThisConfig.header); break;
case "post": reqRes = await post(ThisConfig.url, ThisConfig.body, ThisConfig.header); break;
case "postForm": reqRes = await postForm(ThisConfig.url, ThisConfig.body); break;
}
const UseTime = new Date().valueOf() - StartTime;
if (reqRes.success) {
if (!updateInfo[name]) updateInfo[name] = {lastTime:thisTime, updateUseTime:UseTime};
else {
updateInfo[name].lastTime = thisTime;
updateInfo[name].updateUseTime = UseTime;
}
if (dataQueue[name]) delete dataQueue[name];
dataQueue[name] = JSON.stringify(reqRes.body);//放入缓存
} else {
let errorMsg = reqRes.message;
if (reqRes.message && reqRes.message.code == "ESOCKETTIMEDOUT") errorMsg = "超时";
console.log(`接口 ${name} 请求失败 失败原因${errorMsg}`);
if (["404", "503"].indexOf(errorMsg) > -1) { //下次不再请求
errorInterfaceInfo[name] = errorMsg;
}
initSuccess = false;
}
}
return initSuccess;
}
//即时数据缓存 当请求失败时会用到这里的数据
let realTimeDataQueue = {};
//即时数据初始化
async function initRealTime() {
let initSuccess = true;
for (let interfaceName in Config) {
const ThisConfig = Config[interfaceName];
if (ThisConfig.type == INTERFACEREQUESTTYPEENUM.定时更新) continue;
let reqRes;
switch(ThisConfig.reqType) {
case "get": reqRes = await get(ThisConfig.url, ThisConfig.body, ThisConfig.header); break;
case "post": reqRes = await post(ThisConfig.url, ThisConfig.body, ThisConfig.header); break;
case "postForm": reqRes = await postForm(ThisConfig.url, ThisConfig.body); break;
}
if (!reqRes.success) {
console.log(`${interfaceName} 接口请求失败 请求地址为 ${ThisConfig.url} 失败原因 ${reqRes.message}`);
initSuccess = false;
}
realTimeDataQueue[interfaceName] = reqRes.data;
}
return initSuccess;
}
export async function getInterfaceByInterfaceName(name, body?, header?) {
const ThisConfig = Config[name];
let data:any;
if (ThisConfig.type == INTERFACEREQUESTTYPEENUM.即时更新) {
let reqRes;
let reqBody = Object.assign( ThisConfig.body|| {}, body || {});
let reqHeader = Object.assign( ThisConfig.header|| {}, header || {});
switch(ThisConfig.reqType) {
case "get": reqRes = await get(ThisConfig.url, reqBody, reqHeader); break;
case "post": reqRes = await post(ThisConfig.url, reqBody, reqHeader); break;
case "getParmiss": reqRes = await getParmiss(ThisConfig.url, reqBody, reqHeader); break;
case "postParmiss": reqRes = await postParmiss(ThisConfig.url, reqBody, reqHeader); break;
case "postForm": reqRes = await postForm(ThisConfig.url, reqBody ); break;
case "postPHP": reqRes = await postPHP(ThisConfig.url, reqBody, reqHeader); break;
}
if (reqRes.success) {
data = reqRes.data;
} else {
data = realTimeDataQueue[name];
}
} else data = dataQueue[name];
return data;
}
function get(url:string, query?, headers?, timeOut?) {
timeOut = timeOut || 5000;
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
return new Promise((resolve, reject)=>{
let paramater:any = { url, json:true, timeout:timeOut };
if (query) paramater.qs = query;
if (headers) paramater.headers = headers;
request.get(paramater, function (err, res, data) {
const success = !err && res && res.statusCode == 200;
let message = err || res.statusCode || "";
resolve({success, message, data});
})
})
}
function post(url, body, headers) {
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
let header = {"content-type": "application/json"};
return new Promise((resolve, reject)=>{
request({
url: url,
method: "POST",
json: true,
headers: Object.assign(header, headers),
body: body
}, function(error, response, data) {
if (!error && response.statusCode == 0) {
resolve(data);
}
else {
reject(error || `${url} => ${JSON.stringify(data)}`)
}
});
})
}
function postForm(url, body) {
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
return new Promise((resolve, reject)=>{
request({
url: url,
method: "POST",
json: true,
form:body
}, function(err, res, data) {
const success = !err && res && res.statusCode == 200;
let message = err || res.statusCode || "";
resolve({success, message, data});
});
})
}
function postParmiss(url, reqBody, headers) {
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
return new Promise((resolve, reject)=>{
request({
url: url,
method: "POST",
json: true,
form: reqBody
}, function(error, response, body) {
resolve(body);
});
})
}
function getParmiss(url, query?, headers?) {
return new Promise((resolve, reject)=>{
let paramater:any = { url, json:true };
if (query) paramater.qs = query;
if (headers) paramater.headers = headers;
request.get(paramater, function (err, r, body) {
if (err) return resolve(err);
if (r && r.statusCode != 200) return resolve( { error: 'httpError:'+r.statusCode })
resolve(body);
});
})
}
function postPHP(url, body, headers) {
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
let header = {"content-type": "application/json"};
return new Promise((resolve, reject)=>{
request({
url: url,
method: "POST",
json: true,
headers: Object.assign(header, headers),
body: body
}, function(error, response, body) {
resolve(body);
});
})
}
import { INTERFACEREQUESTTYPEENUM } from "../../config/enum";
import { systemConfig } from "../../config/serverConfig";
//配置
// "接口名称":{
// type:"1是即时更新 2是即时更新 使用 INTERFACErEQUESTTYPEENUM",
// time:"更新频率毫秒 例如1小时这里就是 3600000",
// url:"url地址",
// reqType:"get还是post get = get post = post",
// header:{},
// body:{}
// }
export const Config = {
// "获取接口地址":{type:INTERFACEREQUESTTYPEENUM.即时更新, time:3600000*12, url:"http://nmzxdec.ischooldays.cn:1066/dec/api/index.php", reqType:"postForm", header:{}, body:{}},
};
/**
* 房间点位
*/
import { planarArrDecollateForIndex, planarArrDeconstruct, planarArrForObjectList } from "../../dataPackage/planaryArrayAnalysis";
import { onceSheetBecomeOfblockData, onceSheetBecomeOfblockDataToUrl } from "../../util/analysisExcel";
function packageDataProcess(blockDataList, titltListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList) {
let result = {};
for (let i = 0; i < blockDataList.length; i++) {
let {blockData, blockTitle} = blockDataList[i];
if (keyValueOrTitleList.indexOf(blockTitle) > -1) {
let titleList = titltListConfig[blockTitle] || [];
result[blockTitle] = planarArrForObjectList(blockData, 0, titleList);
}
else if (barChartList.indexOf(blockTitle) > -1) {
result[blockTitle] = planarArrDeconstruct(blockData);
}
else if (stringList.indexOf(blockTitle) > -1) result[blockTitle] = planarArrForObjectList(blockData);
else if (decollatePlanarList.indexOf(blockTitle) > -1) result[blockTitle] = planarArrDecollateForIndex(blockData);
}
return result;
}
/**---------------------------------------房间-------------------------------------------- */
export function roomPointT1TableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总房间定点.xlsx', 'T1');
let keyValueOrTitleList = ['T1']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function roomPointT2TableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总房间定点.xlsx', 'T2');
let keyValueOrTitleList = ['T2']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function roomPointDjTableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总房间定点.xlsx', '东郊');
let keyValueOrTitleList = ['东郊']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
/**---------------------------------------座椅-------------------------------------------- */
export function seatPointT1TableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总座椅定点.xlsx', 'T1');
let keyValueOrTitleList = ['T1']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function seatPointT2TableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总座椅定点.xlsx', 'T2');
let keyValueOrTitleList = ['T2']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function seatPointDjTableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总座椅定点.xlsx', '东郊');
let keyValueOrTitleList = ['东郊']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
/**---------------------------------------标志标识-------------------------------------------- */
export function signPointT1TableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总标志标识定点.xlsx', 'T1');
let keyValueOrTitleList = ['T1']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function signPointT2TableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总标志标识定点.xlsx', 'T2');
let keyValueOrTitleList = ['T2']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function signPointDjTableData() {
let blockDataList = onceSheetBecomeOfblockData('汇总标志标识定点.xlsx', '东郊');
let keyValueOrTitleList = ['东郊']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
/**
* 房间点位
*/
import { planarArrDecollateForIndex, planarArrDeconstruct, planarArrForObjectList } from "../../dataPackage/planaryArrayAnalysis";
import { onceSheetBecomeOfblockData, onceSheetBecomeOfblockDataToUrl } from "../../util/analysisExcel";
function packageDataProcess(blockDataList, titltListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList) {
let result = {};
for (let i = 0; i < blockDataList.length; i++) {
let {blockData, blockTitle} = blockDataList[i];
if (keyValueOrTitleList.indexOf(blockTitle) > -1) {
let titleList = titltListConfig[blockTitle] || [];
result[blockTitle] = planarArrForObjectList(blockData, 0, titleList);
}
else if (barChartList.indexOf(blockTitle) > -1) {
result[blockTitle] = planarArrDeconstruct(blockData);
}
else if (stringList.indexOf(blockTitle) > -1) result[blockTitle] = planarArrForObjectList(blockData);
else if (decollatePlanarList.indexOf(blockTitle) > -1) result[blockTitle] = planarArrDecollateForIndex(blockData);
}
return result;
}
export function zjzHzTableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/汇总后的企业名称.xlsx', 'Sheet1');
let keyValueOrTitleList = ['汇总的企业']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function zjzPxhTableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/排序重组后的企业.xlsx', 'Sheet1');
let keyValueOrTitleList = ['排序后企业']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function qysjTableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/2.xlsx', 'Sheet1');
let keyValueOrTitleList = ['企业数据']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function 平方公里373TableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/【3.73平方公里实体租赁】.xlsx', 'Sheet1');
let keyValueOrTitleList = ['软件园3.73平方公里实体租赁企业摸排情况']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function 平方公里100TableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/【汽车城100平方公里范围企业】已去掉注销吊销企业.xlsx', 'Sheet1');
let keyValueOrTitleList = ['100平方公里']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function 关联入驻企业TableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/【汽车城软件关联入驻企业】.xlsx', 'Sheet1');
let keyValueOrTitleList = ['智能化']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function 入驻年份企业类型TableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/【入驻年份】园招商汇总表.xlsx', 'Sheet1');
let keyValueOrTitleList = ['2023年 软件园公司招商汇总表']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function 小台账TableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/【小台账】.xlsx', '招商汇报统计');
let keyValueOrTitleList = ['上海智能汽车软件园在园企业汇总表']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function 重点稳商TableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/【重点稳商企业】.xlsx', 'Sheet1');
let keyValueOrTitleList = ['企业名称']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
export function qysjgxhTableData() {
let blockDataList = onceSheetBecomeOfblockData('张江镇/企业标签数据_完整更新.xlsx', '企业数据');
let keyValueOrTitleList = ['企业数据']; //适配 饼图 键值以及需要多个Key的
let barChartList = []; //适配 柱状图 折线图
let stringList = [];
let decollatePlanarList = []; //适配 表格
let titleListConfig = {};
let result = packageDataProcess(blockDataList, titleListConfig, keyValueOrTitleList, barChartList, stringList, decollatePlanarList);
return result;
}
//打包完数据之后的处理
/**
* recombinationObject 重组对象 在打包完数据后使用 必须是keyvalue之后
* @param data [{key:key1, value:value1, unit:unit1 }, {key:key2, value:value2, unit:unit2}]
* @param check {"key2":[{key:"key1", name:""}] }
* @returns [{key:key1, value:value1, key2:key2, value2:value2}]
*/
export function recombinationObject(data, checkInfo) {
let dataMap = {};
data.forEach(info => {
let { key } = info;
dataMap[key] = info;
});
let removeKeyMap = {};
for (let checkKey in checkInfo) {
let checkList = checkInfo[checkKey];
checkList.forEach(item => {
let {key, name} = item;
removeKeyMap[key] = 1;
let onceCheck = dataMap[key];
dataMap[checkKey][name] = onceCheck.value;
dataMap[checkKey][`${name}Unit`] = onceCheck.unit;
});
}
let dataList = [];
data.forEach(info => {
let { key } = info;
if (removeKeyMap[key]) return;
dataList.push(dataMap[key]);
});
return dataList;
}
/**
* 修改表格数据结构
* @param titleList
* @param dataList
* @returns
*/
export function change(titleList, dataList) {
let data = [];
dataList.forEach(subList => {
let onceData:any = {};
subList.forEach( (item, index)=> {
let key = titleList[index];
onceData[key] = item;
} );
data.push(onceData);
});
return data;
}
/**
* 获取单条线路数据
* @param line 线路
* @param data 数据
* @param conf 配置
* @returns
*/
export function getLineOneData(line, data, conf) {
let result:any = {};
data.forEach(item => {
let dataLine = item.line;
if (line == dataLine) {
for (let name = 0; name < conf.length; name++) {
result[conf[name]] = item[conf[name]];
}
}
});
return result;
}
/**
* 单条弹窗数据
* @param line 线路
* @param data 数据
* @param conf 配置
* @returns
*/
export function getPopupOneData(line, data, conf) {
let result:any = {};
data.forEach(item => {
let dataLine = item.line;
let dataSite = item.site;
if (line == dataLine) {
if (!result[dataSite]) result[dataSite] = {};
for (let name = 0; name < conf.length; name++) {
result[dataSite][conf[name]] = item[conf[name]];
}
}
});
return result;
}
/**
* 多条弹窗数据
* @param line
* @param data
* @param conf
* @returns
*/
export function getPopupMoreData(line, data, conf) {
let result:any = {};
data.forEach(item => {
let dataLine = item.line;
let dataSite = item.site;
let pipelineRelocationData = {};
if (line == dataLine) {
if (!result[dataSite]) result[dataSite] = {site:item.site, state:item.state, data:[]};
for (let name = 0; name < conf.length; name++) {
pipelineRelocationData[conf[name]] = item[conf[name]];
}
result[dataSite]["data"].push(pipelineRelocationData);
}
});
return result;
}
/**
* 弹窗详细数据
* @param id
* @param tableData
* @param changeConf
* @param conf
* @returns
*/
export function getPopupDetailsData(id, tableData, changeConf, conf, name) {
let details:any = {};
for (let key in tableData) {
if (id == key) {
let data = change(changeConf, tableData[key].bodyList );
data.forEach(item => {
let itemName = item[name];
let detailsData = {};
if (!details[itemName]) details[itemName] = [];
for (let name = 0; name < conf.length; name++) {
detailsData[conf[name]] = item[conf[name]];
}
details[itemName].push(detailsData);
});
}
}
let detailsList = [];
for (let key in details) {
detailsList.push({name: key, dataList: details[key]})
}
return detailsList;
}
\ No newline at end of file
/**
* changeObjectToList 将对象形式的数据转换为keyvalue的数组 对象中的键名称将作为key 传入mapping时 使用对应的change作为key的值
* @param data 数据{key1:value1, key2:value2, key3:value3...}
* @param reflect 对应关系 [{key:"key1",change:"名称1"},{key:"key2", change:"名称2"},{key:"key3", change:"名称3"}]
* @returns [{key:"名称1", value:value1}, {key:"名称2", value:value2}, {key:key3, value:value3}]
*/
export function changeObjectToList(data, reflect?) {
let keyList = [];
if (!reflect || !reflect.length) {
for (let key in data) {
keyList.push({key, change:key});
}
}
let dataList = [];
keyList.forEach(info => {
let {key, change} = info;
let value = data[key];
if (value) dataList.push({ key:change, value:`${value}`});
});
return dataList;
}
/**
* changeObjectKey 按mapping的对应关系修改 data中的key 如果对应关系中找不到,则会使用原来的key
* @param data {key1:value1, key2:value2, key3:value3...}
* @param reflect {"key1":"名称1", "key2":"名称2", "key3":"名称3"}
* @returns {"名称1":value1, "名称2":value2, "名称3":value3}
*/
export function changeObjectKey(data, reflect) {
let result = {};
for (let key in data) {
let changeKey = reflect[key] || key;
result[changeKey] = `${data[key]}`;
}
return result;
}
/**
* changeListObjectToListByReflect 将data中的object的key替换成 reflect对应的值
* @param data [{key1:value1, key2:value2...}, {key1:value1, key2:value2...}, {key1:value1, key2:value2...}]
* @param reflect 映射 不传就不会替换 {"key1":"名称1", "key2":"名称2", "key3":"名称3"}
* @returns [{"名称1":value1, "名称2":value2...}, {"名称1":value1, "名称2":value2...}, {"名称1":value1, "名称2":value2...}]
*/
export function changeListObjectToListByReflect(data, reflect?) {
let dataList = [];
if (!reflect) return dataList;
data.forEach(item => {
let changeInfo = {};
for (let key in item) {
let newKey = reflect[key] || key;
changeInfo[newKey] = `${item[key]}`;
}
dataList.push(changeInfo);
});
return dataList;
}
/**
* getDesignativByReflect 获取data中指定的的key
* @param data [{key1:value1, key2:value2, key3:value3...}, {key1:value1, key2:value2, key3:value3...}, {key1:value1, key2:value2, key3:value3...}] 或者 {key1:value1, key2:value2, key3:value3...}
* @param reflect List 映射 必须参数 ["key1", "key2"] 为key的名称
* @returns [{key1:value1, key2:value2, ...}, {key1:value1, key2:value2, ...}, {key1:value1, key2:value2, ...}]
*/
export function getDesignativByReflect(data, reflect) {
if (typeof data != "object") return data;
let type = Array.isArray(data) ? "array" : "object";
if ((type == "array" && !reflect.length) || (type == "object" && !Object.keys(reflect) ) ) return data;
let reflectMap = {};
reflect.forEach(keyName => {reflectMap[keyName] = 1});
if (type=="array") {
let dataList = [];
data.forEach(item => {
let once = {};
for (let key in item) {
if (!reflectMap[key]) continue;
once[key] = item[key];
}
dataList.push(once);
});
return dataList;
} else {
let dataInfo = {};
for(let key in reflectMap) {
if (data[key]) dataInfo[key] = data[key];
}
return dataInfo;
}
}
/**
* designativListKeyAddUnit为集合中指定的key添加单位
* @param data [{key1:value1, key2:value2, key3:value3...}, {key1:value1, key2:value2, key3:value3...}, {key1:value1, key2:value2, key3:value3...}]
* @param reflect {key1:"%", key2:"个"}
* @returns [{key1:"value1%", ke2:"value2个", keys:"value3"}]
*/
export function designativListKeyAddUnit(data, reflect) {
let dataList = [];
data.forEach(item => {
let onceData = {};
for (let key in item) {
let unit = reflect[key] || '';
onceData[key] = `${item[key]}${unit}`
}
dataList.push(onceData);
});
return dataList;
}
\ No newline at end of file
import { separateDataAndUint, unifiedMaxAndMinValueAndStep } from "./tool";
//数据出口封装 只做封装 少量的数据校验
/**
* getStringOut 获取文字列表返回结果
* @param title 数据标题
* @param data 数据体 格式:["txt...", "str..."]
* @returns {title, dataList:[string...]}
*/
export function getStringOut(title, data) {
let dataList = [];
data.forEach( (str) => {
dataList.push(str);
});
return { title, dataList};
}
/**
* getOnceYBarChartOut 获取单y轴柱状图
* @param title 数据标题
* @param data 数据体 格式: {xUnit:x轴单位, yUnit:y单位, dataInfo:{"图表名称":[{key:"数据key", value:"数据值", unit:"单位" }, {key:"数据key", value:"数据值", unit:"单位" } ] } }
* @returns {title:标题, xUnit:x轴单位, yUnit:y轴单位, yMinValue:最小值, yMaxValue:最大值, yStepValue:间隔,
* chartList:[{thisChartTitle:数据名称, total:总数, unit:单位, dataList:[{name:y轴名称, value:值, unit:单位}] } ]}
* 入参data里面的dataInfo中的unit可以为空 会读取yUnit 所以入参优先度 yUnit > unit 默认值都是空字符串
*/
export function getOnceYBarChartOut(title, data, stepCount?) {
let chartList = [];
let {xUnit, yUnit, dataInfo} = data;
let thisYUnit = yUnit ||"";
let min = new Date().valueOf();
let max = 0;
for (let dataName in dataInfo) {
let onceChartList = dataInfo[dataName];
let dataList = [];
let total = 0;
onceChartList.forEach(item => {
let {key, value, unit} = item;
min = Math.min(value, min);
max = Math.max(value, max);
total += parseInt(value);
dataList.push({name:key, value, unit: unit || thisYUnit});
});
chartList.push({thisChartTitle:dataName, total, unit:thisYUnit, dataList});
}
let {maxNumber, minNumber, stepNumber} = unifiedMaxAndMinValueAndStep(max, min, stepCount);
return {title, xUnit, yUnit:thisYUnit, yMinValue:minNumber, yMaxValue:maxNumber, yStepValue:stepNumber, chartList};
}
/**
* getDoubleYBarChartOut 获取双y轴柱状图
* @param title 数据标题
* @param data 数据体 格式:{xUnit:x轴单位, leftYUnit:左边y单位, rightYUnit:右边y单位 dataInfo:{"图表名称":{from:"left", subList:[{key:"数据key", value:"数据值", unit:"单位" }, {key:"数据key", value:"数据值", unit:"单位" } ]} } }
* @returns {title:标题, xUnit:x轴单位, leftYUnit:左边单位, rightYUnit:右边单位, leftYMinValue:左边最小值, leftYMaxValue:左边最大值, leftYStepValue:左边间隔,
* rightYMinValue:右边最小值, rightYMaxValue:右边最大值, rightYStepValue:右边间隔,
* dataList:[{subTitle:数据名称, total:总数, unit:单位, subDataList:[{name:y轴名称, value:值, unit:单位}] }] }
* 入参data里面的dataInfo中的unit可以为空 会读取yUnit 所以入参优先度 yUnit > unit 默认值都是空字符串
*/
export function getDoubleYBarChartOut(title, data, stepCountInfo?) {
stepCountInfo = stepCountInfo || {left:5, right:5};
let dataList = [];
let {xUnit, leftYUnit, rightYUnit, dataInfo} = data;
let thisLeftYUnit = leftYUnit || "";
let thisRightYUnit = rightYUnit || "";
let leftMin = new Date().valueOf();
let leftMax = 0;
let rightMin = new Date().valueOf();
let rightMax = 0;
for (let dataName in dataInfo) {
let {subList, from} = dataInfo[dataName];
let subDataList = [];
let total = 0;
let thisDataUnit = from == "left" ? thisLeftYUnit : thisRightYUnit;
subList.forEach(item => {
let {key, value, unit} = item;
if (from == "left") {
leftMin = Math.min(value, leftMin);
leftMax = Math.max(value, leftMax);
} else {
rightMin = Math.min(value, rightMin);
rightMax = Math.max(value, rightMax);
}
total += value;
subDataList.push({name:key, value, unit:unit || thisDataUnit});
});
dataList.push({subTitle:dataName, total, unit:thisDataUnit, subDataList});
}
let leftInfo = unifiedMaxAndMinValueAndStep(leftMax, leftMin,stepCountInfo.left);
let rightInfo = unifiedMaxAndMinValueAndStep(rightMax, rightMin,stepCountInfo.right);
return {title, xUnit, leftYUnit:thisLeftYUnit, rightYUnit:thisRightYUnit, leftYMinValue:leftInfo.minNumber, leftYMaxValue:leftInfo.maxNumber, leftYStepValue:leftInfo.stepNumber,
rightYMinValue:rightInfo.minNumber, rightYMaxValue:rightInfo.maxNumber, rightYStepValue:rightInfo.stepNumber, dataList}
}
/**
* getTableOut 获取列表返回
* @param title 数据标题
* @param data 数据体 格式:{titleList:[], dataList:[{a,b,c},{a,b,c},{a,b,c}] }
* @returns {title:数据标题, total:数据总条数, titleList:[表头...], valueList:[[a,b,c,d...],[a,b,c,d...]] }
* 解出来的对象的key是需要有顺序的,所以进这里之前要把值a-z排好序,按显示要求排序,
*/
export function getTableOut(title, data) {
let {titleList, dataList} = data;
let valueList = [];
dataList.forEach(info => {
let subList = [];
for (let key in info) {
subList.push(info[key]);
}
valueList.push(subList);
});
return { title, total:dataList.length, titleList, valueList };
}
/**
* getKeyValueOut 获取键值的返回结果
* @param title 数据标题
* @param data 数据体 [{key:"", value:"", unit:""}]
* @returns {title:数据标题, dataList:[], total:数据值总数, count:数据总条数 }
*/
export function getKeyValueOut(title, data) {
let dataList = [];
let total = 0;
data.forEach(info => {
let {key, value, unit} = info;
let typeChangeValue;
if (!isNaN(value)) {
typeChangeValue = parseFloat(value);
total+= typeChangeValue;
} else typeChangeValue = value;
dataList.push({name:key, value: Math.round(typeChangeValue * 100) /100, unit});
});
return {title, total: Math.round(total * 100) /100, count:dataList.length, dataList};
}
/**
* getObjectListOut 获取对象数组结果
* @param title 数据标题
* @param data 数据体 [{value:"", value:"", unit:""}]
* @returns {title:数据标题, dataList:[{name:"", value:"", key1:"", key2:""}] }
*/
export function getObjectListOut(title, data) {
//todo 没有特殊逻辑
return {title, dataList:data};
}
/**
* getRankOut 获取排名结果
* @param title 数据标题
* @param data 数据体 {unit, max, dataInfo:[{key, value, details}, {}, {}, {}] }
* @returns {title:数据标题, max, unit dataList:[{name, value, unit, rankNumber}] }
*/
export function getRankOut(title, data) {
let {unit, max, dataInfo} = data;
let dataList = [];
dataInfo.forEach((info, index) => {
let {key, value} = info;
let rankNumber = index + 1;
dataList.push({name:key, value, details:info.details, rankNumber});
});
return { title, unit, max, dataList };
}
/**
* getRadarChartOut 获取雷达图
* @param title 数据标题
* @param data 数据体 [{key, value, max, unit}]
* @returns {title:数据标题, dataList:[{name:"指标名称", max:"最大值", value:"当前值", unit:"单位"}]}
*/
export function getRadarChartOut(title, data) {
let dataList = [];
data.forEach(info => {
dataList.push({
name:info.key,
value:info.value,
max:info.max,
unit:info.unit
});
});
return {title, dataList};
}
/**
* getMapOut 地图数据
* @param title 数据标题
* @param data 数据体 [{name:数据名称, x:x坐标, y:坐标, coordinate:[经度, 纬度], unit:单位, value:值, details:"补充"}]
* @returns {title:数据标题, dataList:[{name:数据名称, x:x坐标, y:坐标, coordinate:[经度, 纬度], unit:单位, value:值, details:"补充"} ] }
*/
export function getMapOut(title, data) {
//todo 无特殊逻辑
return {title, dataList:data};
}
/**
* getScatterFigureOutData 获取撒点图的返回结果
* @param title 标题
* @param data 数据 格式 [{x, y, name}, {x, y, name}, {x, y, name}, {x, y, name}]
* @returns { title:标题, xMax:x轴最大值, xMin:x最小值, yMax:y最大值, yMin:y最小值, dataList:[{name:点的名称, value:[x坐标, y坐标]} ] };
*/
export function getScatterFigureOutData(title, data) {
let dataList = [];
let xMaxNumber = 0;
let xMinNumber = new Date().valueOf();
let yMaxNumber = 0;
let yMinNumber = new Date().valueOf();
data.forEach(item => {
let { x, y, name } = item;
let xCoordinateInfo = separateDataAndUint(x);
let yCoordinateInfo = separateDataAndUint(y);
const XNumber = xCoordinateInfo.dataNum;
const YNumber = yCoordinateInfo.dataNum;
yMaxNumber = Math.max(YNumber, yMaxNumber);
yMinNumber = Math.min(YNumber, yMinNumber);
xMaxNumber = Math.max(XNumber, xMaxNumber);
xMinNumber = Math.min(XNumber, xMinNumber);
let value = [XNumber, YNumber];
dataList.push({ value, name:name || "" });
});
let xMaxMinInfo = unifiedMaxAndMinValueAndStep(xMaxNumber, xMinNumber);
let yMaxMinInfo = unifiedMaxAndMinValueAndStep(yMaxNumber, yMinNumber);
return { title, xMax:xMaxMinInfo.maxNumber, xMin:xMaxMinInfo.minNumber, yMax:yMaxMinInfo.maxNumber, yMin:yMaxMinInfo.minNumber, dataList };
}
import { BizError } from "../util/bizError";
import pyfl from 'pyfl';
//disintegrate 分解二维数据源数据
/**
* planarArrForObjectList 解析二维数组
* @param planarArr 二维数组 例子:[[title1, title2, title3, title4],[value1, value2, value3, value4],[value5, value6, value7, value8]]
* @param titleIndex 标题集合所在第一层数组的下标
* @param titleList 自定义标题列表 不传则会取每个title的中文首字母作为key
* @returns {"dataList":[{title1:value1, title2:value2, title3:value3, title4:value4}, {title1:value5, title2:value6, title3:value7, title4:value8}], titleList:[]}
*/
export function planarArrForObjectList(planarArr, titleIndex = 0, titleList = []) {
let dataTitleList = [];
let dataMaxLength = 0;
for (let i = titleIndex; i< planarArr.length; i++) {
let subList = planarArr[i];
if (i == titleIndex) {
dataTitleList = subList;
continue;
}
dataMaxLength = Math.max(subList.length, dataMaxLength);
}
let useTitleList = !titleList.length ? changeChineseTitleIntoEnglish(dataTitleList) : titleList;
if (dataMaxLength == 2 && !titleList.length) useTitleList = ["key", "value"];
if (dataTitleList.length < dataMaxLength ) throw new BizError(`解析时数据异常 数据长度:${dataMaxLength} 大于 标题长度${dataTitleList}`);
if (titleList.length && titleList.length < dataMaxLength) throw new BizError(`解析时数据异常 传入标题长度${titleList.length} 数据最大长度${dataMaxLength}`);
let dataList = [];
for (let i = (titleIndex + 1); i< planarArr.length; i++) {
let subList = planarArr[i];
let addInfo:any = {};
subList.forEach((item, index) => {
let key = useTitleList[index];
let value = item;
addInfo[key] = value;
});
dataList.push(addInfo);
}
return {dataList, titleList:useTitleList };
}
function changeChineseTitleIntoEnglish(titles) {
let result = [];
titles.forEach(chineseStr => {
result.push(pyfl(chineseStr).toLowerCase());
});
return result;
}
/**
* planarArrDeconstruct 解构二维数组
* 第一列是名称
* @param planarArr 二维数组 例:[[name, 1月, 2月, 3月],[数据1, 1月数据, 2月数据,3月数据 ],[数据2, 1月数据, 2月数据,3月数据]]
* @param titleIndex 标题集合所在第一层数组的下标
* @returns [{"name":"", data:[{key:"1月", value:"1月数据"}, {key:"2月", value:"2月数据"} ]}];
*/
export function planarArrDeconstruct(planarArr, titleIndex = 0) {
let dataInfo = []
let titleList = [];
for (let i = titleIndex; i < planarArr.length; i++) {
let subList = planarArr[i];
if (titleIndex == i){
titleList = subList;
} else {
let thisDataName = "";
let thisDataList = [];
subList.forEach((item, index) => {
if (!index) {
thisDataName = item;
return;
}
let key = titleList[index];
thisDataList.push({key, value:item});
});
dataInfo.push({name:thisDataName, data:thisDataList});
}
}
return dataInfo;
}
/**
* planarArrDecollateForIndex 拆解二维数组
* @param planarArr 二维数组
* @param decollateIndex 拆解开始的下标
* @returns {headerList:decollateIndex下标之前的集合(包括decollateIndex), bodyList:decollateIndex下标之后的集合(不包括decollateIndex)}
*/
export function planarArrDecollateForIndex(planarArr, decollateIndex = 0) {
let headerList = planarArr.slice(decollateIndex, decollateIndex + 1);
let bodyList = planarArr.slice(decollateIndex + 1, planarArr.length);
return {headerList, bodyList};
}
//excel 和 接口都可以使用的格式化数据的方法
/**
* objBecomeOfList 对象变成数组 value不限制类型
* @param obj 对象 {"key1":"value1", "key2":"value2"}
* @param keyName 指定key的名称 默认 name
* @param valueName 指定value的名称 默认 data
* @returns [{name:"key1", "data":"value1"}, ...]
*/
export function objBecomeOfList(obj, keyName="name", valueName="data") {
let result = [];
for (let key in obj) {
let once:any = {};
once[keyName] = key;
once[valueName] = obj[key];
result.push(once);
}
return result;
}
/**
* objChangeKey obj改变key
* @param obj {"key1":"value1", "key2":"value2"}
* @param checkKeyInfo {"key1":"eKey1", "key2":"eKey2"}
* @returns
*/
export function objChangeKey(obj, checkKeyInfo) {
let result = {};
for (let key in obj) {
let newKey = checkKeyInfo[key] || key;
result[newKey] = obj[key];
}
return result;
}
/**
* objListChangeKey objList 改变key
* @param objList
* @param checkKeyInfo
* @returns
*/
export function objListChangeKey(objList, checkKeyInfo) {
return
}
\ No newline at end of file
import { systemConfig } from "../config/serverConfig";
/**
* separateDataAndUint 截取字符串中的单位
* @param str 待处理字符串
* @returns {dataNumber:数据, dataUnit:单位}
*/
export function separateDataAndUint(str) {
str = `${str}`;
if (!str) return {dataNum:0, dataUnit:""};
let dataNum = parseFloat(str.replace(/[\u4E00-\u9FA5a-zA-Z]+/,""));
let dataUnit = str.replace(/^(-)?\d+(\.\d+)?/, "");
return {dataNum, dataUnit};
}
/**
* unifiedMaxAndMinValueAndStep 求最大最小值以及间隙
* @param max 最大
* @param min 最小
* @param count 分多少份 默认5
* @returns {maxNumber:向上留值最大, minNumber:向下留值最小, stepNumber:间隔};
*/
export function unifiedMaxAndMinValueAndStep(max, min, count=5) {
let maxNumber = Math.ceil(max);
let minNumber = Math.floor(min);
function getNumberInLength(length) {
let lengthCount = 1;
for (let i = 1; i < length; i++) {
lengthCount = lengthCount * 10;
}
return lengthCount;
}
let maxNumberLength = getNumberInLength(`${maxNumber}`.length);
let minNumberLength = getNumberInLength(`${minNumber}`.length);
if (maxNumber <= 10 && maxNumber > 0) maxNumber = 10;
else maxNumber = Math.ceil(maxNumber / maxNumberLength) * maxNumberLength;
minNumber = Math.floor(minNumber / minNumberLength) * minNumberLength;
let stepNumber = Math.ceil((maxNumber - minNumber) / count);
return {maxNumber, minNumber, stepNumber};
}
/**
* 地图撒点转换函数
* @param TIMData
* @param fileName
* @returns
*/
export function convertTIMDataToModelFormat(TIMData, fileName, configs) {
const modelTabs = [
{
label: "全部",
children: []
},
{
label: "T1",
children: []
},
{
label: "T2",
children: []
},
{
label: "东交",
children: []
}
];
// 处理T1数据
if (TIMData.T1 && TIMData.T1.dataList) {
const t1Children = organizeDataByFloor(TIMData.T1.dataList, 'T1', fileName, configs);
modelTabs[1].children = t1Children;
// 同时添加到"全部"标签
modelTabs[0].children = modelTabs[0].children.concat(t1Children);
}
// 处理T2数据
if (TIMData.T2 && TIMData.T2.dataList) {
const t2Children = organizeDataByFloor(TIMData.T2.dataList, 'T2', fileName, configs);
modelTabs[2].children = t2Children;
// 同时添加到"全部"标签
modelTabs[0].children = modelTabs[0].children.concat(t2Children);
}
// 处理Dj数据(东交)
if (TIMData.Dj && TIMData.Dj.dataList) {
const djChildren = organizeDataByFloor(TIMData.Dj.dataList, 'Dj', fileName, configs);
modelTabs[3].children = djChildren;
// 同时添加到"全部"标签
modelTabs[0].children = modelTabs[0].children.concat(djChildren);
}
return modelTabs;
}
// 按楼层组织数据
function organizeDataByFloor(dataList, buildingType, fileName, configs) {
// 首先处理套房关系
const suiteMap = new Map(); // 套房主房间 -> 子房间列表
const childToParentMap = new Map(); // 子房间 -> 主房间
// 第一步:建立套房关系映射
dataList.forEach(item => {
if (item.zfjh) {
// 这是一个子房间,有主套房
if (!suiteMap.has(item.zfjh)) {
suiteMap.set(item.zfjh, []);
}
suiteMap.get(item.zfjh).push(item.fjh);
childToParentMap.set(item.fjh, item.zfjh);
}
});
// 第二步:按楼层分组并构建maps数据
const floorMap = new Map();
dataList.forEach(item => {
const floorKey = item.lc;
// 如果是套房的子房间,跳过单独处理(将在套房中统一处理)
if (item.zfjh) {
return;
}
if (!floorMap.has(floorKey)) {
floorMap.set(floorKey, []);
}
let mapItem;
// 检查这个房间是否是套房的主房间
if (suiteMap.has(item.fjh)) {
// 这是一个套房主房间
mapItem = {
name: item.fjh,
x: item.xzzb,
y: item.yzzb,
size: item.dwdx === 'default' ? 'medium' : item.dwdx, // 套房通常用medium尺寸
suites: suiteMap.get(item.fjh)
};
} else {
// 普通房间
mapItem = {
name: item.fjh,
x: item.xzzb,
y: item.yzzb,
size: item.dwdx
};
}
floorMap.get(floorKey).push(mapItem);
});
// 转换为model格式的children数组
const children = [];
// 根据建筑类型设置楼层顺序和属性
const floorConfig = getFloorConfig(configs, buildingType);
floorConfig.forEach(config => {
const floorData = floorMap.get(config.floorName) || [];
if (floorData.length > 0 || config.includeEmpty) {
children.push({
name: config.displayName,
altitude: config.altitude || '',
src: getFloorImageSrc(buildingType, config.imgName, fileName),
maps: floorData
});
}
});
return children;
}
// 获取楼层图片路径(这里需要根据你的实际图片路径进行调整)
function getFloorImageSrc(lc, floorName, fileName) {
// 这里返回一个默认的图片路径,你需要根据实际情况调整
// 例如:require(`../public/static/images/${buildingType.toLowerCase()}/${floorName}.png`)
let imgUrl = `${systemConfig.imgIp}/${fileName}/${lc}/${floorName}.png`;
return imgUrl;
}
// 获取楼层配置
function getFloorConfig(configs, buildingType) {
return configs[buildingType] || [];
}
import { httpServer } from "./net/http_server";
import { initConfig, systemConfig } from "./config/serverConfig";
async function lanuch() {
await initConfig();
httpServer.createServer( systemConfig.port );
console.log('This indicates that the server is started successfully.');
}
lanuch();
var formidable = require("formidable");
export async function parseFormParam(req, res, next) {
    var form = new formidable.IncomingForm();
    form.parse(req, (err, fields, files)=>{
        if (err) {
           next(err)
        }
        else {
            req.fields = fields;
            req.files = files;
            next();
        }
    })
}
\ No newline at end of file
import * as crypto from 'crypto';
import { getInterfaceByInterfaceName } from '../data/interface/cronJob';
import { BizError } from '../util/bizError';
/**
* 加密
* @param text 要加密的明文
* @param key 密码
* @param iv 偏移量
* key和iv都应为16字节长
* @returns
*/
export function encrypt(text, key, iv) {
let cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
let encrypted = cipher.update(text, 'utf8', 'base64');
encrypted += cipher.final('base64');
return encrypted;
}
/**
* 解密
* @param encrypted 要解密的密文
* @param key 密码
* @param iv 偏移量
* key和iv都应为16字节长
* @returns
*/
export function decrypt(encrypted, key, iv) {
let decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
let decrypted = decipher.update(encrypted, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
export async function getToken() {
let appId = "sec_dt_platform";
let plaintext = appId + new Date().valueOf();
let key = 'b81d56b0071dc916';
let iv = 'b81d56b0071dc916';
let signature = encrypt(plaintext, key, iv);
let data = await getInterfaceByInterfaceName("获取token接口", {appId, signature});
let token = "";
if (!data) throw new BizError("获取token失败");
let {success, message, code, timestamp, result, requestId} = data;
if (success) {
token = result;
} else {
throw new BizError(`${code} ${message} 获取token失败`)
}
return token;
}
\ No newline at end of file
export function httpErrorHandler(err, req, res, next) {
console.log("in httpErrorHandler");
console.log(err);
//todo 自定义错误编码
if (err) {
if (err.message == "您的登录已失效" ) {
res.success({success:false, msg:err.message, code:501});
next();
}
else if (err.message == "您的账户没有访问权限") {
res.success({success:false, msg:"非常抱歉,您没有权限,请联系工作人员!", code:502});
next();
} else if ( err.message == "token已过期") {
res.success({success:false, msg:"token失效", code:503});
next();
}
else {
res.success({success:false, msg:err.message, code:500});
next();
}
}
}
\ No newline at end of file
export function watch(req, res, next) {
res.success = success.bind({res:res, req:req});
return next();
}
function success(data) {
let resultPack;
if (data ) {
if ( data.success === undefined || data.success === true ) {
resultPack = {data, success:true, code:200};
}
else {
resultPack = data;
}
}else {
resultPack = {code:500, success:false, msg:'result is null'};
}
this.res.send(resultPack);
}
import express = require('express');
import bodyParser = require('body-parser');
import routers = require('../routers/router');
import compression = require('compression');
import * as path from "path";
import { watch } from '../middleware/watch';
import { httpErrorHandler } from '../middleware/httpErrorHandler';
import fallback from 'express-history-api-fallback';
export class httpServer {
static createServer(port:number) {
var httpServer = express();
httpServer.all('*',function (req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header('Access-Control-Allow-Credentials', true);
res.header("X-Powered-By", ' 3.2.1');
res.header("Authorization", 'Basic SzEyUlBDOksxMlJQQ1B3ZA==');
if(req.method === 'OPTIONS'){
res.statusCode = 200;
res.end();
}else{
next();
}
});
httpServer.use(bodyParser.json({limit:"10kb"}));
httpServer.use(compression())
httpServer.use(watch);
routers.setRouter(httpServer);
httpServer.use(httpErrorHandler);
httpServer.use(express.static(path.join(__dirname, "../../img/")) );
httpServer.use(express.static(path.join(__dirname, "../../pdf/")) );
const root = path.join(__dirname, "../../public/")
httpServer.use(express.static(root))
httpServer.use(fallback('index.html', { root }))
console.log('web listen on port:'+port);
httpServer.listen(port);
console.log('server listen on port:'+port);
return httpServer;
}
}
/**
* 总路由入口
*/
import asyncHandler = require('express-async-handler');
import * as TIMRouters from '../biz/TIM';
import * as md5Routers from '../biz/md5';
import * as TIM2Routers from '../biz/TIM2';
import * as zyRouters from '../biz/zy';
import * as bzbsRouters from '../biz/bzbs';
export function setRouter(httpServer){
httpServer.post('/api/bussiness/floor/resource/analyse', asyncHandler(TIMRouters.getResourceAnalyse));
httpServer.post('/api/bussiness/terminal/info', asyncHandler(TIMRouters.getTerminalInfo));
httpServer.post('/api/bussiness/room/room/info', asyncHandler(TIMRouters.getRoomInfo));
httpServer.post('/api/room/point', asyncHandler(TIMRouters.getRoomPoint)); //业务用房撒点
httpServer.post('/api/seat/point', asyncHandler(zyRouters.getSeatPoint)); //座椅撒点
httpServer.post('/api/sign/point', asyncHandler(bzbsRouters.getSignPoint)); //标志标识撒点
// httpServer.post('/api/seat/point', asyncHandler(zyRouters.getSeatPoint)); //登高车撒点
// 公开接口 - 生成签名(前端调用)
httpServer.post('/api/auth/generateSign', asyncHandler(md5Routers.generateSignApi));
// 新版本
httpServer.post('/api/bussiness/analyse/ledger/url', asyncHandler(TIM2Routers.ledgerUrl)); //台账跳转地址
httpServer.post('/api/bussiness/analyse/roles/list', asyncHandler(TIM2Routers.getRolesList));
httpServer.post('/api/bussiness/analyse/roles/edit', asyncHandler(TIM2Routers.getRolesEdit));
httpServer.post('/api/bussiness/analyse/total', asyncHandler(TIM2Routers.getTotal));
httpServer.post('/api/bussiness/analyse/analyse', asyncHandler(TIM2Routers.getAnalyse));
httpServer.post('/api/bussiness/analyse/terminal', asyncHandler(TIM2Routers.getTerminal));
httpServer.post('/api/bussiness/analyse/room', asyncHandler(TIM2Routers.getRoom));
httpServer.post('/api/bussiness/analyse/homePage', asyncHandler(TIM2Routers.getHomePage));
// 座椅
httpServer.post('/api/seat/analyse/total', asyncHandler(zyRouters.getTotal));
httpServer.post('/api/seat/analyse/terminal', asyncHandler(zyRouters.getTerminal));
httpServer.post('/api/seat/analyse/floor', asyncHandler(zyRouters.getFloor));
httpServer.post('/api/seat/analyse/seat', asyncHandler(zyRouters.getSeat));
// 标志标识
httpServer.post('/api/sign/analyse/total', asyncHandler(bzbsRouters.getTotal));
httpServer.post('/api/sign/analyse/terminal', asyncHandler(bzbsRouters.getTerminal));
httpServer.post('/api/sign/analyse/floor', asyncHandler(bzbsRouters.getFloor));
httpServer.post('/api/sign/analyse/sign', asyncHandler(bzbsRouters.getSign));
}
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "../util/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(/_dou/.test(str)) str = str.replace(/_dou/gm, ",");
if(/_zyh/.test(str)) str = str.replace(/_zyh/gm, "“");
if(/_yyh/.test(str)) str = str.replace(/_yyh/gm, "”");
if(/_dun/.test(str)) str = str.replace(/_dun/gm, "、");
if(/_ju/.test(str)) str = str.replace(/_ju/gm, "。");
return str
} else if (typeof value == 'string') {
try {//兼容数据库 '[1,2,3]'
value = JSON.parse(value);
}catch(err) {
return enumConf[parseInt(value)];
}
}
let str = "";
value.forEach((item, index) => {
let subStr = enumConf[item];
/**特化处理 */
if(/_dou/.test(subStr)) subStr = subStr.replace(/_dou/gm, ",");
if(/_zyh/.test(subStr)) subStr = subStr.replace(/_zyh/gm, "“");
if(/_yyh/.test(subStr)) subStr = subStr.replace(/_yyh/gm, "”");
if(/_dun/.test(subStr)) subStr = subStr.replace(/_dun/gm, "、");
if(/_ju/.test(subStr)) subStr = subStr.replace(/_ju/gm, "。");
str += subStr;
if (index == value.length-1) str+="";
else str += ","
});
return str;
}
/**
* 根据枚举值反向获取名称
* @param enumConf
* @param code
* @returns
*/
export function changeEnumNameByCode(enumConf, code: string) {
for (const [name, value] of Object.entries(enumConf)) {
if (value === code) {
return name;
}
}
return '未知';
}
import moment = require("moment");
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "../util/bizError";
import { FILETYPE } from "../config/enum";
const md5 = require("md5");
export function getUserToken(loginId:string) {
return md5(`${loginId}_${Math.ceil(Math.random()*1000)}${new Date().valueOf()}`);
}
export function getMySqlMs(time?) {
time = time || new Date().valueOf();
// time += (8*3600*1000);
return moment(time).format("YYYY-MM-DD HH:mm:ss");
}
export function getClientMs(time) {
if (!time) return new Date().valueOf();
return new Date(time).valueOf();
}
export function getPartyMemberId(param) {
return md5(`${param}-${new Date().valueOf()}-${Math.ceil(Math.random() * 10000)}`);
}
export function getDefPwd(phone:string) {
return md5(`${phone.slice(5, 11)}`);
}
export function getFileType(fileName) {
let fileType = 0;
fileName.forEach(info => {
let repList = info.split(".");
let type = repList[repList.length-1];
if (!type) throw new BizError(ERRORENUM.文件不存在, `文件名 ${info}`);
let typeNum = 0;
switch(type) {
case 'pdf': typeNum = FILETYPE.pdf; break;
case 'doc':
case 'docx': typeNum = FILETYPE.word; break;
case 'jpg':
case 'png': typeNum = FILETYPE.图片; break;
};
if (typeNum) {
if (!fileType) fileType = typeNum;
else if (fileType != typeNum) fileType = FILETYPE.多类型;
}
});
return fileType;
}
const xlsx = require('node-xlsx');
const path = require('path');
/**
* onceSheetBecomeOfblockData 将excel文件的指定sheet解析成数据块数据
* @param fileName 文件名称
* @param sheetName 表名称
* @returns [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
*/
export function onceSheetBecomeOfblockData(fileName, sheetName) {
let {sheetMap} = getExcel( path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", fileName ));
let thisBlockData = getBlockData(sheetMap[sheetName]);
return thisBlockData;
}
/**
* excelBecomeOfBlockData 将excel所有的sheet解析成数据块
* @param fileName 文件名称
* @returns {"sheetName1":[ {blockData:数据块(二维数组), blockTitle:"数据标题"}], ...}
*/
export function excelBecomeOfBlockData(fileName) {
let {sheetMap} = getExcel( path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", fileName ));
let result = {};
for (let sheetName in sheetMap) {
result[sheetName] = getBlockData(sheetMap[sheetName]);
}
return result;
}
/**
* 将指定文件夹里的excel文件的指定sheet解析成数据块数据
* @param fileName
* @param sheetName
* @param url
* @returns
*/
export function onceSheetBecomeOfblockDataToUrl(fileName, sheetName, url) {
let {sheetMap} = getExcel( path.join(__dirname.substring(0,__dirname.indexOf("out")), `res${url}`, fileName ));
let thisBlockData = getBlockData(sheetMap[sheetName]);
return thisBlockData;
}
/**
* planaryArrayBecomeOfBlockData 将符合excel规则的sheet二维数组转为 数据块
* @param dataList excel解出来的数据
* @returns thisBlockData 返回数据块集合 格式:blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
*/
export function planaryArrayBecomeOfBlockData(planaryArray) {
return getBlockData(planaryArray);;
}
//===
/**
* getBlockData 数据分块
* @param dataList 解析出来的excel二维数组
* @returns 返回数据块集合 格式:blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
*/
function getBlockData(dataList) {
let blockList = [];
for (let i = 0; i < 999; i++) {
let {blockData, blockTitle, notItem, delDataList} = checkBlock(dataList);
if (notItem) break;
dataList = delDataList;
if (blockTitle) blockList.push({blockData, blockTitle});
}
return blockList;
}
function getListFristNotNullItemIndex(list) { //获取起始坐标
if (!list.length) return null;
for (let i = 0; i < list.length; i++) {
if (list[i]) return i;
}
}
function getListFirstNullItemIndex(startX, list) { //获取第一个为空的坐标
if (!list.length) return null;
let checkItem = false;
let firstItemIndex = 0;
for (let i = startX; i <= list.length; i++) {
let item = list[i];
if (!checkItem && item) checkItem = true;
if (checkItem && !item) {
firstItemIndex = i;
break;
}
}
return firstItemIndex;
}
function listRegionIsNull(list, startX, endX) { //指定区间内数据是否未空
let isNull = true;
if ( !list.length ) return isNull;
for (let i = startX; i < endX; i++) {
let item = list[i];
if (item) {
isNull = false;
break;
}
}
return isNull;
}
function thisListNotItem(list) {
for (let i = 0; i < list.length; i++) {
if (list[i]) return false;
}
return true
}
function checkBlock(dataList) {
//纵向有效起始点
let startY = 0;
let startX = 0;
let isNotBlockTitle = false; //没有块标题
let isLook = false;
let endX = 0;//x轴最长结束下标 【包括下标】
let blockTitle = ''; //标题块名称
let notItem = true;
for (let i = 0; i < dataList.length; i++) {
let childList = dataList[i] || [];
if (!thisListNotItem(childList)) {
if ( !isLook ) {
let thisRoowStartX = getListFristNotNullItemIndex(childList);
let thisRoowLastItem = childList[thisRoowStartX + 1];
let LastList = dataList[i+1] || [];
// let lastRoowStartX = getListFristNotNullItemIndex(LastList);
let lastRoowHaveItem = LastList[thisRoowStartX];
if ( thisRoowLastItem || (LastList.length && lastRoowHaveItem) ) {
if (lastRoowHaveItem && thisRoowLastItem ) {
isNotBlockTitle = true; //不存在标题块
blockTitle = `${thisRoowStartX}_${i}`;
startY = i;
startX = thisRoowStartX;
}
else {
blockTitle = dataList[i][thisRoowStartX];
dataList[i][thisRoowStartX] = null;
if ( thisRoowLastItem ) { // 同行存在元素 标题在y轴上
startY = i;
startX = thisRoowStartX + 1;
} else { // 同行存在元素 标题在x轴上
startY = i + 1;
startX = thisRoowStartX;
}
}
isLook = true;
} else { //只有标题 无内容
console.log(dataList[i][thisRoowStartX]);
dataList[i][thisRoowStartX] = null;
}
} else {
//测量最大连续长度
let firstNullX = getListFirstNullItemIndex(startX, childList);
if (firstNullX) endX = Math.max(endX, firstNullX-1);
break;
}
notItem = false;
}
}
let endY = 0;//y轴连续下标 【包括下标】
let yInfoStart = false;
let yInfoEnd = false;
for (let y = startY; y < dataList.length; y++) {
//纵向找连续性
let thisRoow = dataList[y];
let regionIsNull = listRegionIsNull(thisRoow, startX, endX);
if (!regionIsNull) {
endY = y;
if (!yInfoStart) yInfoStart = true;
}
if (yInfoStart && regionIsNull) yInfoEnd = true;
if (yInfoEnd) break;
}
let blockData = [];
for (let y = startY; y <= endY; y++) {
let onceList = [];
for (let x = startX; x <= endX; x++) {
onceList.push(dataList[y][x]);
dataList[y][x] = null;
}
blockData.push(onceList);
}
return {blockData, blockTitle, delDataList:dataList,notItem};
}
//获取单个excel文件的数据
function getExcel(filePath) {
const workSheetsFromFile = xlsx.parse(filePath);
let sheetMap = {};
let sheetList = [];
for (let i = 0; i < workSheetsFromFile.length; i++) {
let sheetInfo = workSheetsFromFile[i];
sheetMap[sheetInfo.name] = sheetInfo.data;
sheetList.push(sheetInfo);
}
return {sheetMap, sheetList}
}
\ No newline at end of file
import { getBizMsg, getSysMsg } from "../config/errorEnum";
import { logError } from "./log";
export class BizError extends Error {
constructor(...msgs) {
let reqErrorMsg = '';
let logErrorMsg = '';
for (let i = 0; i <msgs.length; i++) {
if (!i) {
let msg = getBizMsg(msgs[i]);
reqErrorMsg = msg;
logErrorMsg = msg;
} else {
logErrorMsg += ` | ${msgs[i]} `;
}
}
logError(logErrorMsg);
super(reqErrorMsg);
}
}
export class SysError extends Error {
constructor(...msgs) {
let reqErrorMsg = '';
let logErrorMsg = '';
for (let i = 0; i <msgs.length; i++) {
if (!i) {
let msg= getSysMsg(msgs[i]);
reqErrorMsg = msg;
logErrorMsg = msg;
} else {
if (typeof msgs[i] == 'object') logErrorMsg += ` | ${JSON.stringify(msgs[i])} `;
else logErrorMsg += ` | ${msgs[i]} `;
}
}
logError(logErrorMsg);
super(reqErrorMsg);
}
}
\ No newline at end of file
let log4js = require('log4js');
let path = require('path');
//log路径
export const systemLogPath = {
errorLogFile:"error",
errorLogDir:"error",
handleLogFile:"handle",
handleLogDir:"handle"
}
//日志根目录
let baseLogPath = path.resolve(__dirname.substring(0, __dirname.indexOf("out")), 'logs');
// let baseLogPath = path.resolve('./', 'logs');
let errFile = path.resolve(baseLogPath, systemLogPath.errorLogDir, systemLogPath.errorLogFile);
let handFile =path.resolve(baseLogPath, systemLogPath.handleLogDir, systemLogPath.handleLogFile);
let config = {
appenders:
{
"rule-console": {"type": "console"},
"errorLogger": {
"type": "dateFile", // 日志类型
"filename": errFile, // 输出文件名
"pattern": "-yyyy-MM-dd.log", // 后缀
"alwaysIncludePattern": true, // 上面两个参数是否合并
"encoding": "utf-8", // 编码格式
"maxLogSize": 1000, // 最大存储内容
"numBackups": 3, // 当文件内容超过文件存储空间时,备份文件的数量
"path": `/${systemLogPath.errorLogDir}`
},
"handleLogger": {
"type": "dateFile",
"filename": handFile,
"pattern": "-yyyy-MM-dd.log",
"alwaysIncludePattern": true,
"encoding": "utf-8",
"maxLogSize": 1000,
"numBackups": 3,
"path": `/${systemLogPath.handleLogDir}`
}
},
categories: {
"default": {"appenders": ["rule-console"], "level": "all"}, //这个配置一定要有
"errorLogger": {"appenders": ["errorLogger"], "level": "error"},
"handleLogger": {"appenders": ["handleLogger"], "level": "all"}
},
"baseLogPath": path.resolve(baseLogPath, systemLogPath.handleLogDir, systemLogPath.handleLogFile)
};
log4js.configure(config); //加载配置文件
//调用预先定义的日志名称
let errorLogger = log4js.getLogger("errorLogger");
let handleLogger = log4js.getLogger("handleLogger");
let consoleLogger = log4js.getLogger("rule-console");
//错误日志
export function logError(...errStrs) {
let str = "";
errStrs.forEach(item => {
str += item + " | ";
});
errorLogger.error(`errorInfo => ${str}`);
}
//普通日志
export function logHandle(msgStr:string) {
handleLogger.info(`logInfo => ${msgStr}`);
}
//输出日志
export function logConsole(logStr:string) {
consoleLogger.info(`logInfo => ${logStr}`);
}
var xml2js = require("xml2js");
/**
*
* @param str 需要解析的xml文本
* @returns 解析好的对象
*/
export function analysisXml(str) {
return new Promise( (resolve, reject) => {
xml2js.parseString(str, (err, result) => {
if (err) return reject(err);
return resolve(result);
});
});
}
\ No newline at end of file
import * as request from 'request';
import { BizError } from './bizError';
const md5 = require("md5");
import axios from 'axios';
import moment from 'moment';
let systemId = "TIM";
let password = "CD0832C695E245D791514B3B421B9C47";
export function get(url:string, query?, headers?, timeOut?) {
timeOut = timeOut || 5000;
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
return new Promise((resolve, reject)=>{
let paramater:any = { url, json:true, timeout:timeOut };
if (query) paramater.qs = query;
if (headers) paramater.headers = headers;
request.get(paramater, function (err, res, body) {
const success = !err && res && res == 200;
let message = err || res.statusCode || "";
resolve({success, message, body});
})
})
}
// export function post(url, body, headers) {
// if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
// let header = {"content-type": "application/json"};
// return new Promise((resolve, reject)=>{
// request({
// url: url,
// method: "POST",
// json: true,
// headers: Object.assign(header, headers),
// body: body
// }, function(err, res, body) {
// const success = !err && res && res == 200;
// let message = err || res.statusCode || "";
// resolve({success, message, body});
// });
// })
// }
export function post(url, body = {}, headers = {}) {
return new Promise((resolve, reject) => {
// URL 验证
if (!url) {
resolve({success: false, message: "请求地址为空", body: null});
return;
}
if (url.search(/http:/) === -1 && url.search(/https:/) === -1) {
resolve({success: false, message: "请求地址格式错误", body: null});
return;
}
// 默认 headers
const defaultHeaders = {
'User-Agent': 'Mozilla/5.0 (compatible; TestClient/1.0)',
'Accept': 'application/json, */*'
};
// 合并 headers,传入的 headers 优先级更高
const finalHeaders = {...defaultHeaders, ...headers};
console.log('请求URL:', url);
console.log('请求头:', finalHeaders);
request({
url: url,
method: "POST",
json: true,
headers: finalHeaders,
body: body,
timeout: 15000,
gzip: true
}, function(err, response, body) {
if (err) {
console.error('请求错误:', err);
resolve({
success: false,
message: err.message,
body: null,
statusCode: null
});
return;
}
console.log('响应状态码:', response.statusCode);
console.log('响应头:', response.headers);
const result = {
success: response.statusCode === 200,
message: response.statusMessage || `HTTP ${response.statusCode}`,
body: body,
statusCode: response.statusCode,
headers: response.headers
};
resolve(result);
});
});
}
export function postForm(url, body) {
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
return new Promise((resolve, reject)=>{
request({
url: url,
method: "POST",
json: true,
form:body
}, function(err, res, body) {
const success = !err && res && res == 200;
let message = err || res.statusCode || "";
resolve({success, message, body});
});
})
}
export function postParmiss(url, reqBody, headers) {
if (!url || (url.search(/http:/) && url.search(/https:/)) ) throw new BizError(!url ? "请求地址为空" : "请求地址错误");
return new Promise((resolve, reject)=>{
request({
url: url,
method: "POST",
json: true,
form: reqBody
}, function(error, response, body) {
resolve(body);
});
})
}
export function getParmiss(url, query?, headers?) {
return new Promise((resolve, reject)=>{
let paramater:any = { url, json:true };
if (query) paramater.qs = query;
if (headers) paramater.headers = headers;
request.get(paramater, function (err, r, body) {
if (err) return resolve(err);
if (r && r.statusCode != 200) return resolve( { error: 'httpError:'+r.statusCode })
resolve(body);
});
})
}
/**
* query请求
* @param url
* @param body
* @param headers
* @returns
*/
export async function postAxios(url, body = {}, headers = {}) {
try {
let currentTime = moment().format("YYYYMMDDHHmmss");
let sign = md5(`${systemId}${password}${currentTime}`);
const response = await axios({
method: 'post',
url: url,
data: body,
headers: {
'Accept': 'application/json, */*',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (compatible; TestClient/1.0)',
"sign": sign,
"currentTime": currentTime,
"systemId": systemId,
...headers
},
timeout: 30000,
validateStatus: (status) => status < 500 // 接受除了服务器错误外的所有状态码
});
return {
success: response.status === 200,
message: response.statusText,
body: response.data,
statusCode: response.status,
headers: response.headers
};
} catch (error) {
if (error.response) {
return {
success: false,
message: error.response.statusText,
body: error.response.data,
statusCode: error.response.status,
headers: error.response.headers
};
} else {
return {
success: false,
message: error.message,
body: null,
statusCode: null
};
}
}
}
/**
* body请求
* @param url
* @param body
* @param headers
* @returns
*/
export async function postJsonAxios(url, body = {}, headers = {}) {
try {
let currentTime = moment().format("YYYYMMDDHHmmss");
let sign = md5(`${systemId}${password}${currentTime}`);
const response = await axios({
method: 'post',
url: url,
data: body,
headers: {
'Accept': 'application/json, */*',
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0 (compatible; TestClient/1.0)',
"sign": sign,
"currentTime": currentTime,
"systemId": systemId,
...headers
},
timeout: 10000,
validateStatus: (status) => status < 500
});
return {
success: response.status === 200,
message: response.statusText,
body: response.data,
statusCode: response.status,
headers: response.headers
};
} catch (error) {
if (error.response) {
// 服务器返回了错误状态码
return {
success: false,
message: error.response.statusText,
body: error.response.data,
statusCode: error.response.status,
headers: error.response.headers
};
} else if (error.request) {
// 请求发送了但没有收到响应
return {
success: false,
message: 'No response received from server',
body: null,
statusCode: null
};
} else {
// 请求配置出错
return {
success: false,
message: error.message,
body: null,
statusCode: null
};
}
}
}
//对象判空
export function objectKeyIsNull(obj, ...keyNames) {
let isNull = false;
for (let i = 0; i < keyNames.length; i++) {
let keyStr = keyNames[i];
let moreKeyList = keyStr.split(".");
let lastObj;
for (let j = 0; j < moreKeyList.length; j++) {
lastObj = obj[moreKeyList[j]];
if (!lastObj) {
isNull = true;
break;
}
}
if (isNull) break;
}
return isNull;
}
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"sourceMap": true,
"rootDir":"./src",
"outDir":"./out",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": false,
"noImplicitAny": false,
"strictNullChecks": false,
"types": ["node"]
},
"exclude": [
"node_modules",
"public" // 排除public目录
]
}
\ 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