初始化静态数据

parent 4ae28400
/**
* 迪勤云平台 API 客户端
*/
import * as crypto from 'crypto';
import { post } from '../util/request';
import { BizError } from '../util/bizError';
import { ERRORENUM } from '../config/errorEnum';
/**
* 获取网关设备列表(分页)
* @param page 当前页码,默认 1
* @param limit 每页条数,默认 10
* @returns 网关设备数据,包含 rows、total 等
*/
export async function processDeviceData(page: number = 1, limit: number = 10): Promise<any> {
const path = '';
const body = { page, limit };
const result = {data: {}};
return result.data;
}
export async function getToken() {
}
\ No newline at end of file
/**
* 飞奕云平台 API 客户端
* 参考 region.ts 的编码风格:async/await、BizError、清晰的注释
*/
import * as crypto from 'crypto';
import { post } from '../util/request';
import { BizError } from '../util/bizError';
import { ERRORENUM } from '../config/errorEnum';
import { FEIYI } from '../config/clientEnum';
// 全局变量缓存 token 和过期时间
let feiYiToken = "";
let expireTime = 0;
let getTokenTime = 0;
let isFetchingToken = false; // 避免并发获取 token 的标志位
let refreshTokenPromise: Promise<string> | null = null; // 用于避免并发刷新 token 的 Promise
/**
* 飞奕云平台配置(建议从环境变量或配置文件中读取)
*/
const FEIYI_CONFIG = {
baseUrl: 'https://m.achelp.cn/open',
clientId: process.env.FEIYI_CLIENT_ID || '419636996764598272', // 我方提供的 clientId
secretKey: process.env.FEIYI_SECRET_KEY || '02fc75446b4544b3a02444a2b5f9be2b', // 我方提供的 appSecret
};
/**
* 生成随机字符串 nonce
* @param length 长度,默认 16
*/
function generateNonce(): string {
return crypto.randomBytes(16).toString('hex');
}
/**
* 生成签名 sign
* 算法:
* 1. 除去空值请求参数(accessKey 即使为空串也保留)
* 2. 按照参数名的字母升序排列非空请求参数(包含 accessKey)
* 3. 使用 URL 键值对格式拼接(key1=value1&key2=value2...)
* 4. 拼接上 SecretKey 得到 stringSignTemp
* 5. 对 stringSignTemp 进行 MD5 运算,并将结果所有字符转换为大写
* @param params 请求参数对象
* @param secretKey 密钥
*/
function generateSign(params: Record<string, any>, timestamp: string, nonce: string, secretKey: string, charset: string = 'UTF-8'): string {
// 1. 过滤掉值为 null 或 undefined 的参数(空字符串保留)
const filteredParams: Record<string, any> = {};
for (const key in params) {
if (params[key] !== null && params[key] !== undefined) {
filteredParams[key] = params[key];
}
}
// 2. 按 key 升序排序
const sortedKeys = Object.keys(filteredParams).sort();
// 3. 拼接成 key1=value1&key2=value2...
const paramStr = sortedKeys.map(key => `${key}=${filteredParams[key]}`).join('&');
// 4. 拼接timestamp、nonce和SecretKey
const stringSignTemp = paramStr + `&timestamp=${timestamp}&nonce=${nonce}&SecretKey=${secretKey}`;
console.log('MD5加密请求参数:', stringSignTemp);
// 6. MD5 并转大写
return crypto.createHash('md5').update(stringSignTemp).digest('hex').toUpperCase();
}
/**
* 获取飞奕云平台 access_token
* @returns {Promise<string>} access_token
* @throws 如果请求失败或响应码非 00000,则抛出 BizError
*/
export async function getFeiYiToken(): Promise<string> {
const url = `${FEIYI_CONFIG.baseUrl}${FEIYI.获取Token}`;
// 校验token是否有效,有效则直接返回
const now = Date.now();
if (feiYiToken && expireTime > now) {
console.log(`使用缓存 token,剩余有效时间: ${(expireTime - now) / 1000} 秒`);
return feiYiToken;
}
// 根据文档,获取 token 的请求参数
const params = {
AccessKey: '', // 文档要求传空串
clientId: FEIYI_CONFIG.clientId
};
// 生成签名
const timestamp = Date.now().toString(); // 毫秒时间戳
const nonce = generateNonce();
const sign = generateSign(params, timestamp, nonce, FEIYI_CONFIG.secretKey);
console.log('MD5加密签名:', sign);
const requestBody = {
...params,
timestamp: timestamp,
nonce: nonce,
sign: sign
};
let result: any;
try {
result = await post(url, requestBody, {});
} catch (err) {
throw new BizError(ERRORENUM.网络错误, `获取 token 网络失败: ${err.message}`);
}
console.log('获取 token 响应:', result);
// 检查响应结构:文档中返回 { code, data: { access_token } }
if (!result || result.code !== '00000') {
throw new BizError(ERRORENUM.第三方接口错误, `获取 token 失败: ${result?.message || '未知错误'}`);
}
const accessToken = result.data?.access_token;
if (!accessToken) {
throw new BizError(ERRORENUM.第三方接口错误, '响应中未包含 access_token');
} else {
// 更新全局 token 和过期时间
feiYiToken = accessToken;
getTokenTime = now;
// 默认 2分钟 过期,如果响应中包含 expires_in 字段,则使用该值(单位毫秒)
expireTime = now + (result.data.expires_in ? result.data.expires_in : 2 * 60 * 1000);
console.log(`获取新 token: ${accessToken}, 过期时间: ${new Date(expireTime).toISOString()}`);
}
return accessToken;
}
/**
* 带 Token 的 POST 请求封装
* 自动获取/刷新 token
* @param path 接口路径(相对路径)
* @param body 请求体
* @param retry 是否重试(用于 token 过期重试)
*/
async function feiYiPost(path: string, body: any, retry: boolean = true): Promise<any> {
// 获取 token
const token = await getFeiYiToken();
const url = `${FEIYI_CONFIG.baseUrl}${path}`;
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
};
let result: any;
try {
result = await post(url, body, headers);
console.log(`请求 ${path} 成功,响应:`, result);
} catch (err) {
throw new BizError(ERRORENUM.网络错误, `请求 ${path} 失败: ${err.message}`);
}
// 如果 token 过期(示例错误码可能为 token 过期,文档未明确,假设 code 为 401 或其他)
// 这里简单判断如果 code 不为 '00000' 且包含 token 相关错误,则重试一次
if (result.code !== '00000') {
if (retry && (result.code === '401' || result.message?.includes('token'))) {
// 可选:清除 token 缓存,重新获取
return feiYiPost(path, body, false);
}
throw new BizError(ERRORENUM.第三方接口错误, `接口 ${path} 调用失败: ${result.message || JSON.stringify(result)}`);
}
return result;
}
/**
* 获取网关设备列表(分页)
* @param page 当前页码,默认 1
* @param limit 每页条数,默认 10
* @returns 网关设备数据,包含 rows、total 等
*/
export async function getGatewayDeviceList(page: number = 1, limit: number = 10): Promise<any> {
const path = FEIYI.网关设备列表;
const body = { page, limit };
const result = await feiYiPost(path, body);
// 返回 data 部分,包含 page, limit, total, rows
return result.data;
}
/**
* 内机列表分页查询
* @param params
* @returns
{
"code": "00000", //状态码 00000 为正常 其他为异常
"message": "success", //返回状态 success 为成功, 其他为失败
"data": { // 返回数据
"page": 1, //当前页码
"limit": 0, //每页条数
"total": 579, //总数
"rows": [{
"indoorUnitId": "98566729709518848", //内机 ID
"roomId": "98452624688414720", //房间 ID
"floorId": "98452624680026112", //楼层 ID
"buildingId": "34390184208629760", //楼栋 ID
"indoorUnitAddressFull": "11-1-1-1", //内机四段地址
"onOffLock": 1, //是否开关锁定 1 锁定 0 未锁定
"onOff": 0, //开关状态 1 开 0 关
"workModeLock": 0, //是否工作模式锁定 1 锁定 0 未锁定
"workMode": 2, //工作模式 1 制冷 2 制热 3 送风 4 除湿
"tempSetLock": 0, //是否温度锁定 1 锁定 0 未锁定
"tempSet": 16.0, // 设定温度
"tempSetLo": 16.0, // 锁定下限温度
"tempSetHi": 32.0, // 锁定下限温度
"fanSpeed": 4, // 风速 1 高风 2 中风 4 低风
"hasTimingTasks": 0, //是否有定时任务
"alarmCode": "LOST", //空调故障码
"roomTemp": 27 //室内温度(实际为空调回风温度,有一定的误差仅做参考)
"lockedSwitch": 0, // 锁定的开关:0 关 1 开
"lockedMode": 0, // 锁定模式 1 制冷 2 制热 3 送风 4 除湿 10 制热/送风 11 制冷/送风 12 制冷/除湿 13 制冷/除湿/送风 14 除湿/送风
}]
}
}
*/
export async function getIndoorUnitList(params: any): Promise<any> {
const path = FEIYI.内机列表;
const body = { ...params };
const result = await feiYiPost(path, body);
return result.data;
}
/**
* 空调内机控制
* @param params
* @returns
*/
export async function controlIndoorUnit(params: any): Promise<any> {
const path = FEIYI.内机控制;
if (!params.indoorUnitAddressFull || !Array.isArray(params.indoorUnitAddressFull) || params.indoorUnitAddressFull.length === 0) {
throw new BizError(ERRORENUM.参数错误, "设备编号不能为空");
}
const body = { ...params };
const result = await feiYiPost(path, body);
console.log('控制内机响应:', result);
let success = result.code === '00000'? true : false;
return { success, data: result.message };
}
/**
* 建筑物树结构查询
* @param params
* @returns
{
"code": "00000", //状态码 00000 为正常,其他为异常
"message": "success", //状态信息 success 为成功,其他为异常
"data": [{
"buildingId": "97474765970866176", //建筑物 ID
"parentId": "0", //建筑物父 ID
"buildingName": "飞奕 1", // 建筑物名称
"buildingType": 1, //建筑物类型 1 楼栋 2 楼层 3 房间
"children": [ //子建筑物
{
"buildingId": "97474766339964928",
"parentId": "97474765970866176",
"buildingName": "1 层",
"buildingType": 2,
"children": [{
"buildingId": "97474766696480768",
"parentId": "97474766339964928",
"buildingName": "1-0",
"buildingType": 3,
"children": []
}]
}
]
}],
"timestamp": 1714290880301
}
*/
export async function getRegionTree(): Promise<any> {
const path = FEIYI.建筑物树结构;
const body = { };
const result = await feiYiPost(path, body);
return result.data;
}
/**
* 电表分页查询
* @param params
* @returns
{
"code": "00000", //状态码 00000 为成功,其他为失败
"message": "success", //提示信息 success 为成功 其他为失败
"data": {
"page": 0, //当前页码
"limit": 0, //每页条数
"total": 6, //总条数
"rows": [{
"meterId": "110510431701041152", //电表 ID
"gatewayComId": , //电表网关设备通信 ID
"gatewayCode": , //电表网关设备编码
"protocolType": "DLT645-2007", //电表协议类型
"ammeterReadingAfterTransformationRatio": 6547.68, //电表变比后读数
"transformationRatio": 80.0, //电表变比
"meterComId": "210505015447" //电表地址
}, {
"gatewayComId": , //电表网关设备通信 ID
"gatewayCode": , //电表网关设备编码
"meterId": "110510346153885697",
"transformationRatio": 50.0,
"meterComId": "210505015560"
}]
},
"timestamp": 1713245734235
}
*/
export async function getElectricMaterList(params: any): Promise<any> {
const path = FEIYI.电表列表;
const body = { ...params };
const result = await feiYiPost(path, body);
return result.data;
}
/**
* 抄表记录查询
* @param params
* @returns
{
"code": "00000", //状态码 00000 表示成功,其他为失败
"message": "success", //提示信息 success 为成功,其他为失败
"data": {
"page": 1, //当前页码
"limit": 0, //每页条数
"total": 6, //总条数
"rows": [{
"electricMeterStateId": "112111594590437376", //抄表记录 ID
"gatewayId": "97477557167063040", //主机设备 ID
"gatewayCode": "fa000001400001240231212000200026" //主机设备编码
"meterComId": "210505015595", //电表地址
"gatewayComId": 11, // 电表网关通信 ID
"transformationRatio": 100.0, //电表变比
"powerConsumptionAfterTransformationRatio": 0.08, //电表变比后用电量
"ammeterReadingAfterTransformationRatio": 19167.4, // 电表变比后读数
"ammeterReadingBeforeTransformationRatio": 191.67, //电表变比前读数
"energyLoss": 0.00, //损耗电量
"deviceTime": 1706371200000, //设备时间
}]
},
"timestamp": 1713145563759
}
*/
export async function getMaterStateList(params: any): Promise<any> {
const path = FEIYI.抄表记录;
const body = { ...params };
const result = await feiYiPost(path, body);
return result.data;
}
/**
* 内机开关机记录查询
* @param params
* @returns
{
"code": "00000",
"message": "success",
"path": null,
"data": {
"page": 1,
"limit": 0,
"total": 278,
"rows": [{
"indoorUnitEventId": "140718238987321344", //内机事件 ID
"indoorUnitId": "97478680942739586", //内机 ID
"gatewayComId": 1, //主机通信 ID
"roomId": "97474774841819136", //内机所在房间 ID
"floorId": "97474774485303296", //内机所在楼层 ID
"buildingId": "97474765970866176", //内机所在楼栋 ID
"indoorUnitAddressFull": "1-8-128-16", //内机四段地址
"onOff": 0, //内机开关标志 0 关 1 开
"workMode": 4, //工作模式 1 制冷 2 制热 3 送风 4 除湿
"tempSet": 18.0, //内机温度设置
"fanSpeed": 2, //内机风速 风速 1 高风 2 中风 4 低风
"createTime": 1713173801018 //事件发生时间
}]
},
"timestamp": 1713173831195
}
*/
export async function getIndoorUnitStateList(params: any): Promise<any> {
const path = FEIYI.内机开关机记录;
const body = { ...params };
const result = await feiYiPost(path, body);
return result.data;
}
/**
* 区域位置业务
*/
import * as crypto from 'crypto';
import { post } from '../util/request';
/**
* 区域位置
* @returns 区域位置数据
*/
export async function getRegionLocation(gatewayPage: number) {
const result = [{"regionKey":"32","regionName":"三十二位","xz":1587,"yz":487,"qualityIndex":"优","gatewayPage":gatewayPage}];
return result;
}
\ No newline at end of file
/**
* 运行分析页面
*/
import * as crypto from 'crypto';
import { post } from '../util/request';
import { BizError } from '../util/bizError';
import { ERRORENUM } from '../config/errorEnum';
import { max } from 'moment';
import { title } from 'process';
/**
* 运行分析
* @returns 大屏所需的所有指标数据
*/
export async function getRunAnalysis() {
// 一、能耗管理与趋势
// 1、能耗管理
let energyManagement = {
"jrnh": "16212",
"zrnh": "13829",
"zrtb": "17.24",
"bynh": "21128",
"synh": "0",
"sytb": "0"
};
// 2、能耗趋势
let electricityTrend = {
"last24HoursMax": 11258,
"last24Hours": [
{
"key": "2026-06-28 17时",
"value": "10429"
},
{
"key": "2026-06-28 18时",
"value": "10483"
}
],
"last7DaysMax": 18601,
"last7Days": [
{
"key": "2026-06-23",
"value": "13636"
},
{
"key": "2026-06-24",
"value": "15402"
}
],
"last30DaysMax": 18601,
"last30Days": [
{
"key": "2026-05-31",
"value": "0"
},
{
"key": "2026-06-01",
"value": "0"
}
],
"lastYearMax": 21128,
"lastYear": [
{
"key": "2025-07",
"value": "0"
},
{
"key": "2025-08",
"value": "0"
}
]
};
// 二、设备耗电量监控
let deviceTypeMap = new Map();
let deviceElectricityMap = new Map();
let deviceElectricityDatas = deviceTypeList.map((deviceType) => {
return {
"deviceType": deviceType,
"deviceCount": deviceTypeMap.get(deviceType) || 0,
"electricity": deviceElectricityMap.get(deviceType) || 0
}
});
let deviceElectricity = {
titleList: ["设备","数量","耗电情况"],
dataList: deviceElectricityDatas
};
// 三、设备监测情况与趋势
// 1、设备监测情况
let deviceMonitor = {
total: 100,
online: 80,
offline: 15,
fault: 5,
};
// 2、设备监测趋势
let deviceMonitorTrend = [{
key: "2026-06-28 07时",
value: 80
},{
key: "2026-06-28 17时",
value: 75
}];
// 四、预警工单处理
// 1、预警处理状态
let alertStatus = {
resolved: 1,
responded: 1,
unresolved: 1
};
// 2、预警工单列表
let alertWorkOrders = [
{ riskContent: "空调压缩机异常", alertTime: "26/02/01", status: "已解决" },
{ riskContent: "温度传感器离线", alertTime: "26/02/01", status: "已响应" },
{ riskContent: "湿度超标", alertTime: "26/02/02", status: "未处理" }
];
// 五、空气质量环境监控
// 1、空气质量指数和趋势
let environmentalQuality = {
qualityIndex: {
current: "优",
max: 100,
min: 0,
index: 80
},
iaqQualityTrend: [{
key: "2026-06-28 07时",
value: 100
},{
key: "2026-06-28 17时",
value: 79
}]
};
// 2、环境数据监测
let environmentalTrend = {
"todayEnvironmental": "优秀",
"currentTemperature": "24.5℃",
"currentHumidity": "55%",
"currentPm25": "0μg/m³",
"currentCo2": "800ppm",
"temperatureTrend": [
{
"time": "0:00",
"value": "0"
}
],
"humidityTrend": [
{
"time": "0:00",
"value": "0"
}
],
"pm25Trend": [
{
"time": "0:00",
"value": "0"
}
],
"co2Trend": [
{
"time": "0时",
"value": "0"
}
],
"qualityIndex": 500,
"currentHcho": 0,
"currentLightLevel": 0,
"currentPm10": 0,
"currentPressure": 0,
"currentTvoc": 2,
"hchoTrend": [
{
"time": "0:00",
"value": "0"
}
],
"lightLevelTrend": [
{
"time": "0:00",
"value": "0"
}
],
"pm10Trend": [
{
"time": "0:00",
"value": "0"
}
],
"pressureTrend": [
{
"time": "0:00",
"value": "0"
}
],
"tvocTrend": [
{
"time": "0:00",
"value": "0"
}
]
};
// 六、机房环境功率监控
// 1、机房环境监控
let compRoomEnvironmental = [{
index: 1,
key: "温度",
value: "24.5℃",
},{
index: 2,
key: "湿度",
value: "55%",
},{
index: 3,
key: "配置",
value: "烟感",
},{
index: 4,
key: "常开",
value: "水浸",
}];
// 2、机房功率监控
let compRoomPower = [{
key: "2026-06-28 07时",
value: 200
},{
key: "2026-06-28 17时",
value: 400
}];
// 七、设备汇总
let summaryData = {"runningDevices":83,"offlineDevices":0,"normalRate":"100.00%","faultDevices":0}
// 返回所有指标监控信息
return {
nhgl: energyManagement,
nhqs: electricityTrend,
sbhdljk: deviceElectricity,
sbjcqk: deviceMonitor,
sbjcqs: deviceMonitorTrend,
yjclzt: alertStatus,
yjgd: alertWorkOrders,
kqzl: environmentalQuality,
hjjc: environmentalTrend,
jfhjjk: compRoomEnvironmental,
jfgljk: compRoomPower,
sbhz: summaryData
};
}
/**
* 运行分析弹窗
* @returns 区域设备的指标数据
*/
export async function getAnalysisPopup() {
return {
"regionName": "汇报厅",
"sbztjc": {
"total": 100,
"online": 80,
"offline": 15,
"fault": 5
},
"sbztjcqs": [
{
"key": "2026-06-28 05:00",
"online": 80,
"offline": 15,
"fault": 5
}
],
"nhjc": [
{
"key": "2026-06-28 05:00",
"value": "104"
}
]
};
}
/**
* 智能监控
* @returns 大屏所需的所有指标数据
*/
export async function getRunMonitoring() {
// 一、智能监测情况
let znjcqk = {
"titleList": ["监测区域","状态","设备使用情况","在线率"],
"dataList": [{"regionName":"汇报厅","status":0,"deviceUseStatus":"95%","onlineRate":"20/1"}]
};
// 二、故障原因分析
let gzyyfx = {
"gzfl": 10,
"gzflzb": [{
faultCode: "L07",
faultCount: 5,
faultRate: "50%"
},{
faultCode: "13",
faultCount: 5,
faultRate: "50%"
}]
};
// 三、运维处置状态
let ywczzt = {
"todo": 10,
"doing": 5,
"done": 5,
"titleList": ["风险内容","告警时间","告警位置","设备编号","状态"],
"dataList": [{"faultDescription":"一一","occurredTime":"2025-05-26 02:00:00","regionName":"汇报厅","deviceId":"8-3-0-5","status":0}]
}
// 四、环境监测
let environmentalTrend = {
"temperatureTrend": [
{
"time": "0:00",
"value": "0"
}
],
"humidityTrend": [
{
"time": "0:00",
"value": "0"
}
],
"pm25Trend": [
{
"time": "0:00",
"value": "0"
}
],
"co2Trend": [
{
"time": "0时",
"value": "0"
}
],
"hchoTrend": [
{
"time": "0:00",
"value": "0"
}
],
"lightLevelTrend": [
{
"time": "0:00",
"value": "0"
}
],
"pm10Trend": [
{
"time": "0:00",
"value": "0"
}
],
"pressureTrend": [
{
"time": "0:00",
"value": "0"
}
],
"tvocTrend": [
{
"time": "0:00",
"value": "0"
}
]
};
// 五、设备汇总
let summaryData = {"runningDevices":83,"offlineDevices":0,"normalRate":"100.00%","faultDevices":0}
// 返回所有指标监控信息
return {
znjcqk: znjcqk,
gzyyfx: gzyyfx,
ywczzt: ywczzt,
hjjc: environmentalTrend,
sbhz: summaryData
}
}
/**
* 智能监控弹窗
* @returns 区域设备的指标数据
*/
export async function getMonitorPopup() {
return {
"regionName": "汇报厅",
"kqzljc": {
"environmental": "优秀",
"temperature": "24.5℃",
"humidity": "55%",
"pm25": "0μg/m³",
"co2": "800ppm",
"tvoc": "2ppb",
"hcho": "0ppb",
"lightLevel": "0lux",
"oxygen": "0%" // 含氧量
},
"sbjc": {
"titleList": ["编号", "设备", "状态", "参数", "监测数据"],
"dataList": [
{
"deviceId": "8-1-0-2",
"deviceName": "空调内机8-1-0-2",
"status": 0,
"parameter": "8-1-0-2",
"monitoringData": ""
},{
"deviceId": "24E124710E466083",
"deviceName": "环境监测cgq6",
"status": 0,
"parameter": "‌o3,co2,hpa,pir,hcho,pm10,pm25,tvoc,humidity,lighting,pressure,temperature",
"monitoringData": "10、2000、1260、5、1.25、1000、1000、500、100、L5、5000、60"
}
]
}
};
}
/**
* 控制设备运行
* @param deviceId 设备编号
* @param deviceType 设备类型(可选)
* @param status 控制状态(可选)
* @returns 控制结果
*/
export async function controlDeviceRunning(params: {
deviceId: string;
deviceType?: string;
status?: number;
}) {
// 第一步:查询设备并判断是否存在
// 第二步:设置设备运行状态并下发
return { isSuccess: false };
}
let deviceTypeList: string[] = [
"IEQ传感器",
"烟感器",
"摄像头",
"空调",
"音响",
"照明",
"等离子",
"人流监测",
"电表",
"排风"
]
\ No newline at end of file
// 请求第三方客户端接口枚举
export enum FEIYI {
获取Token = '/oauth2/openapi/token',
网关设备列表 = '/openApi/gw/page',
内机列表 = '/openApi/indoorUnit/list',
内机控制 = '/openApi/indoorUnit/control',
建筑物树结构 = '/openApi/building/tree',
电表列表 = '/openApi/electricMeter/getAll',
抄表记录 = '/openApi/electricMeterState/list',
内机开关机记录 = '/openApi/indoorUnit/event/switch',
}
export enum DIQIN {
获取Token = '/v2/tokens/access_token',
获取区域信息 = '/v2/locations',
获取区域明细信息 = '/v2/locations/', // {location_id}
获取环境设备信息 = '/v2/devices/', // {device_id}
获取环境设备数据信息 = '/v2/data_sources/' // {data_source_id}
}
\ No newline at end of file
......@@ -44,7 +44,9 @@ export enum ERRORENUM {
空文件失败,
文件上传失败,
只能上传docdocxexcelpngjpg图片,
该时间段已有预约
该时间段已有预约,
网络错误,
第三方接口错误
}
/**
......
......@@ -79,6 +79,17 @@ export const TablesConfig = [
defaultValue: null,
comment: '父级区域ID,null表示顶级区域,用于层级关系'
},
parent_key: {
type: Sequelize.STRING(100),
allowNull: true,
defaultValue: null,
comment: '父级区域key,作为parent_id补充'
},
region_param: {
type: DataTypes.JSON,
allowNull: true,
comment: '区域参数定义,包含坐标等'
},
sort_order: {
type: DataTypes.INTEGER,
allowNull: false,
......@@ -418,14 +429,24 @@ export const TablesConfig = [
allowNull: false,
comment: '设备标识'
},
fault_type: {
fault_origin_id: {
type: Sequelize.STRING(100),
allowNull: false,
comment: '原始故障id'
},
fault_code: {
type: DataTypes.STRING(50),
allowNull: true,
comment: '故障代码'
},
fault_type: {
type: Sequelize.STRING(100),
allowNull: true,
comment: '故障类型'
},
fault_level: {
type: Sequelize.ENUM('一级', '二级', '三级'),
allowNull: false,
allowNull: true,
comment: '故障等级'
},
fault_info: {
......
......@@ -16,4 +16,17 @@ export async function addData(tableName:string, data:any) {
await tableModel.bulkCreate(dataArray);
return { isSuccess:true };
}
/**
* 插入单条数据并返回完整记录(含自增ID)
* 使用 create 替代 bulkCreate,确保返回值包含自增主键
* @param tableName 表名
* @param data 单条数据对象
* @returns { isSuccess, data: 插入后的完整记录 }
*/
export async function insertOne(tableName: string, data: any) {
let tableModel = mysqlModelMap[tableName];
const result = await tableModel.create(data);
return { isSuccess: true, data: result };
}
\ No newline at end of file
/**
* 访问迪勤客户端API接口
*/
import asyncHandler from 'express-async-handler';
import * as diqinClientBiz from '../biz/diqinClient';
import { eccReqParamater } from '../util/verificationParam';
export function setRouter(httpServer) {
/** 获取环境监测数据 */
httpServer.post('/api/dq/diqin/getProcessDevices', asyncHandler(getProcessDevices));
}
/**
* 获取环境监测数据
* @param page 当前页码,默认 1
* @param limit 每页条数,默认 10
*/
async function getProcessDevices(req, res) {
let reqConf = {page:'Number', limit:'Number', roomId: 'String', indoorUnitAddressFull: 'String'};
const NotMustHaveKeys = [ "page", "limit", "roomId", "indoorUnitAddressFull" ];
let params = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
const result = await diqinClientBiz.processDeviceData(params);
res.success(result);
}
\ No newline at end of file
/**
* 访问飞翼客户端API接口
*/
import asyncHandler from 'express-async-handler';
import * as feiyiClientBiz from '../biz/feiyiClient';
import { eccReqParamater } from '../util/verificationParam';
export function setRouter(httpServer) {
/** 网关设备列表 */
httpServer.post('/api/dq/feiyi/gateway/list', asyncHandler(getFeiyiGatewayList));
/** 空调内机列表 */
httpServer.post('/api/dq/feiyi/indoorUnit/list', asyncHandler(getFeiyiIndoorUnitList));
/** 空调内机控制 */
httpServer.post('/api/dq/feiyi/indoorUnit/control', asyncHandler(getFeiyiIndoorUnitControl));
}
/**
* 网关设备列表
*/
async function getFeiyiGatewayList(req, res) {
let reqConf = {page:'Number', limit:'Number'};
const NotMustHaveKeys = [ "page", "limit" ];
let { page, limit } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
const result = await feiyiClientBiz.getGatewayDeviceList(page, limit);
res.success(result);
}
/**
* 空调内机列表
* @param page 当前页码,默认 1
* @param limit 每页条数,默认 10
* @param buildingId 楼栋ID(可选)
* @param floorId 楼层ID(可选)
* @param roomId 区域ID(可选)
* @param gatewayCode 网关设备ID(可选)
*/
async function getFeiyiIndoorUnitList(req, res) {
let reqConf = {page:'Number', limit:'Number', roomId: 'String', indoorUnitAddressFull: 'String'};
const NotMustHaveKeys = [ "page", "limit", "roomId", "indoorUnitAddressFull" ];
let params = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
const result = await feiyiClientBiz.getIndoorUnitList(params);
res.success(result);
}
/**
* 空调内机控制
* @param indoorUnitAddressFull 要控制的内机地址集合
* @param workMode 1 制冷 2 制热 3 送风 4 除湿
* @param openApiAction control 控制指令 / lock 锁定指令
*/
async function getFeiyiIndoorUnitControl(req, res) {
let reqConf = { indoorUnitAddressFull: 'Array', workMode: 'Number', openApiAction: 'String' };
const NotMustHaveKeys = [ "workMode", "openApiAction" ];
let params = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
const result = await feiyiClientBiz.controlIndoorUnit(params);
res.success(result);
}
/**
* 区域位置路由
*/
import asyncHandler from 'express-async-handler';
import * as regionBiz from '../biz/region';
import { eccReqParamater } from '../util/verificationParam';
export function setRouter(httpServer) {
/** 区域位置 */
httpServer.post('/api/dq/region/location', asyncHandler(getRegionLocation));
}
/**
* 区域位置
*/
async function getRegionLocation(req, res) {
let reqConf = {gatewayPage:'Number'};
const NotMustHaveKeys = [];
let { gatewayPage } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
const result = await regionBiz.getRegionLocation(gatewayPage);
res.success(result);
}
\ No newline at end of file
/**
* 总路由入口
*/
import * as feiyiClientRouter from './feiyiClient';
import * as diqinClientRouter from './diqinClient';
import * as regionRouter from './region';
import * as runningRouter from './running';
export function setRouter(httpServer) {
feiyiClientRouter.setRouter(httpServer);
diqinClientRouter.setRouter(httpServer);
regionRouter.setRouter(httpServer);
runningRouter.setRouter(httpServer);
}
......
/**
* 运行分析路由
*/
import asyncHandler from 'express-async-handler';
import * as runningBiz from '../biz/running';
import { eccReqParamater } from '../util/verificationParam';
export function setRouter(httpServer) {
/** 运行分析 */
httpServer.post('/api/dq/run/analysis', asyncHandler(getRunAnalysis));
/** 运行分析弹窗 */
httpServer.post('/api/dq/run/analysis/popup', asyncHandler(getAnalysisPopup));
/** 智能监控 */
httpServer.post('/api/dq/run/monitoring', asyncHandler(getRunMonitoring));
/** 智能监控弹窗 */
httpServer.post('/api/dq/run/monitor/popup', asyncHandler(getMonitorPopup));
/** 控制设备运行 */
httpServer.post('/api/dq/run/device/running', asyncHandler(controlDeviceRunning));
}
/**
* 运行分析
*/
async function getRunAnalysis(req, res) {
const { } = req.body;
const result = await runningBiz.getRunAnalysis();
res.success(result);
}
/**
* 运行分析弹窗
*/
async function getAnalysisPopup(req, res) {
const { } = req.body;
const result = await runningBiz.getAnalysisPopup();
res.success(result);
}
/**
* 智能监控
*/
async function getRunMonitoring(req, res) {
const { } = req.body;
const result = await runningBiz.getRunMonitoring();
res.success(result);
}
/**
* 智能监控弹窗
*/
async function getMonitorPopup(req, res) {
const { } = req.body;
const result = await runningBiz.getMonitorPopup();
res.success(result);
}
/**
* 控制设备运行
* @param req
* @param res
*/
async function controlDeviceRunning(req, res) {
let reqConf = {deviceId:'String', deviceType:'String', status:'Number'};
const NotMustHaveKeys = [ "deviceType" ];
let params = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
const result = await runningBiz.controlDeviceRunning(params);
res.success(result);
}
\ 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