南瑞意见修改:前端页面和后端接口

This commit is contained in:
lixiaoyuan
2026-01-05 16:13:13 +08:00
parent 97e4b182de
commit e278ae1003
51 changed files with 2812 additions and 958 deletions

View File

@@ -6,7 +6,7 @@
"exportpath": "D:/Programs/openresty-1.27.1.1-win64/zdownload", "exportpath": "D:/Programs/openresty-1.27.1.1-win64/zdownload",
"database": {"host": "localhost", "port": 3306, "user": "root", "passwd": "jsyh@2025", "dbname": "ess"}, "database": {"host": "localhost", "port": 3306, "user": "root", "passwd": "jsyh@2025", "dbname": "ess"},
"http": {"token":0, "port": 19800, "encryption":0, "encryptKey":""}, "http": {"token":0, "port": 19800, "encryption":0, "encryptKey":""},
"mqtt": {"host":"mqtt://118.195.161.113:8883","username":"admin","password":"jsyh@2025", "interval": 120}, "mqtt": {"host":"mqtt://118.195.161.113:8883","username":"admin","password":"jsyh@2025", "interval": 300},
"topic": { "topic": {
"EMS_YX": {"deviceType":101, "polling":0, "enabled": 1}, "EMS_YX": {"deviceType":101, "polling":0, "enabled": 1},
"EMS_YC": {"deviceType":101, "polling":0, "enabled": 1}, "EMS_YC": {"deviceType":101, "polling":0, "enabled": 1},
@@ -26,6 +26,7 @@
"Cooling_YX": {"deviceType":14, "polling":1, "enabled": 1}, "Cooling_YX": {"deviceType":14, "polling":1, "enabled": 1},
"Gateway_YX": {"deviceType":15, "polling":1, "enabled": 1}, "Gateway_YX": {"deviceType":15, "polling":1, "enabled": 1},
"Gateway_YC": {"deviceType":15, "polling":1, "enabled": 1}, "Gateway_YC": {"deviceType":15, "polling":1, "enabled": 1},
"Gateway_YT": {"deviceType":15, "polling":0, "enabled": 1},
"Charger_YC": {"deviceType":106, "polling":0, "enabled": 1} "Charger_YC": {"deviceType":106, "polling":0, "enabled": 1}
}, },
"view": {"latitude":0,"longitude":0,"altitude":0}, "view": {"latitude":0,"longitude":0,"altitude":0},

View File

@@ -278,29 +278,31 @@
{"key": "0x1022", "datatype": "uint16", "alert": 0, "name":"电操状态NO", "remark": "1闭合0断开"}, {"key": "0x1022", "datatype": "uint16", "alert": 0, "name":"电操状态NO", "remark": "1闭合0断开"},
{"key": "0x1023", "datatype": "uint16", "alert": 0, "name":"远程关机NO", "remark": "1开机0无效"}, {"key": "0x1023", "datatype": "uint16", "alert": 0, "name":"远程关机NO", "remark": "1开机0无效"},
{"key": "0x1024", "datatype": "uint16", "alert": 0, "name":"远程开机NO", "remark": "1开机0无效"}, {"key": "0x1024", "datatype": "uint16", "alert": 0, "name":"远程开机NO", "remark": "1开机0无效"},
{"key": "0x1025", "datatype": "uint16", "alert": 0, "name":"BA故障信号NO", "remark": "1故障0正常"}, {"key": "0x1025", "datatype": "uint16", "alert": 1, "name":"BA故障信号NO", "remark": "1故障0正常"},
{"key": "0x1026", "datatype": "uint16", "alert": 0, "name":"PCS_01状态", "remark": "1在线0掉线"}, {"key": "0x1026", "datatype": "uint16", "alert": 1, "name":"PCS_01状态", "remark": "1在线0掉线"},
{"key": "0x1027", "datatype": "uint16", "alert": 0, "name":"PCS_02状态", "remark": "1在线0掉线"}, {"key": "0x1027", "datatype": "uint16", "alert": 1, "name":"PCS_02状态", "remark": "1在线0掉线"},
{"key": "0x1028", "datatype": "uint16", "alert": 0, "name":"PCS_03状态", "remark": "1在线0掉线"}, {"key": "0x1028", "datatype": "uint16", "alert": 1, "name":"PCS_03状态", "remark": "1在线0掉线"},
{"key": "0x1029", "datatype": "uint16", "alert": 0, "name":"PCS_04状态", "remark": "1在线0掉线"}, {"key": "0x1029", "datatype": "uint16", "alert": 1, "name":"PCS_04状态", "remark": "1在线0掉线"},
{"key": "0x102A", "datatype": "uint16", "alert": 0, "name":"PCS_05状态", "remark": "1在线0掉线"}, {"key": "0x102A", "datatype": "uint16", "alert": 1, "name":"PCS_05状态", "remark": "1在线0掉线"},
{"key": "0x102B", "datatype": "uint16", "alert": 0, "name":"PCS_06状态", "remark": "1在线0掉线"}, {"key": "0x102B", "datatype": "uint16", "alert": 1, "name":"PCS_06状态", "remark": "1在线0掉线"},
{"key": "0x102C", "datatype": "uint16", "alert": 0, "name":"PCS_07状态", "remark": "1在线0掉线"}, {"key": "0x102C", "datatype": "uint16", "alert": 1, "name":"PCS_07状态", "remark": "1在线0掉线"},
{"key": "0x102D", "datatype": "uint16", "alert": 0, "name":"PCS_09状态", "remark": "1在线0掉线"}, {"key": "0x102D", "datatype": "uint16", "alert": 1, "name":"PCS_08状态", "remark": "1在线0掉线"},
{"key": "0x102E", "datatype": "uint16", "alert": 0, "name":"PCS_10状态", "remark": "1在线0掉线"}, {"key": "0x102E", "datatype": "uint16", "alert": 1, "name":"PCS_09状态", "remark": "1在线0掉线"},
{"key": "0x102F", "datatype": "uint16", "alert": 1, "name":"PCS_01下发设置", "remark": "1故障0正常"}, {"key": "0x102F", "datatype": "uint16", "alert": 1, "name":"PCS_10状态", "remark": "1在线0掉线"},
{"key": "0x1030", "datatype": "uint16", "alert": 1, "name":"PCS_02下发设置", "remark": "1故障0正常"}, {"key": "0x1030", "datatype": "uint16", "alert": 1, "name":"PCS_01下发设置", "remark": "1故障0正常"},
{"key": "0x1031", "datatype": "uint16", "alert": 1, "name":"PCS_03下发设置", "remark": "1故障0正常"}, {"key": "0x1031", "datatype": "uint16", "alert": 1, "name":"PCS_02下发设置", "remark": "1故障0正常"},
{"key": "0x1032", "datatype": "uint16", "alert": 1, "name":"PCS_04下发设置", "remark": "1故障0正常"}, {"key": "0x1032", "datatype": "uint16", "alert": 1, "name":"PCS_03下发设置", "remark": "1故障0正常"},
{"key": "0x1033", "datatype": "uint16", "alert": 1, "name":"PCS_05下发设置", "remark": "1故障0正常"}, {"key": "0x1033", "datatype": "uint16", "alert": 1, "name":"PCS_04下发设置", "remark": "1故障0正常"},
{"key": "0x1034", "datatype": "uint16", "alert": 1, "name":"PCS_06下发设置", "remark": "1故障0正常"}, {"key": "0x1034", "datatype": "uint16", "alert": 1, "name":"PCS_05下发设置", "remark": "1故障0正常"},
{"key": "0x1035", "datatype": "uint16", "alert": 1, "name":"PCS_07下发设置", "remark": "1故障0正常"}, {"key": "0x1035", "datatype": "uint16", "alert": 1, "name":"PCS_06下发设置", "remark": "1故障0正常"},
{"key": "0x1036", "datatype": "uint16", "alert": 1, "name":"PCS_08下发设置", "remark": "1故障0正常"}, {"key": "0x1036", "datatype": "uint16", "alert": 1, "name":"PCS_07下发设置", "remark": "1故障0正常"},
{"key": "0x1037", "datatype": "uint16", "alert": 1, "name":"PCS_09下发设置", "remark": "1故障0正常"}, {"key": "0x1037", "datatype": "uint16", "alert": 1, "name":"PCS_08下发设置", "remark": "1故障0正常"},
{"key": "0x1038", "datatype": "uint16", "alert": 1, "name":"PCS_10下发设置", "remark": "1:故障0正常"}, {"key": "0x1038", "datatype": "uint16", "alert": 1, "name":"PCS_09下发设置", "remark": "1故障0正常"},
{"key": "0x1039", "datatype": "uint16", "alert": 1, "name":"内部DSP通信故障", "remark": "1:故障0正常"}, {"key": "0x1039", "datatype": "uint16", "alert": 1, "name":"PCS_10下发设置", "remark": "1:故障0正常"},
{"key": "0x103A", "datatype": "uint16", "alert": 1, "name":"BMS CAN通信故障", "remark": "1:故障0正常"}, {"key": "0x103A", "datatype": "uint16", "alert": 1, "name":"内部DSP通信故障", "remark": "1:故障0正常"},
{"key": "0x103B", "datatype": "uint16", "alert": 1, "name":"下发设置失败", "remark": "1:故障0正常"} {"key": "0x103B", "datatype": "uint16", "alert": 1, "name":"BMS CAN通信故障", "remark": "1:故障0正常"},
{"key": "0x103C", "datatype": "uint16", "alert": 1, "name":"下发设置失败", "remark": "1:故障0正常"},
{"key": "0x103D", "datatype": "uint16", "alert": 0, "name":"手动/自动并离网状态", "remark": "1:自动0手动"}
] ]
}, },
"PCS_YC":{ "PCS_YC":{

View File

@@ -2,6 +2,15 @@
"EMS":{ "EMS":{
"deviceType":101, "deviceType":101,
"addrYC":[ "addrYC":[
["BCU总通信状态", "0x2018", "--", ""],
["PCU总通信状态", "0x2019", "--", ""],
["电表总通信状态", "0x201A", "--", ""],
["消防总通信状态", "0x201B", "--", ""],
["UPS总通信状态", "0x201C", "--", ""],
["温湿度总通信状态", "0x201D", "--", ""],
["空调总通信状态", "0x201E", "--", ""],
["EMU通信状态", "0x201F", "--", ""],
["冷机总通信状态", "0x2020", "--", ""],
["A相电压", "0x107E", "0.0", " V", "1"], ["A相电压", "0x107E", "0.0", " V", "1"],
["A相电流", "0x1084", "0.0", " A"], ["A相电流", "0x1084", "0.0", " A"],
["B相电压", "0x1080", "0.0", " V", "1"], ["B相电压", "0x1080", "0.0", " V", "1"],
@@ -11,7 +20,18 @@
["总有功功率", "0x1096", "0.0", " kW"] ["总有功功率", "0x1096", "0.0", " kW"]
], ],
"addrCurve": ["0x107E", "0x1084", "0x1096"] "addrCurve": ["0x107E", "0x1084", "0x1096"],
"valstr": {
"0x2018": {"0":"正常", "1":"告警", "2":"故障"},
"0x2019": {"0":"正常", "1":"告警", "2":"故障"},
"0x201A": {"0":"正常", "1":"告警", "2":"故障"},
"0x201B": {"0":"正常", "1":"告警", "2":"故障"},
"0x201C": {"0":"正常", "1":"告警", "2":"故障"},
"0x201D": {"0":"正常", "1":"告警", "2":"故障"},
"0x201E": {"0":"正常", "1":"告警", "2":"故障"},
"0x201F": {"0":"正常", "1":"告警", "2":"故障"},
"0x2020": {"0":"正常", "1":"告警", "2":"故障"}
}
}, },
"PCS":{ "PCS":{
"deviceType":102, "deviceType":102,
@@ -24,17 +44,21 @@
["B相电流", "0x001A", "0.0", " A"], ["B相电流", "0x001A", "0.0", " A"],
["C相电压", "0x0011", "0.0", " V", "1"], ["C相电压", "0x0011", "0.0", " V", "1"],
["C相电流", "0x001B", "0.0", " A"], ["C相电流", "0x001B", "0.0", " A"],
["期望有功功率", "0x000B", "0.0", " kW"],
["总有功功率", "0x0025", "0.0", " kW"] ["总有功功率", "0x0025", "0.0", " kW"]
], ],
"addrCurve": ["0x0010", "0x0019", "0x0025"] "addrCurve": ["0x0010", "0x0019", "0x0025"],
"valstr": {
"0x1009": {"0":"待机","1":"充电","2":"放电","3":"搁置"},
"0x100A": {"1":"离网","0":"并网"}
}
}, },
"PCU":{ "PCU":{
"deviceType":103, "deviceType":103,
"addrYC":[ "addrYC":[
["电网状态", "0x1007", "--", ""], ["电网状态", "0x1007", "--", ""],
["启停状态", "0x1006", "--", ""], ["启停状态", "0x1006", "--", ""],
["有功功率期望值","0x000E", "0.0", " KW"], ["手动/自动状态", "0x103D", "--", ""],
["无功功率期望值","0x000F", "0.0", " kVar"],
["A相电压", "0x0013", "0.0", " V", "1"], ["A相电压", "0x0013", "0.0", " V", "1"],
["A相电流", "0x001C", "0.0", " A"], ["A相电流", "0x001C", "0.0", " A"],
["B相电压", "0x0014", "0.0", " V", "1"], ["B相电压", "0x0014", "0.0", " V", "1"],
@@ -43,7 +67,12 @@
["C相电流", "0x001E", "0.0", " A"], ["C相电流", "0x001E", "0.0", " A"],
["总有功功率", "0x0028", "0.0", " kW"] ["总有功功率", "0x0028", "0.0", " kW"]
], ],
"addrCurve": ["0x0013", "0x001C", "0x0028"] "addrCurve": ["0x0013", "0x001C", "0x0028"],
"valstr": {
"0x1007": {"1":"离网","0":"并网"},
"0x1006": {"1":"开机","0":"关机"},
"0x103D": {"1":"自动","0":"手动"}
}
}, },
"BMS":{ "BMS":{
"deviceType":104, "deviceType":104,
@@ -54,28 +83,36 @@
["SOH", "0x0002", "0", " %", "0.1"], ["SOH", "0x0002", "0", " %", "0.1"],
["电压", "0x0003", "0.0", " V", "0.1"], ["电压", "0x0003", "0.0", " V", "0.1"],
["电流", "0x0005", "0.0", " A", "0.1"], ["电流", "0x0005", "0.0", " A", "0.1"],
["单体最电压", "0x0021", "0.0", " V", "0.1"], ["单体最电压", "0x0021", "0.0", " V", "0.001"],
["单体最小电压", "0x0024", "0.0", " V", "0.1"], ["单体最小电压", "0x0024", "0.0", " V", "0.001"],
["单体最大温度", "0x0029", "0.0", " ℃", "0.1"], ["单体最大温度", "0x0029", "0.0", " ℃", "0.1"],
["单体最小温度", "0x002C", "0.0", " ℃", "0.1"] ["单体最小温度", "0x002C", "0.0", " ℃", "0.1"]
], ],
"addrCurve": ["0x0003", "0x0005", ""] "addrCurve": ["0x0003", "0x0005", ""],
"valstr": {
"0x004A": {"0":"待机","1":"充电","2":"放电"}
}
}, },
"BCU":{ "BCU":{
"deviceType":105, "deviceType":105,
"addrYC":[ "addrYC":[
["充放状态", "0xA003", "--", ""], ["充放状态", "0xA003", "--", ""],
["运行状态", "0xA004", "--", ""], ["运行状态", "0xA004", "--", ""],
["簇可充量", "0x0019", "0.0", " Ah", "0.1"], ["簇可充量", "0x0025", "0.0", " kWh", "1"],
["簇可放量", "0x001B", "0.0", " Ah", "0.1"], ["簇可放量", "0x0027", "0.0", " kWh", "1"],
["簇SOC", "0x000B", "0", " %", "0.1"], ["簇SOC", "0x000B", "0", " %", "0.1"],
["簇SOH", "0x000C", "0", " %", "0.1"], ["簇SOH", "0x000C", "0", " %", "0.1"],
["簇电压", "0x0003", "0.0", " V", "0.1"], ["簇电压", "0x0003", "0.0", " V", "0.1"],
["簇电流", "0x0005", "0", " A", "0.1"], ["簇电流", "0x0005", "0", " A", "0.1"],
["簇温度", "0x0007", "0.0", " ", "0.1"], ["单体最高电压", "0x0045", "0", " V", "0.001"],
["簇电阻", "0x0009", "0.0", " Ω"] ["单体最低电压", "0x0047", "0", " V", "0.001"],
["单体平均电压", "0x0049", "0", " V", "0.001"]
], ],
"addrCurve": ["0x0003", "0x0005", ""] "addrCurve": ["0x0003", "0x0005", ""],
"valstr": {
"0xA003": {"17":"开路","34":"待机","51":"充电","68":"放电"},
"0xA004": {"17":"跳机","34":"待机","51":"放空","68":"充满","85":"预警","102":"正常"}
}
}, },
"MEM":{ "MEM":{
"deviceType":3, "deviceType":3,
@@ -116,6 +153,7 @@
["B相电流", "0x0013", "0.0", " A"], ["B相电流", "0x0013", "0.0", " A"],
["C相电压", "0x000F", "0.0", " V"], ["C相电压", "0x000F", "0.0", " V"],
["C相电流", "0x0015", "0.0", " A"], ["C相电流", "0x0015", "0.0", " A"],
["三相总有功","0x0023", "0.0", " kW"],
["总有功总需量", "0x0025", "0.0", " kW"] ["总有功总需量", "0x0025", "0.0", " kW"]
], ],
"addrCurve": ["0x000B","0x0011","0x0023"] "addrCurve": ["0x000B","0x0011","0x0023"]

View File

@@ -0,0 +1,193 @@
{
"EMS":{
"deviceType":101,
"addrYC":[
["BCU总通信状态", "0x2018", "--", ""],
["PCU总通信状态", "0x2019", "--", ""],
["电表总通信状态", "0x201A", "--", ""],
["消防总通信状态", "0x201B", "--", ""],
["UPS总通信状态", "0x201C", "--", ""],
["温湿度总通信状态", "0x201D", "--", ""],
["空调总通信状态", "0x201E", "--", ""],
["EMU通信状态", "0x201F", "--", ""],
["冷机总通信状态", "0x2020", "--", ""],
["A相电压", "0x107E", "0.0", " V", "1"],
["A相电流", "0x1084", "0.0", " A"],
["B相电压", "0x1080", "0.0", " V", "1"],
["B相电流", "0x1086", "0.0", " A"],
["C相电压", "0x1082", "0.0", " V", "1"],
["C相电流", "0x1088", "0.0", " A"],
["总有功功率", "0x1096", "0.0", " kW"]
],
"addrCurve": ["0x107E", "0x1084", "0x1096"],
"valstr": {
"0x2018": {"0":"正常", "1":"告警", "2":"故障"},
"0x2019": {"0":"正常", "1":"告警", "2":"故障"},
"0x201A": {"0":"正常", "1":"告警", "2":"故障"},
"0x201B": {"0":"正常", "1":"告警", "2":"故障"},
"0x201C": {"0":"正常", "1":"告警", "2":"故障"},
"0x201D": {"0":"正常", "1":"告警", "2":"故障"},
"0x201E": {"0":"正常", "1":"告警", "2":"故障"},
"0x201F": {"0":"正常", "1":"告警", "2":"故障"},
"0x2020": {"0":"正常", "1":"告警", "2":"故障"}
}
},
"PCS":{
"deviceType":102,
"addrYC":[
["充放状态", "0x1009", "--", ""],
["电网状态", "0x100A", "--", ""],
["A相电压", "0x0010", "0.0", " V", "1"],
["A相电流", "0x0019", "0.0", " A"],
["B相电压", "0x0011", "0.0", " V", "1"],
["B相电流", "0x001A", "0.0", " A"],
["C相电压", "0x0011", "0.0", " V", "1"],
["C相电流", "0x001B", "0.0", " A"],
["总有功功率", "0x0025", "0.0", " kW"]
],
"addrCurve": ["0x0010", "0x0019", "0x0025"],
"valstr": {
"0x1009": {"0":"待机","1":"充电","2":"放电","3":"搁置"},
"0x100A": {"1":"离网","0":"并网"}
}
},
"PCU":{
"deviceType":103,
"addrYC":[
["电网状态", "0x1007", "--", ""],
["启停状态", "0x1006", "--", ""],
["手动/自动状态", "0x103D", "--", ""],
["有功功率期望值","0x000E", "0.0", " KW"],
["无功功率期望值","0x000F", "0.0", " kVar"],
["A相电压", "0x0013", "0.0", " V", "1"],
["A相电流", "0x001C", "0.0", " A"],
["B相电压", "0x0014", "0.0", " V", "1"],
["B相电流", "0x001D", "0.0", " A"],
["C相电压", "0x0015", "0.0", " V", "1"],
["C相电流", "0x001E", "0.0", " A"],
["总有功功率", "0x0028", "0.0", " kW"]
],
"addrCurve": ["0x0013", "0x001C", "0x0028"],
"valstr": {
"0x1007": {"1":"离网","0":"并网"},
"0x1006": {"1":"开机","0":"关机"},
"0x103D": {"1":"自动","0":"手动"}
}
},
"BMS":{
"deviceType":104,
"addrYC":[
["充放状态", "0x004A", "--", ""],
["堆功率", "0x000F", "0.0", " kW"],
["SOC", "0x0001", "0", " %", "0.1"],
["SOH", "0x0002", "0", " %", "0.1"],
["电压", "0x0003", "0.0", " V", "0.1"],
["电流", "0x0005", "0.0", " A", "0.1"],
["单体最大电压", "0x0021", "0.0", " V", "0.001"],
["单体最小电压", "0x0024", "0.0", " V", "0.001"],
["单体最大温度", "0x0029", "0.0", " ℃", "0.1"],
["单体最小温度", "0x002C", "0.0", " ℃", "0.1"]
],
"addrCurve": ["0x0003", "0x0005", ""],
"valstr": {
"0x004A": {"0":"待机","1":"充电","2":"放电"}
}
},
"BCU":{
"deviceType":105,
"addrYC":[
["充放状态", "0xA003", "--", ""],
["运行状态", "0xA004", "--", ""],
["簇可充电量", "0x0025", "0.0", " kWh", "1"],
["簇可放电量", "0x0027", "0.0", " kWh", "1"],
["簇SOC", "0x000B", "0", " %", "0.1"],
["簇SOH", "0x000C", "0", " %", "0.1"],
["簇电压", "0x0003", "0.0", " V", "0.1"],
["簇电流", "0x0005", "0", " A", "0.1"]
],
"addrCurve": ["0x0003", "0x0005", ""],
"valstr": {
"0xA003": {"17":"开路","34":"待机","51":"充电","68":"放电"},
"0xA004": {"17":"跳机","34":"待机","51":"放空","68":"充满","85":"预警","102":"正常"}
}
},
"MEM":{
"deviceType":3,
"addrYC":[
["日充电电量", "0x002F", "0", " kWh"],
["日放电电量", "0x0031", "0", " kWh"],
["总充电电量", "0x004D", "0", " kWh"],
["总放电电量", "0x004F", "0", " kWh"],
["日充电费用", "0x0033", "0", " 元"],
["日放电费用", "0x0035", "0", " 元"],
["总充电费用", "0x0051", "0", " 元"],
["总放电费用", "0x0053", "0", " 元"],
["日收益", "0x0037", "0", " 元"],
["总收益", "0x0055", "0", " 元"],
["日正向尖电能", "0x0039", "0", " kWh"],
["日正向峰电能", "0x003B", "0", " kWh"],
["日正向平电能", "0x003D", "0", " kWh"],
["日正向谷电能", "0x003F", "0", " kWh"],
["日正向总电能", "0x0041", "0", " kWh"],
["日反向尖电能", "0x0043", "0", " kWh"],
["日反向峰电能", "0x0045", "0", " kWh"],
["日反向平电能", "0x0047", "0", " kWh"],
["日反向谷电能", "0x0049", "0", " kWh"],
["日反向总电能", "0x004B", "0", " kWh"],
["总正向尖电能", "0x0057", "0", " kWh"],
["总正向峰电能", "0x0059", "0", " kWh"],
["总正向平电能", "0x005B", "0", " kWh"],
["总正向谷电能", "0x005D", "0", " kWh"],
["总正向总电能", "0x005F", "0", " kWh"],
["总反向尖电能", "0x0061", "0", " kWh"],
["总反向峰电能", "0x0063", "0", " kWh"],
["总反向平电能", "0x0065", "0", " kWh"],
["总反向谷电能", "0x0067", "0", " kWh"],
["总反向总电能", "0x0069", "0", " kWh"],
["A相电压", "0x000B", "0.0", " V"],
["A相电流", "0x0011", "0.0", " A"],
["B相电压", "0x000D", "0.0", " V"],
["B相电流", "0x0013", "0.0", " A"],
["C相电压", "0x000F", "0.0", " V"],
["C相电流", "0x0015", "0.0", " A"],
["三相总有功","0x0023", "0.0", " kW"],
["总有功总需量", "0x0025", "0.0", " kW"]
],
"addrCurve": ["0x000B","0x0011","0x0023"]
},
"TH": {
"deviceType":10,
"addrYC":[
["温度", "0x0003", "0.0", " ℃", "0.1"],
["湿度", "0x0004", "0.0", " %", "0.1"]
]
},
"Cooling": {
"deviceType":14,
"addrYC":[
["开关", "0x1003", "0", "", "1"],
["采样模式", "0x1004", "0", "", "1"],
["制冷状态", "0x1005", "0", "", "1"],
["制热状态", "0x1006", "0", "", "1"],
["高温告警", "0x1007", "0", "", "1"],
["低温告警", "0x1008", "0", "", "1"],
["高压告警", "0x1009", "0", "", "1"],
["低压告警", "0x100A", "0", "", "1"]
]
},
"Charger": {
"deviceType":106,
"addrYC":[
["工作状态", "11", "空闲", ""],
["需求电压", "12", "0.0", " V", "0.1"],
["需求电流", "13", "0.0", " A", "0.01"],
["需求功率", "14", "0.0", " kW", "0.1"],
["输出电压", "15", "0.0", " V", "0.1"],
["输出电流", "16", "0.0", " A", "0.01"],
["输出功率", "17", "0.0", " kW", "0.1"],
["功率限值", "18", "0.0", " kW", "0.1"]
],
"addrCurve": ["15", "16", "17"]
}
}

View File

@@ -48,7 +48,7 @@
], ],
"addrCurve": ["0x0010", "0x0019", "0x0025"], "addrCurve": ["0x0010", "0x0019", "0x0025"],
"valstr": { "valstr": {
"0x1009": {"0":"待机","1":"充电","2":"放电","3":"搁置"}, "0x1009": {"0":"待机","1":"充电","2":"放电","3":"空闲"},
"0x100A": {"1":"离网","0":"并网"} "0x100A": {"1":"离网","0":"并网"}
} }
}, },

View File

@@ -49,7 +49,7 @@
], ],
"addrCurve": ["0x0010", "0x0019", "0x0025"], "addrCurve": ["0x0010", "0x0019", "0x0025"],
"valstr": { "valstr": {
"0x1009": {"0":"待机","1":"充电","2":"放电","3":"搁置"}, "0x1009": {"0":"待机","1":"充电","2":"放电","3":"空闲"},
"0x100A": {"1":"离网","0":"并网"} "0x100A": {"1":"离网","0":"并网"}
} }
}, },

View File

@@ -1,6 +1,6 @@
#include "Constant.h" #include "Constant.h"
namespace CONST namespace CONSTS
{ {
const std::string VAR; const std::string VAR;
} }

View File

@@ -1,11 +1,11 @@
#ifndef _CONSTANTS_H_ #ifndef _MYCONSTS_H_
#define _CONSTANTS_H_ #define _MYCONSTS_H_
#include <string> #include <string>
namespace CONST namespace CONSTS
{ {
extern const std::string VAR; extern const std::string VAR;
} }
#endif // !_CONSTANTS_H_ #endif // !_MYCONSTS_H_

View File

@@ -12,9 +12,10 @@ enum class EAlertType
enum class EDeviceType enum class EDeviceType
{ {
NUL = 0,
//1 变压器 0 //1 变压器 0
//2 配电柜 0 //2 配电柜 0
//3 电表 1 E_METER = 3, //3 电表 1
//4 门禁 0 //4 门禁 0
//5 空调 0 //5 空调 0
//6 照明 0 //6 照明 0

View File

@@ -28,6 +28,9 @@ std::shared_ptr<Device> Device::create(Fields& fields)
static const int BCU_UNIT_SIZE = 256; static const int BCU_UNIT_SIZE = 256;
Device::Device() Device::Device()
{ {
cacheU = vector<float>(144, 0);
cacheI = vector<float>(144, 0);
cacheP = vector<float>(144, 0);
vecBCUUnit = std::vector<std::vector<float>>(BCU_UNIT_SIZE, std::vector<float>(5, 0.0f)); vecBCUUnit = std::vector<std::vector<float>>(BCU_UNIT_SIZE, std::vector<float>(5, 0.0f));
} }
@@ -104,54 +107,54 @@ int Device::startComm()
return 0; return 0;
} }
void Device::getCacheVoltage(std::vector<std::string>& vec) //void Device::getCacheVoltage(std::vector<std::string>& vec)
{ //{
vec.resize(mapCacheVoltage.size()); // vec.resize(mapCacheVoltage.size());
int i = 0; // int i = 0;
for (auto iter = mapCacheVoltage.begin(); iter != mapCacheVoltage.end(); ++iter) // for (auto iter = mapCacheVoltage.begin(); iter != mapCacheVoltage.end(); ++iter)
{ // {
vec[i] = Utils::toStr(iter->second); // vec[i] = Utils::toStr(iter->second);
i++; // i++;
} // }
} //}
void Device::getCacheCurrent(std::vector<std::string>& vec) //void Device::getCacheCurrent(std::vector<std::string>& vec)
{ //{
vec.resize(mapCacheCurrent.size()); // vec.resize(mapCacheCurrent.size());
int i = 0; // int i = 0;
for (auto iter = mapCacheCurrent.begin(); iter != mapCacheCurrent.end(); ++iter) // for (auto iter = mapCacheCurrent.begin(); iter != mapCacheCurrent.end(); ++iter)
{ // {
vec[i] = Utils::toStr(iter->second); // vec[i] = Utils::toStr(iter->second);
i++; // i++;
} // }
} //}
void Device::getCachePower(std::vector<std::string>& vec) //void Device::getCachePower(std::vector<std::string>& vec)
{ //{
vec.resize(mapCachePower.size()); // vec.resize(mapCachePower.size());
int i = 0; // int i = 0;
for (auto iter = mapCachePower.begin(); iter != mapCachePower.end(); ++iter) // for (auto iter = mapCachePower.begin(); iter != mapCachePower.end(); ++iter)
{ // {
vec[i] = Utils::toStr(iter->second); // vec[i] = Utils::toStr(iter->second);
i++; // i++;
} // }
} //}
void Device::setCache(int datatype, std::vector<float>& vd) void Device::setCache(int datatype, std::vector<float>& vd)
{ {
std::map<int, float>* mapptr = NULL; std::vector<float>* vecptr = NULL;
if (datatype == 1) { mapptr = &mapCacheVoltage; } if (datatype == 1) { vecptr = &cacheU; }
else if (datatype == 2) { mapptr = &mapCacheCurrent; } else if (datatype == 2) { vecptr = &cacheI; }
else if (datatype == 3) { mapptr = &mapCachePower; } else if (datatype == 3) { vecptr = &cacheP; }
if (mapptr) if (vecptr)
{ {
const int step = 600; const int step = 600;
const int N = 86400/step; const int N = 86400/step;
int64_t tsSeconds = Utils::timeDaySeconds(); int64_t tsSeconds = Utils::timeDaySeconds();
int npos = tsSeconds / step; int npos = tsSeconds / step;
for (int i = 0; i<N; ++i) for (int i = 0; i<N && i< vecptr->size(); ++i)
{ {
if (i < vd.size()) { (*mapptr)[i] = vd[i]; } if (i < vd.size()) { (*vecptr)[i] = vd[i]; }
else if (i <= npos) { (*mapptr)[i] = 0; } else if (i <= npos) { (*vecptr)[i] = 0; }
} }
} }
} }
@@ -164,9 +167,9 @@ bool Device::cache(int npos)
} }
if (npos == 0) if (npos == 0)
{ {
mapCacheVoltage.clear(); std::fill(cacheU.begin(), cacheU.end(), 0);
mapCacheCurrent.clear(); std::fill(cacheI.begin(), cacheI.end(), 0);
mapCachePower.clear(); std::fill(cacheP.begin(), cacheP.end(), 0);
} }
std::string addrV; std::string addrV;
@@ -186,9 +189,9 @@ bool Device::cache(int npos)
int U = Utils::toInt(this->getParam(addrV, "0")); int U = Utils::toInt(this->getParam(addrV, "0"));
int I = Utils::toInt(this->getParam(addrI, "0")); int I = Utils::toInt(this->getParam(addrI, "0"));
int P = addrP.empty() ? U*I*0.001 : Utils::toInt(this->getParam(addrP, "0")); int P = addrP.empty() ? U*I*0.001 : Utils::toInt(this->getParam(addrP, "0"));
mapCacheVoltage[npos] = U; cacheU[npos] = U;
mapCacheCurrent[npos] = I; cacheI[npos] = I;
mapCachePower[npos] = P; cacheP[npos] = P;
return true; return true;
} }

View File

@@ -23,9 +23,9 @@ public:
int startComm(); int startComm();
void getCacheVoltage(std::vector<std::string>& vec); //void getCacheVoltage(std::vector<std::string>& vec);
void getCacheCurrent(std::vector<std::string>& vec); //void getCacheCurrent(std::vector<std::string>& vec);
void getCachePower(std::vector<std::string>& vec); //void getCachePower(std::vector<std::string>& vec);
// int datatype: 1: 电压2电流3功率 // int datatype: 1: 电压2电流3功率
void setCache(int datatype, std::vector<float>& vec); void setCache(int datatype, std::vector<float>& vec);
@@ -49,7 +49,7 @@ public:
int type = {0}; int type = {0};
std::string name; std::string name;
std::string code; std::string code;
int category; int category = 0;
bool isOpen = false; bool isOpen = false;
std::string attrsJson = ""; std::string attrsJson = "";
int sortNo {0}; int sortNo {0};
@@ -67,9 +67,13 @@ public:
std::shared_ptr<CommEntity> commEntity; std::shared_ptr<CommEntity> commEntity;
int64_t tsDataDate {}; int64_t tsDataDate {};
std::map<int, float> mapCacheVoltage; //std::map<int, float> mapCacheVoltage;
std::map<int, float> mapCacheCurrent; //std::map<int, float> mapCacheCurrent;
std::map<int, float> mapCachePower; //std::map<int, float> mapCachePower;
std::vector<float> cacheU;
std::vector<float> cacheI;
std::vector<float> cacheP;
// 参数值(保存从设备读取的参数值) // 参数值(保存从设备读取的参数值)
std::map<std::string, std::string> mapParams; std::map<std::string, std::string> mapParams;

View File

@@ -18,6 +18,18 @@ Station::Station() : stationId(0)
predictStorageIn = vector<int>(144, 0); predictStorageIn = vector<int>(144, 0);
predictStorageOut = vector<int>(144, 0); predictStorageOut = vector<int>(144, 0);
predictCharge = vector<int>(144, 0); predictCharge = vector<int>(144, 0);
storage.U = vector<int>(144, 0);
storage.I = vector<int>(144, 0);
storage.P = vector<int>(144, 0);
charge.U = vector<int>(144, 0);
charge.I = vector<int>(144, 0);
charge.P = vector<int>(144, 0);
pv.U = vector<int>(144, 0);
pv.I = vector<int>(144, 0);
pv.P = vector<int>(144, 0);
} }
void Station::setFields(Fields& fields) void Station::setFields(Fields& fields)
@@ -214,13 +226,13 @@ void Station::setGarewayParams()
string Station::getGatewayMode() string Station::getGatewayMode()
{ {
// 0手动1峰谷套利2配网增容3应急供电4并网保电5自定时段 // 0手动1峰谷套利2配网增容3应急供电4并网保电5运营支撑
if (gatewayParam.mode == 0) { return "手动"; } if (gatewayParam.mode == 0) { return "手动"; }
else if (gatewayParam.mode == 1) { return "峰谷套利"; } else if (gatewayParam.mode == 1) { return "峰谷套利"; }
else if (gatewayParam.mode == 2) { return "配网增容"; } else if (gatewayParam.mode == 2) { return "配网增容"; }
else if (gatewayParam.mode == 3) { return "应急供电"; } else if (gatewayParam.mode == 3) { return "应急供电"; }
else if (gatewayParam.mode == 4) { return "并网保电"; } else if (gatewayParam.mode == 4) { return "并网保电"; }
else if (gatewayParam.mode == 5) { return "自定时段"; } else if (gatewayParam.mode == 5) { return "运营支撑"; }
else { return "--"; }; else { return "--"; };
} }
@@ -236,7 +248,11 @@ static map<int, string> mapPeriodOper =
string Station::getGatewayParam() string Station::getGatewayParam()
{ {
stringstream ss; stringstream ss;
std::string str1 = "峰谷套利时段:<br>"; std::string str1 = std::format("运行模式:{}<br>储能EMY状态{}<br>充电桩状态:{}<br><br>",
getGatewayMode(),
this->emuStatus == 1 ? "在线" : (this->emuStatus == 0 ? "离线" : "--"),
this->cdzStatus == 1 ? "在线" : (this->cdzStatus == 0 ? "离线" : "--"));
str1 += "峰谷套利时段:<br>";
{ {
njson json; njson json;
if (JSON::parse(gatewayParam.param1, json)) if (JSON::parse(gatewayParam.param1, json))
@@ -346,18 +362,24 @@ void Station::readAlert(std::shared_ptr<Device> device, std::string addr, int v,
} }
} }
void Station::readRuntimeData(int deviceNo, string addr, int val) void Station::readEnergyData(int deviceNo, string addr, int val)
{ {
if (deviceNo == 1) if (deviceNo == 1) // 入网电表
{ {
if (addr == "0x000B") { this->voltage = val; } // A相电压 R uint32 1V 0x000B if (addr == "0x000B") { this->grid.voltage = val; } // A相电压 R uint32 1V 0x000B
if (addr == "0x0011") { this->current = val; } // A相电流 R int32 1A 0x0011 if (addr == "0x0011") { this->grid.current = val; } // A相电流 R int32 1A 0x0011
if (addr == "0x0023") { this->power = val; } // 三相总有功 R int32 1kW 0x0023 if (addr == "0x0023") { this->grid.power = val; } // 三相总有功 R int32 1kW 0x0023
// 功率因数 ?? 电表没有功率因数数据
} }
else if (deviceNo == 2) else if (deviceNo == 2) // 储能电表
{ {
statData.ts = Utils::time(); statData.ts = Utils::time();
if (addr == "0x002F") { statData.dayElectIn = val; } //日充电电量 R uint32 1kWh 0x002F
if (addr == "0x000B") { this->storage.voltage = val; } // A相电压 R uint32 1V 0x000B
else if (addr == "0x0011") { this->storage.current = val; } // A相电流 R int32 1A 0x0011
else if (addr == "0x0023") { this->storage.power = val; } // 三相总有功 R int32 1kW 0x0023
// 功率因数 ?? 电表没有功率因数数据
else if (addr == "0x002F") { statData.dayElectIn = val; } // 日充电电量 R uint32 1kWh 0x002F
else if (addr == "0x0031") { statData.dayElectOut = val; } //日放电电量 R uint32 1kWh 0x0031 else if (addr == "0x0031") { statData.dayElectOut = val; } //日放电电量 R uint32 1kWh 0x0031
else if (addr == "0x0033") { statData.dayFeeIn = val; } //日充电费用 R uint32 1RMB 0x0033 else if (addr == "0x0033") { statData.dayFeeIn = val; } //日充电费用 R uint32 1RMB 0x0033
else if (addr == "0x0035") { statData.dayFeeOut = val; } //日放电费用 R uint32 1RMB 0x0035 else if (addr == "0x0035") { statData.dayFeeOut = val; } //日放电费用 R uint32 1RMB 0x0035
@@ -392,7 +414,29 @@ void Station::readRuntimeData(int deviceNo, string addr, int val)
else if (addr == "0x0069") { statData.totalElectOut_Total = val; } //总反向总有功电能 R uint32 1kWh 0x0069 else if (addr == "0x0069") { statData.totalElectOut_Total = val; } //总反向总有功电能 R uint32 1kWh 0x0069
} }
} }
// 充电桩
void Station::readChargeData(int deviceNo, string addr, int val)
{
if (addr == "11") { charge.connector1.isCharge = val; } //枪1:状态 R uint16 11
//枪1 : 需求电压 R uint16 12
//枪1 : 需求电流 R uint16 13
//枪1 : 需求功率 R uint16 14
else if (addr == "15") { charge.connector1.voltage = val * 0.1; } //枪1 : 输出电压 R uint16 15
else if (addr == "16") { charge.connector1.current = val * 0.01; } //枪1 : 输出电流 R uint16 16
else if (addr == "17") { charge.connector1.power = val * 0.1; } //枪1 : 输出功率 R uint16 17
//枪1 : 功率限值 R uint16 18
else if (addr == "21") { charge.connector2.isCharge = val; } //枪2 : 状态 R uint16 21
//枪2 : 需求电压 R uint16 22
//枪2 : 需求电流 R uint16 23
//枪2 : 需求功率 R uint16 24
else if (addr == "25") { charge.connector2.voltage = val * 0.1; } //枪2 : 输出电压 R uint16 25
else if (addr == "26") { charge.connector2.current = val * 0.01; } //枪2 : 输出电流 R uint16 26
else if (addr == "27") { charge.connector2.power = val * 0.1; } //枪2 : 输出功率 R uint16 27
//枪2 : 功率限值 R uint16 28
bool isCharge = (charge.connector1.isCharge || charge.connector2.isCharge);
charge.status = isCharge ? 2 : 1;
}
void Station::readTHData(int deviceNo, string addr, int val) void Station::readTHData(int deviceNo, string addr, int val)
{ {
auto& unit = mapTempHumUnit[deviceNo]; auto& unit = mapTempHumUnit[deviceNo];
@@ -507,6 +551,11 @@ void Station::readGatewayStatus(int deviceNo, int cdzStatus, int emuStatus)
device->ts = Utils::time(); device->ts = Utils::time();
} }
if (cdzStatus == 0) charge.status = 0;
else if (charge.status == 0) charge.status = 1;
if (emuStatus == 0) storage.status = 0;
else if (storage.status == 0) storage.status = 1;
//充电桩 1在线0离线 //充电桩 1在线0离线
if (cdzStatus >= 0) if (cdzStatus >= 0)
{ {
@@ -565,24 +614,51 @@ void Station::cache()
int npos = tDaySeconds / 600; int npos = tDaySeconds / 600;
int offset = tDaySeconds % 600; int offset = tDaySeconds % 600;
bool save = false; bool save = false;
if (offset >= (600-180) && npos + 1 < 144) if (posCache != npos && offset <= 180) // 超过时间点3分钟内没有存储进行兼容处理
{ {
npos += 1; if (npos == 0)
save = true; {
std::fill(storage.U.begin(), storage.U.end(), 0);
std::fill(storage.I.begin(), storage.I.end(), 0);
std::fill(storage.P.begin(), storage.P.end(), 0);
std::fill(charge.U.begin(), charge.U.end(), 0);
std::fill(charge.I.begin(), charge.I.end(), 0);
std::fill(charge.P.begin(), charge.P.end(), 0);
std::fill(pv.U.begin(), pv.U.end(), 0);
std::fill(pv.I.begin(), pv.I.end(), 0);
std::fill(pv.P.begin(), pv.P.end(), 0);
} }
else if (offset <= 180 && posCache < npos)
{
save = true; save = true;
posCache = npos; posCache = npos;
} }
if (save) if (save && npos < storage.U.size())
{ {
mapCacheElectIn[npos] = Utils::random(100, 800); // dayElectIn storage.U[npos] = storage.voltage;
mapCacheElectOut[npos] = Utils::random(100, 800); // dayElectOut storage.I[npos] = storage.current;
mapCacheElectCharger[npos] = Utils::random(100, 800); // 暂无数据源 storage.P[npos] = storage.power;
charge.U[npos] = charge.connector1.voltage;
charge.I[npos] = charge.connector1.current;
charge.P[npos] = charge.connector1.power;
//pv.U[npos];
//pv.I[npos];
//pv.P[npos];
} }
} }
static njson VectorToJsonArray(vector<float>& vec, int n)
{
//int v = Utils::random(40, 50);
njson jsonArray = njson::array();
for (int i = 0; i <= n && i < vec.size(); ++i)
{
jsonArray.push_back(int(vec[i]));
//jsonArray.push_back(v + Utils::random(1, 6) -3);
}
return jsonArray;
}
void Station::writeStatistic() void Station::writeStatistic()
{ {
auto dao = DaoEntity::create("history_day"); auto dao = DaoEntity::create("history_day");
@@ -603,15 +679,15 @@ void Station::writeStatistic()
fields.set("station_id", this->stationId); fields.set("station_id", this->stationId);
fields.set("device_id", device->deviceId); fields.set("device_id", device->deviceId);
fields.set("datatype", 1); fields.set("datatype", 1);
fields.set("value", MapValueToJson(npos, device->mapCacheVoltage)); fields.set("value", VectorToJsonArray(device->cacheU, npos));
DAO::insertRuntimeData(dao, fields); DAO::insertRuntimeData(dao, fields);
fields.set("datatype", 2); fields.set("datatype", 2);
fields.set("value", MapValueToJson(npos, device->mapCacheCurrent)); fields.set("value", VectorToJsonArray(device->cacheI, npos));
DAO::insertRuntimeData(dao, fields); DAO::insertRuntimeData(dao, fields);
fields.set("datatype", 3); fields.set("datatype", 3);
fields.set("value", MapValueToJson(npos, device->mapCachePower)); fields.set("value", VectorToJsonArray(device->cacheP, npos));
DAO::insertRuntimeData(dao, fields); DAO::insertRuntimeData(dao, fields);
//spdlog::info("[device] write runtime date to database, deviceId={}", device->deviceId); //spdlog::info("[device] write runtime date to database, deviceId={}", device->deviceId);
} }
@@ -803,3 +879,9 @@ void Station::predict()
// predictCharge[i] = v3 >= 0 ? v3 : 0; // predictCharge[i] = v3 >= 0 ? v3 : 0;
//} //}
} }
void Station::writeDeviceData()
{
}

View File

@@ -119,13 +119,16 @@ public:
string getGatewayParam(); string getGatewayParam();
void readAlert(std::shared_ptr<Device> device, std::string addr, int v, std::string text); void readAlert(std::shared_ptr<Device> device, std::string addr, int v, std::string text);
void readRuntimeData(int deviceNo, string addr, int val); void readEnergyData(int deviceNo, string addr, int val);
void readChargeData(int deviceNo, string addr, int val);
void readTHData(int deviceNo, string addr, int val); void readTHData(int deviceNo, string addr, int val);
void readFire40Data(int deviceNo, string addr, int val); void readFire40Data(int deviceNo, string addr, int val);
void readCoolingData(int deviceNo, string addr, int val); void readCoolingData(int deviceNo, string addr, int val);
void readGatewayMode(int deviceNo, int mode, string p1, string p2, string p3); void readGatewayMode(int deviceNo, int mode, string p1, string p2, string p3);
void readGatewayStatus(int deviceNo, int cdzStatus, int emuStatus); void readGatewayStatus(int deviceNo, int cdzStatus, int emuStatus);
void readTDData(int deviceNo);
void setCache(int datatype, std::vector<float>& vd); void setCache(int datatype, std::vector<float>& vd);
void cache(); void cache();
int posCache {0}; int posCache {0};
@@ -135,6 +138,8 @@ public:
void predict(); void predict();
void writeDeviceData();
public: public:
int stationId {}; int stationId {};
std::string name; std::string name;
@@ -147,7 +152,6 @@ public:
int err = 0; int err = 0;
int online = 0; int online = 0;
int running = 0; int running = 0;
bool isConnected {false}; bool isConnected {false};
int workMode {}; // 运行模式 int workMode {}; // 运行模式
@@ -172,6 +176,83 @@ public:
int overload {}; // 防过载回差 40059(1KW 10-300) int overload {}; // 防过载回差 40059(1KW 10-300)
} gatewayParam; } gatewayParam;
int cdzStatus{ -1 }; // 充电桩 1在线0离线
int emuStatus{ -1 }; // 储能 1在线0离线
int pvStatus{ -1 };
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 储能相关数据 ===
struct {
int ts; // 数据更新时间戳(通讯)
int num = 1; // 储能设备的数量(储能仓的个数)
int status = 0; // 储能设备状态: 0离线1空闲2充电3放电9故障
int voltage = 0;
int current = 0;
int power = 0;
float powerFactor = 0;
vector<int> U; // 电压曲线144个点位
vector<int> I; // 电流曲线144个点位
vector<int> P; // 功率曲线144个点位
} storage;
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 充电相关数据 ===
struct {
int ts; // 数据更新时间戳(通讯)
int num = 1; // 充电设备的数量
int status = 0; // 充电设备状态: 0离线1空闲2充电9故障
struct {
int isCharge = 0;
int voltage = 0;
int current = 0;
int power = 0;
int powerLimit = 0;
} connector1;
struct {
int isCharge = 0;
int voltage = 0;
int current = 0;
int power = 0;
int powerLimit = 0;
} connector2;
vector<int> U; // 电压曲线144个点位
vector<int> I; // 电流曲线144个点位
vector<int> P; // 功率曲线144个点位
} charge;
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 光伏相关数据 ===
struct {
int ts; // 数据更新时间戳(通讯)
int status = 0; // 充电设备状态: 0离线1空闲2发电9故障
int voltage = 0;
int current = 0;
int power = 0;
vector<int> U; // 电压曲线144个点位
vector<int> I; // 电流曲线144个点位
vector<int> P; // 功率曲线144个点位
} pv;
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 电网相关数据 ===
struct {
int status = 0; // 充电设备状态: 0离线1空闲2发电9故障
int voltage = 0;
int current = 0;
int power = 0;
float powerFactor = 0;
//vector<int> U; // 电压曲线144个点位
//vector<int> I; // 电流曲线144个点位
vector<int> P; // 功率曲线144个点位
} grid;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// === 系统统计 === /// === 系统统计 ===
// 累计发电量单位kWh // 累计发电量单位kWh
@@ -202,10 +283,10 @@ public:
double humidity {}; double humidity {};
int aircStatus {0}; int aircStatus {0};
int coolingStatus {0}; int coolingStatus {0};
double voltage {0}; //double voltage {0};
double current {0}; //double current {0};
double power {0}; //double power {0};
double powerFactor {0}; //double powerFactor {0};
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// === 设备信息 === /// === 设备信息 ===
@@ -272,12 +353,8 @@ public:
} runtimeData; } runtimeData;
int cdzStatus {-1}; // 充电桩 1在线0离线
int emuStatus {-1}; // 储能 1在线0离线
std::map<std::string, int64_t> mapAlertCache; std::map<std::string, int64_t> mapAlertCache;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// 说明从电表中读取对应数据每间隔600秒10分钟缓存一个点位存储到数据库用于绘制一天的电曲线 /// 说明从电表中读取对应数据每间隔600秒10分钟缓存一个点位存储到数据库用于绘制一天的电曲线
// 储能充电量缓存key位置索引0->144val电量 // 储能充电量缓存key位置索引0->144val电量

View File

@@ -26,7 +26,7 @@ public:
{ {
stringstream ss; stringstream ss;
ss.precision(precision); ss.precision(precision);
ss << val; ss << std::fixed << val;
mapFields[key] = ss.str(); mapFields[key] = ss.str();
} }

View File

@@ -443,6 +443,11 @@ Errcode DAO::queryDeviceList(PageInfo& pageInfo, vector<Fields>& result)
std::string sqlFrom = "FROM device d LEFT JOIN station s ON d.station_id =s.station_id"; std::string sqlFrom = "FROM device d LEFT JOIN station s ON d.station_id =s.station_id";
return QueryPagination("d.*, s.name station_name", sqlFrom, pageInfo, result); return QueryPagination("d.*, s.name station_name", sqlFrom, pageInfo, result);
} }
Errcode DAO::queryDeviceListByStation(PageInfo& pageInfo, string stationId, vector<Fields>& result)
{
std::string sqlFrom = "FROM device d LEFT JOIN station s ON d.station_id =s.station_id WHERE d.station_id='" + stationId + "'";
return QueryPagination("d.*, s.name station_name", sqlFrom, pageInfo, result);
}
// 查询设备类型定义 // 查询设备类型定义
Errcode DAO::queryDeviceTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result) Errcode DAO::queryDeviceTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result)

View File

@@ -74,6 +74,8 @@ public:
// 查询设备信息列表(分页) // 查询设备信息列表(分页)
static Errcode queryDeviceList(PageInfo& pageInfo, vector<Fields>& result); static Errcode queryDeviceList(PageInfo& pageInfo, vector<Fields>& result);
// 查询设备信息列表(分页)
static Errcode queryDeviceListByStation(PageInfo& pageInfo, string stationId, vector<Fields>& result);
// 查询设备信息列表 // 查询设备信息列表
static Errcode queryDeviceList(std::shared_ptr<DaoEntity> dao, vector<Fields>& result, bool sort=false); static Errcode queryDeviceList(std::shared_ptr<DaoEntity> dao, vector<Fields>& result, bool sort=false);
// 查询设备类型定义 // 查询设备类型定义
@@ -112,16 +114,10 @@ public:
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
// === 统计数据管理 === // === 统计数据管理 ===
static Errcode queryStatDataList(std::shared_ptr<DaoEntity> dao, std::string startDate, std::string endDate, vector<Fields>& result); static Errcode queryStatDataList(std::shared_ptr<DaoEntity> dao, std::string startDate, std::string endDate, vector<Fields>& result);
static Errcode queryStatStationGroup(std::shared_ptr<DaoEntity> dao, string stationId, string category, string startDate, string endDate, vector<Fields>& result); static Errcode queryStatStationGroup(std::shared_ptr<DaoEntity> dao, string stationId, string category, string startDate, string endDate, vector<Fields>& result);
static Errcode queryStatStationList(PageInfo& pageInfo, Fields& params, vector<Fields>& result); static Errcode queryStatStationList(PageInfo& pageInfo, Fields& params, vector<Fields>& result);
static Errcode queryWorkModeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result); static Errcode queryWorkModeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result);
static Errcode queryPolicyTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result); static Errcode queryPolicyTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result);
static Errcode insertStatDay(std::shared_ptr<DaoEntity> dao, Fields& fields); static Errcode insertStatDay(std::shared_ptr<DaoEntity> dao, Fields& fields);

View File

@@ -177,7 +177,6 @@ int main(int argc, char** argv)
//OpensslSM2_test(); //OpensslSM2_test();
//SM2_test(); //SM2_test();
// 初始化日志 // 初始化日志
Spdlogger::init(spdlog::level::info, ""); Spdlogger::init(spdlog::level::info, "");
spdlog::info("[main] start ... ======================================================================"); spdlog::info("[main] start ... ======================================================================");
@@ -192,7 +191,7 @@ int main(int argc, char** argv)
QApplication qapp(argc, argv); QApplication qapp(argc, argv);
QString fontFile = QCoreApplication::applicationDirPath() + "/assets/fonts/优设标题黑.ttf"; QString fontFile = QCoreApplication::applicationDirPath() + "/assets/fonts/优设标题黑.ttf";
QFontDatabase::addApplicationFont(fontFile); QFontDatabase::addApplicationFont(fontFile);
QFont font("微软雅黑", 10, 600); QFont font("Cascadia Code, Microsoft YaHei", 10, 600);
QApplication::setFont(font); QApplication::setFont(font);
MainApp mainApp; MainApp mainApp;
return qapp.exec(); return qapp.exec();

View File

@@ -159,6 +159,9 @@ static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
{"/queryStationData", HandlerOptions(&HttpEntity::queryStationData, { DMStation::STATION_ID})}, {"/queryStationData", HandlerOptions(&HttpEntity::queryStationData, { DMStation::STATION_ID})},
{"/queryStationOverview", HandlerOptions(&HttpEntity::queryStationOverview, {DMStation::STATION_ID})}, {"/queryStationOverview", HandlerOptions(&HttpEntity::queryStationOverview, {DMStation::STATION_ID})},
{"/queryStationTodayU", HandlerOptions(&HttpEntity::queryStationTodayU, {DMStation::STATION_ID, "category"})},
{"/queryStationTodayI", HandlerOptions(&HttpEntity::queryStationTodayI, {DMStation::STATION_ID, "category"})},
{"/queryStationTodayP", HandlerOptions(&HttpEntity::queryStationTodayP, {DMStation::STATION_ID, "category"})},
{"/queryDeviceList", HandlerOptions(&HttpEntity::queryDeviceList, {})}, {"/queryDeviceList", HandlerOptions(&HttpEntity::queryDeviceList, {})},
{"/deleteDevice", HandlerOptions(&HttpEntity::deleteDevice, { DMDevice::DEVICE_ID})}, {"/deleteDevice", HandlerOptions(&HttpEntity::deleteDevice, { DMDevice::DEVICE_ID})},
@@ -823,28 +826,120 @@ Errcode HttpEntity::queryStationData(const httplib::Request& req, njson& json, s
njson jsondata; njson jsondata;
if (station) if (station)
{ {
// 温度, 电压、电流、功率、功率因数 /// 储能:电压、电流、功率、功率因数
jsondata["voltage"] = Utils::toStr(station->voltage, 0); {
jsondata["current"] = Utils::toStr(station->current, 0); njson json = njson::object();
jsondata["power"] = Utils::toStr(station->power, 0); json["U"] = Utils::toStr(station->storage.voltage);
jsondata["powerFactor"] = Utils::toStr(station->powerFactor, 0); json["I"] = Utils::toStr(station->storage.current);
jsondata["envTemp"] = Utils::toStr(station->temperature, 0); json["P"] = Utils::toStr(station->storage.power);
jsondata["envhum"] = Utils::toStr(station->humidity, 0); //json["PF"] = Utils::toStr(station->storage.powerFactor, 1);
jsondata["aircStatus"] = station->aircStatus; jsondata["storage"] = json;
jsondata["coolingStatus"] = station->coolingStatus; }
/// 充电:电压、电流、功率、功率因数
{
njson json = njson::object();
json["U"] = Utils::toStr(station->charge.connector1.voltage);
json["I"] = Utils::toStr(station->charge.connector1.current);
json["P"] = Utils::toStr(station->charge.connector1.power);
jsondata["charge"] = json;
}
/// 光伏
{
njson json = njson::object();
json["P"] = Utils::toStr(station->pv.power);
jsondata["pv"] = json;
}
/// 电网
{
njson json = njson::object();
json["U"] = Utils::toStr(station->grid.voltage);
json["I"] = Utils::toStr(station->grid.current);
json["P"] = Utils::toStr(station->grid.power);
//json["PF"] = Utils::toStr(station->grid.powerFactor, 1);
jsondata["grid"] = json;
}
/// 环境:温度、湿度
{
njson json = njson::object();
json["envTemp"] = Utils::toStr(station->temperature, 0);
json["envhum"] = Utils::toStr(station->humidity, 0);
json["aircStatus"] = station->aircStatus;
json["coolingStatus"] = station->coolingStatus;
jsondata["env"] = json;
}
} }
json["data"] = jsondata; json["data"] = jsondata;
return Errcode::OK; return Errcode::OK;
} }
static njson VectorToJsonArray(vector<float>& vec, int n)
{
njson jsonArray = njson::array();
for (int i = 0; i <= n && i < vec.size(); ++i)
{
jsonArray.push_back(int(vec[i]));
}
return jsonArray;
}
// 获取场站今日电压曲线数据category: 1储能2充电3光伏
Errcode HttpEntity::queryStationTodayU(const httplib::Request& req, njson& json, std::string& errmsg)
{
std::string stationId = req.get_param_value("station_id");
std::string catogray = req.get_param_value("category");
njson jsondata;
auto station = Application::data().getStation(Utils::toInt(stationId));
if (station)
{
int n = Utils::timeDaySeconds() / 600;
if (catogray == "1")
{
auto device = station->getDeviceByType(int(EDeviceType::E_METER), "2");
if (device) {
jsondata["U"] = VectorToJsonArray(device->cacheU, n);
jsondata["I"] = VectorToJsonArray(device->cacheI, n);
jsondata["P"] = VectorToJsonArray(device->cacheP, n);
}
}
else if (catogray == "2")
{
auto device = station->getDeviceByType(int(EDeviceType::CHARGER), "1");
if (device) {
jsondata["U"] = VectorToJsonArray(device->cacheU, n);
jsondata["I"] = VectorToJsonArray(device->cacheI, n);
jsondata["P"] = VectorToJsonArray(device->cacheP, n);
}
}
else if (catogray == "3")
{
}
}
json["data"] = jsondata;
return Errcode::OK;
}
// 获取场站今日电流曲线数据category: 1储能2充电3光伏
Errcode HttpEntity::queryStationTodayI(const httplib::Request& req, njson& json, std::string& errmsg)
{
return Errcode::OK;
}
// 获取场站今日功率曲线数据category: 1储能2充电3光伏
Errcode HttpEntity::queryStationTodayP(const httplib::Request& req, njson& json, std::string& errmsg)
{
return Errcode::OK;
}
Errcode HttpEntity::queryDeviceList(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryDeviceList(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
PageInfo pageinfo; PageInfo pageinfo;
pageinfo.index = Utils::toInt(req.get_param_value("page")); pageinfo.index = Utils::toInt(req.get_param_value("page"));
pageinfo.size = Utils::toInt(req.get_param_value("page_size")); pageinfo.size = Utils::toInt(req.get_param_value("page_size"));
string stationId = req.get_param_value("station_id");
std::vector<Fields> result; std::vector<Fields> result;
auto err = DAO::queryDeviceList(pageinfo, result); auto err = DAO::queryDeviceListByStation(pageinfo, stationId, result);
HttpHelper::setPagination(pageinfo, result, json); HttpHelper::setPagination(pageinfo, result, json);
return err; return err;
}; };
@@ -983,14 +1078,20 @@ Errcode HttpEntity::queryDevicCharts(const httplib::Request& req, njson& json, s
int deviceId = params.get<int>("device_id"); int deviceId = params.get<int>("device_id");
auto device = Application::data().getDevice(stationId, deviceId); auto device = Application::data().getDevice(stationId, deviceId);
std::vector<std::string> vecV, vecI, vecP; int npos = Utils::timeDaySeconds() / 600;
std::vector<int> vecU(npos, 0);
std::vector<int> vecI(npos, 0);
std::vector<int> vecP(npos, 0);
if (device) if (device)
{ {
device->getCacheVoltage(vecV); for (size_t i = 0; i < npos; ++i)
device->getCacheCurrent(vecI); {
device->getCachePower(vecP); if (i < device->cacheU.size()) vecU[i] = int(device->cacheU[i]);
if (i < device->cacheI.size()) vecI[i] = int(device->cacheI[i]);
if (i < device->cacheP.size()) vecP[i] = int(device->cacheP[i]);
} }
json["data"] = {{"V", vecV}, {"I", vecI}, {"P", vecP}}; }
json["data"] = {{"V", vecU}, {"I", vecI}, {"P", vecP}};
return Errcode::OK; return Errcode::OK;
} }
@@ -1141,45 +1242,220 @@ Errcode HttpEntity::queryPredictionDetail(const httplib::Request& req, njson& js
return Errcode::OK; return Errcode::OK;
} }
static void VerifyRequstParamsStatDate(Fields& params)
{
if (!params.contains("end_date"))
{
if (!params.contains("start_date"))
{
params.set("end_date", Utils::dateStr());
params.set("start_date", Utils::dateStr(Utils::date() - 86400 * 7));
}
else
{
params.set("end_date", Utils::dateStr(Utils::time(params.value("start_date") + " 00:00:00") + 86400 * 7));
}
}
}
static std::string VerifyStatSqlCondition(Fields& params)
{
std::string stationId = params.value("station_id");
std::string category = params.value("category");
std::string dtStart = params.value("start_date");
std::string dtEnd = params.value("end_date");
std::string sqlCondition;
if (!dtStart.empty() && dtEnd.empty())
{
sqlCondition += "dt BETWEEN '" + dtStart + "' AND '" + dtEnd + "'";
}
if (!stationId.empty())
{
if (!sqlCondition.empty()) sqlCondition += " AND ";
sqlCondition += "ss.station_id='" + stationId + "'";
}
if (!category.empty() && category != "0")
{
//if (!sqlCondition.empty()) sqlCondition += " AND ";
//sqlCondition += "ss.category='" + category + "'";;
}
if (!sqlCondition.empty()) { sqlCondition = " WHERE " + sqlCondition; }
return sqlCondition;
}
static std::string GetRequestStatParams(const httplib::Request& req, Fields& params)
{
GetRequestParams(req, { "station_id", "category", "start_date", "end_date" }, params);
VerifyRequstParamsStatDate(params);
return VerifyStatSqlCondition(params);
}
static string GetStationStatusStr(int status)
{
if (status == 1) return "空闲";
else if (status == 2) return "充电";
else if (status == 2) return "放电";
else if (status == 9) return "故障";
else return "离线";
}
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
std::string sqlCondition = GetRequestStatParams(req, params);
njson jsondata;
std::string launchDate;
float incomeTotal{};
int storageDeviceNum = 0;
int chargeDeviceNum = 0;
int solarDeviceNum = 0;
int capacityTotal{};
bool isQueryStation = params.contains("station_id");
if (isQueryStation)
{
std::string stationId = params.value("station_id");
auto station = Application::data().getStation(Utils::toInt(stationId));
if (station)
{
launchDate = station->launchDate;
storageDeviceNum = 1; //: 储能设备数量
chargeDeviceNum = station->getDeviceCount(2); //: 光伏设备数量
solarDeviceNum = station->getDeviceCount(3); //: 光伏设备数量
capacityTotal = station->capacity; // : 储能总容量kWh精度0.001
jsondata["storage_status"] = GetStationStatusStr(station->storage.status);
jsondata["charge_status"] = GetStationStatusStr(station->charge.status);
jsondata["pv_status"] = "离线";
}
}
else
{
auto& appdata = Application::data();
launchDate = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd
for (auto& item : appdata.mapStation)
{
auto& station = item.second;
storageDeviceNum += 1;
chargeDeviceNum += station->getDeviceCount(2);
solarDeviceNum += station->getDeviceCount(3);
capacityTotal += station->capacity;
}
}
jsondata["launch_date"] = launchDate; // 场站上线启用日期格式yyyy-mm-dd
jsondata["storage_device_num"] = storageDeviceNum; //: 储能设备数量
jsondata["charge_device_num"] = chargeDeviceNum; //: 储能设备数量
jsondata["income_total"] = incomeTotal; // : 累计收益精度0.01
jsondata["solar_device_num"] = solarDeviceNum; //: 光伏设备数量
jsondata["capacity_total"] = capacityTotal; // : 储能总容量kWh精度0.001
// 从 stat_total 表中查询日期最新的一条数据
std::vector<Fields> result;
std::string sql = std::format("SELECT st.* FROM stat_total st INNER JOIN "
"(SELECT station_id, MAX(dt) max_dt FROM stat_total ss {} GROUP BY station_id) tmp "
"ON st.station_id = tmp.station_id AND st.dt = tmp.max_dt; ", sqlCondition);
DaoEntity::execOnce(sql, result);
int eIn = 0;
int eOut = 0;
int tIn = 0;
int tOut = 0;
int nErr = 0;
int eGen = 0;
int eGrid = 0;
int eCharge = 0;
int income = 0;
int incomeCharge = 0;
for (int i=0; i<result.size(); ++i)
{
auto& fields = result[i];
if (isQueryStation)
{
if (params.value("station_id") == fields.value("station_id"))
{
eIn = fields.get<int>("E_in");
eOut = fields.get<int>("E_out");
tIn = fields.get<int>("t_in");
tOut = fields.get<int>("t_out");
eGen = fields.get<int>("E_gen");
eGrid = fields.get<int>("E_grid");
eCharge = fields.get<int>("E_charge");
income = fields.get<int>("income");
}
}
else
{
eIn += fields.get<int>("E_in");
eOut += fields.get<int>("E_out");
tIn += fields.get<int>("t_in");
tOut += fields.get<int>("t_out");
eGen += fields.get<int>("E_gen");
eGrid = fields.get<int>("E_grid");
eCharge += fields.get<int>("E_charge");
income += fields.get<int>("income");
}
}
jsondata["storage_elect_in"] = eIn; //储能充电电量kWh精度0.001
jsondata["storage_elect_out"] = eOut; //储能放电电量kWh精度0.001
jsondata["storage_num_in"] = tIn; //储能设备充电次数
jsondata["storage_num_out"] = tOut; //储能设备放电次数
//jsondata["storage_num_err"] = fields.value("n_err"); //储能设备故障次数
jsondata["solar_elect_gen"] = eGen; //光伏发电电量kWh精度0.001
jsondata["solar_elect_grid"] = eGrid; //光伏入网电量kWh精度0.001
//jsondata["solar_num_err"] = fields.value("n_err_solor"); //光伏设备故障次数
jsondata["charge_elect"] = eCharge; //充电设备充电电量kWh精度0.001
//jsondata["charge_num"] = fields.value("n_charge"); //充电设备充电次数
//jsondata["charge_num_err"] = fields.value("n_err_charge"); //充电设备故障次数
jsondata["income_elect"] = income; //发电收益精度0.01
//jsondata["income_charge"] = fields.value("income_charge"); //充电收益精度0.01
//jsondata["usage_rate"] = 0; //Utils::toStr(float(fields.get<int>("storage_usage") + fields.get<int>("storage_usage")) * 0.5f, 0);
json["data"] = jsondata;
return Errcode::OK;
}
Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
auto& appdata = Application::data(); auto& appdata = Application::data();
float incomeTotal {}; float income = 0.0;
float station_num = appdata.getStationCount(); int nStation = 0;
float solarDeviceNum {}; int nSolar {};
float capacityTotal {}; int capacity {};
float electGenTotal {}; int eGen {};
float electGridTotal {}; int eGrid {};
float electStorageIn {}; int eIn {};
float electStorageOut {}; int eOut {};
for (auto& item : appdata.mapStation) for (auto& item : appdata.mapStation)
{ {
auto& station = item.second; auto& station = item.second;
solarDeviceNum += station->getDeviceCount(3); nStation += 1;
capacityTotal += station->capacity; nSolar += station->getDeviceCount(3);
electGenTotal += station->electGenTotal; capacity += station->capacity;
electGridTotal += station->electGridTotal; eGen += station->electGenTotal;
electStorageIn += station->electStorageIn; eGrid += station->electGridTotal;
electStorageOut += station->electStorageOut; eIn += station->statData.totalElectIn;
eOut += station->statData.totalElectOut;
} }
float income = 0.0;
njson jsondata; njson jsondata;
jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd
jsondata["income_total"] = incomeTotal; // : 累计收益精度0.01 jsondata["income_total"] = income; // : 累计收益精度0.01
jsondata["station_num"] = station_num; // : 能源站数量 jsondata["storage_device_num"] = nStation; //: 储能设备数量
jsondata["storage_device_num"] = station_num; //: 储能设备数量 jsondata["solar_device_num"] = nSolar; //: 光伏设备数量
jsondata["solar_device_num"] = solarDeviceNum; //: 光伏设备数量 jsondata["capacity_total"] = capacity; // : 储能总容量kWh精度0.001
jsondata["capacity_total"] = capacityTotal; // : 储能总容kWh精度0.001 jsondata["solar_elect_gen"] = eGen; // : 发电总电kWh精度0.001
jsondata["solar_elect_gen"] = electGenTotal; // : 发电总电量kWh精度0.001 jsondata["solar_elect_grid"] = eGrid; // : 入网总电量kWh精度0.001
jsondata["solar_elect_grid"] = electGridTotal; // : 入网种电量kWh精度0.001 jsondata["storage_elect_in"] = eIn; // : 储能充电总电量kWh精度0.001
jsondata["storage_elect_in"] = electStorageIn; // : 储能电总电量kWh精度0.001 jsondata["storage_elect_out"] = eOut; // : 储能电总电量kWh精度0.001
jsondata["storage_elect_out"] = electStorageOut; // : 储能放电总电量kWh精度0.001
// 总览页面:累计收益 // 总览页面:累计收益
std::string sql = "SELECT * FROM stat_total st INNER JOIN " std::string sql = "SELECT st.* FROM stat_total st INNER JOIN "
"(SELECT station_id, MAX(dt) max_dt FROM stat_total GROUP BY station_id) tmp " "(SELECT station_id, MAX(dt) max_dt FROM stat_total GROUP BY station_id) tmp "
"ON st.station_id = tmp.station_id AND st.dt = tmp.max_dt; "; "ON st.station_id = tmp.station_id AND st.dt = tmp.max_dt; ";
std::vector<Fields> result; std::vector<Fields> result;
@@ -1216,119 +1492,7 @@ Errcode HttpEntity::queryStatStationGroup(const httplib::Request& req, njson& js
return Errcode(err); return Errcode(err);
} }
static void VerifyRequstParamsStatDate(Fields& params)
{
if (!params.contains("end_date"))
{
if (!params.contains("start_date"))
{
params.set("end_date", Utils::dateStr());
params.set("start_date", Utils::dateStr(Utils::date() - 86400*7));
}
else
{
params.set("end_date", Utils::dateStr(Utils::time(params.value("start_date") +" 00:00:00") + 86400*7));
}
}
}
static std::string VerifyStatSqlCondition(Fields& params)
{
std::string stationId = params.value("station_id");
std::string category = params.value("category");
std::string dtStart = params.value("start_date");
std::string dtEnd = params.value("end_date");
std::string sqlCondition;
if (!dtStart.empty() && dtEnd.empty())
{
sqlCondition += "dt BETWEEN '" + dtStart + "' AND '" + dtEnd + "'";
}
if (!stationId.empty())
{
if (!sqlCondition.empty()) sqlCondition += " AND ";
sqlCondition += "ss.station_id='" + stationId + "'";
}
if (!category.empty() && category != "0")
{
//if (!sqlCondition.empty()) sqlCondition += " AND ";
//sqlCondition += "ss.category='" + category + "'";;
}
if (!sqlCondition.empty()) { sqlCondition = " WHERE " + sqlCondition; }
return sqlCondition;
}
static std::string GetRequestStatParams(const httplib::Request& req, Fields& params)
{
GetRequestParams(req, {"station_id", "category", "start_date", "end_date"}, params);
VerifyRequstParamsStatDate(params);
return VerifyStatSqlCondition(params);
}
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
std::string sqlCondition = GetRequestStatParams(req, params);
//std::string sql = R"(SELECT
// SUM(storage_elect_in) storage_elect_in,
// SUM(storage_elect_out) storage_elect_out,
// SUM(storage_num_in) storage_num_in,
// SUM(storage_num_out) storage_num_out,
// SUM(storage_num_err) storage_num_err,
// SUM(solar_elect_gen) solar_elect_gen,
// SUM(solar_elect_grid) solar_elect_grid,
// SUM(solar_num_err) solar_num_err,
// AVG(storage_usage) storage_usage,
// SUM(charge_elect) charge_elect,
// SUM(charge_num) charge_num,
// SUM(charge_num_err) charge_num_err,
// AVG(charge_usage) charge_usage,
// SUM(income_elect) income_elect,
// SUM(income_charge) income_charge
// FROM stat_day ss)" + sqlCondition + ";";
std::string stationId = params.value("station_id");
njson jsondata;
auto station = Application::data().getStation(Utils::toInt(stationId));
if (station)
{
jsondata["launch_date"] = station->launchDate;
}
auto& appdata = Application::data();
std::vector<Fields> result;
std::string sql = std::format("SELECT * FROM stat_total st INNER JOIN "
"(SELECT station_id, MAX(dt) max_dt FROM stat_total ss {} GROUP BY station_id) tmp "
"ON st.station_id = tmp.station_id AND st.dt = tmp.max_dt; ", sqlCondition);
DaoEntity::execOnce(sql, result);
if (result.size() > 0)
{
auto& fields = result[0];
//jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd
// jsondata["station_id"] = station_id;
jsondata["storage_elect_in"] = fields.value("E_in"); //储能充电电量kWh精度0.001
jsondata["storage_elect_out"] = fields.value("E_out"); //储能放电电量kWh精度0.001
jsondata["storage_num_in"] = fields.value("t_in"); //储能设备充电次数
jsondata["storage_num_out"] = fields.value("t_out"); //储能设备放电次数
jsondata["storage_num_err"] = fields.value("n_err"); //储能设备故障次数
jsondata["solar_elect_gen"] = fields.value("E_gen"); //光伏发电电量kWh精度0.001
jsondata["solar_elect_grid"] = fields.value("E_grid"); //光伏入网电量kWh精度0.001
jsondata["solar_num_err"] = fields.value("n_err_solor"); //光伏设备故障次数
jsondata["charge_elect"] = fields.value("E_charge"); //充电设备充电电量kWh精度0.001
jsondata["charge_num"] = fields.value("n_charge"); //充电设备充电次数
jsondata["charge_num_err"] = fields.value("n_err_charge"); //充电设备故障次数
jsondata["income_elect"] = fields.value("income"); //发电收益精度0.01
jsondata["income_charge"] = fields.value("income_charge"); //充电收益精度0.01
jsondata["usage_rate"] = 0; //Utils::toStr(float(fields.get<int>("storage_usage") + fields.get<int>("storage_usage")) * 0.5f, 0);
json["data"] = jsondata;
}
return Errcode::OK;
}
Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; Fields params;
@@ -1362,6 +1526,7 @@ Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, s
njson jsondata = njson::array(); njson jsondata = njson::array();
for (int64_t t = t0; t<=t1; t += 86400) for (int64_t t = t0; t<=t1; t += 86400)
{ {
i++;
njson jsonrow; njson jsonrow;
std::string dt = Utils::dateStr(t); std::string dt = Utils::dateStr(t);
Fields* fields = NULL; Fields* fields = NULL;

View File

@@ -55,9 +55,24 @@ public:
Errcode deleteStation(const httplib::Request& req, njson& json, std::string& errmsg); Errcode deleteStation(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryStationOverview(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStationOverview(const httplib::Request& req, njson& json, std::string& errmsg);
/// 查询场站信息
// @param: station_id
// @return: object
Errcode queryStationInfo(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStationInfo(const httplib::Request& req, njson& json, std::string& errmsg);
/// 查询场站信息
// @param: station_id
// @return: object
Errcode queryStationData(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStationData(const httplib::Request& req, njson& json, std::string& errmsg);
// 获取场站今日电压曲线数据category: 1储能2充电3光伏
Errcode queryStationTodayU(const httplib::Request& req, njson& json, std::string& errmsg);
// 获取场站今日电流曲线数据category: 1储能2充电3光伏
Errcode queryStationTodayI(const httplib::Request& req, njson& json, std::string& errmsg);
// 获取场站今日功率曲线数据category: 1储能2充电3光伏
Errcode queryStationTodayP(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryDeviceList(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryDeviceList(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode insertDevice(const httplib::Request& req, njson& json, std::string& errmsg); Errcode insertDevice(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode updateDevice(const httplib::Request& req, njson& json, std::string& errmsg); Errcode updateDevice(const httplib::Request& req, njson& json, std::string& errmsg);
@@ -83,12 +98,14 @@ public:
Errcode queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg);
// 系统总览所有场站统计 (总览页 运行状况) /// 总览: 查询累计统计信息
Errcode queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg); // @param: station_id 可选,无该参数时查询所有场站累计数据
Errcode queryStatStationGroup(const httplib::Request& req, njson& json, std::string& errmsg);
// 一个场站的累计统计
Errcode queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg);
// 总览: 所有场站统计 (总览页 运行状况)
Errcode queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryStatStationGroup(const httplib::Request& req, njson& json, std::string& errmsg);
// 场站按类别按天统计 // 场站按类别按天统计
Errcode queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg);

View File

@@ -408,7 +408,8 @@ void MqttClient::ParseArrivedMessage(njson& json, string command, std::shared_pt
} }
device->setParam(addr, val); device->setParam(addr, val);
if (command == "MEM_YC") { station->readRuntimeData(deviceNo, addr, val); } if (command == "MEM_YC") { station->readEnergyData(deviceNo, addr, val); }
else if (command == "Charger_YC") { station->readChargeData(deviceNo, addr, val); }
else if (command == "Fire40_YX") { station->readFire40Data(deviceNo, addr, val); } else if (command == "Fire40_YX") { station->readFire40Data(deviceNo, addr, val); }
else if (command == "TH_YC") { station->readTHData(deviceNo, addr, val); } else if (command == "TH_YC") { station->readTHData(deviceNo, addr, val); }
else if (command == "Cooling_YX" || command == "Cooling_YC") { station->readCoolingData(deviceNo, addr, val); } else if (command == "Cooling_YX" || command == "Cooling_YC") { station->readCoolingData(deviceNo, addr, val); }

View File

@@ -18,7 +18,7 @@ MainApp::MainApp()
this->setAutoFillBackground(true); this->setAutoFillBackground(true);
this->setPalette(palette); this->setPalette(palette);
this->setStyleSheet("color: white;"); this->setStyleSheet("color: white;");
this->setFixedSize(1440, 900); this->setFixedSize(1600, 900);
this->show(); this->show();
this->setAttribute(Qt::WA_StyledBackground, true); // 启用样式表背景绘制 this->setAttribute(Qt::WA_StyledBackground, true); // 启用样式表背景绘制
@@ -43,6 +43,7 @@ QPushButton* MainApp::addMenuItem(int index, string itemName)
{ {
auto itemBtn = new QPushButton(itemName.c_str()); auto itemBtn = new QPushButton(itemName.c_str());
itemBtn->setStyleSheet(QSS_BTN_MENU.c_str()); itemBtn->setStyleSheet(QSS_BTN_MENU.c_str());
//itemBtn->setFont(QFont("微软雅黑", 16, 600));
mapMenuBtn[itemName] = itemBtn; mapMenuBtn[itemName] = itemBtn;
QObject::connect(itemBtn, &QPushButton::clicked, this, [=]() { this->setActiveMenu(itemName); }); QObject::connect(itemBtn, &QPushButton::clicked, this, [=]() { this->setActiveMenu(itemName); });

View File

@@ -42,6 +42,7 @@ static const std::string QSS_TABLE =
" gridline-color: #C0C0C0;" // 网格线颜色 " gridline-color: #C0C0C0;" // 网格线颜色
" border: 1px solid gray;" // 边框 " border: 1px solid gray;" // 边框
" color: white;" // 文字颜色 " color: white;" // 文字颜色
" outline: 2px solid #409EFF;" // 选中焦点轮廓
"}" "}"
// 表头样式 // 表头样式
"QHeaderView { background-color: rgba(150,150,150,50);}" "QHeaderView { background-color: rgba(150,150,150,50);}"
@@ -60,7 +61,6 @@ static const std::string QSS_TABLE =
"QTableWidget::item:selected {" "QTableWidget::item:selected {"
" background-color: rgba(184, 214, 255, 50);" // 选中背景色 " background-color: rgba(184, 214, 255, 50);" // 选中背景色
" color: rgb(220,220,220);" // 选中文字颜色 " color: rgb(220,220,220);" // 选中文字颜色
" outline: none; "
"}"; "}";
static const std::string QSS_BTN_COMBOX = static const std::string QSS_BTN_COMBOX =
@@ -128,7 +128,7 @@ std::shared_ptr<QTableWidget> MyQUI::TableWidget(QWidget* parent, int x, int y,
table->setSelectionMode(QAbstractItemView::SingleSelection); // 设置为单选模式 table->setSelectionMode(QAbstractItemView::SingleSelection); // 设置为单选模式
table->setSelectionBehavior(QAbstractItemView::SelectRows); // 设置为整行选中 table->setSelectionBehavior(QAbstractItemView::SelectRows); // 设置为整行选中
table->horizontalHeader()->setFixedHeight(50); table->horizontalHeader()->setFixedHeight(50);
table->horizontalHeader()->setDefaultSectionSize(60); table->horizontalHeader()->setDefaultSectionSize(50); // 设置默认行宽
return table; return table;
} }

View File

@@ -14,8 +14,6 @@ QWHome::QWHome(QWidget* parent) : MyWidget(parent)
this->setObjectName("home"); this->setObjectName("home");
this->setStyleSheet("#home { background-color:rgba(100,100,100,50); }"); this->setStyleSheet("#home { background-color:rgba(100,100,100,50); }");
int x = 10, y = 0; int x = 10, y = 0;
{ {
//this->groupSys = MyQUI::GroupBox(this, x, y, 1190, 120, "系统"); //this->groupSys = MyQUI::GroupBox(this, x, y, 1190, 120, "系统");
@@ -47,29 +45,29 @@ QWHome::QWHome(QWidget* parent) : MyWidget(parent)
this->addPair("db-n", pw, 20, 20, "数据库名: ", Config::option.database.dbname); this->addPair("db-n", pw, 20, 20, "数据库名: ", Config::option.database.dbname);
this->addPair("db-h", pw, 20, 50, "主机地址: ", Config::option.database.host); this->addPair("db-h", pw, 20, 50, "主机地址: ", Config::option.database.host);
this->addPair("db-u", pw, 20, 80, "用 户 名: ", Config::option.database.user); this->addPair("db-u", pw, 20, 80, "用 户 名: ", Config::option.database.user);
}
QStringList headerTextList; QStringList headerTextList;
headerTextList << "ID" << "站名" << "编号" << "状态" << "MQTT状态" << "召测(秒)" headerTextList << "ID" << "站名" << "编号" << "状态" << "MQTT状态" << "召测(秒)"
<< "日充电\n电量" << "日放电\n电量" << "总充电\n电量" << "总放电\n电量" << "日充电\n电量" << "日放电\n电量" << "总充电\n电量" << "总放电\n电量"
<< "日充电\n费用" << "日放电\n费用" << "总充电\n费用" << "总放电\n费用" << "日充电\n费用" << "日放电\n费用" << "总充电\n费用" << "总放电\n费用"
<< "日收益" << "总收益" << "--"; << "日收益" << "总收益" << "--";
table = MyQUI::TableWidget(this, 10, y += 210, 1350, 265);
table = MyQUI::TableWidget(this, 10, y += 210, 1190, 265);
// 设置为水平表头 // 设置为水平表头
table->setColumnCount(headerTextList.size()); table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList); table->setHorizontalHeaderLabels(headerTextList);
table->setColumnWidth(0, 50); table->setColumnWidth(0, 40);
table->setColumnWidth(1, 120); table->setColumnWidth(1, 120);
table->setColumnWidth(2, 50); table->setColumnWidth(2, 40);
table->setColumnWidth(4, 80); table->setColumnWidth(4, 80);
} table->setColumnWidth(5, 70);
logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false); logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false);
btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除"); btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除");
QObject::connect(btnLogClean.get(), &QPushButton::clicked, this, &QWHome::slotBtnClearLog); QObject::connect(btnLogClean.get(), &QPushButton::clicked, this, &QWHome::slotBtnClearLog);
texteditLog = std::make_shared<QTextEdit>(this); texteditLog = std::make_shared<QTextEdit>(this);
texteditLog->setGeometry(10, y += 35, 1190, 280); texteditLog->setGeometry(10, y += 35, 1350, 340);
texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;"); texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;");
texteditLog->setReadOnly(true); texteditLog->setReadOnly(true);
texteditLog->document()->setMaximumBlockCount(1000); texteditLog->document()->setMaximumBlockCount(1000);

View File

@@ -39,7 +39,7 @@ QWMonitor::QWMonitor(QWidget* parent) : MyWidget(parent)
} }
QStringList headerTextList; QStringList headerTextList;
headerTextList << "ID" << "类型ID" << "类型名称" << "设备名称" << "编号" << "状态" << "通讯\n状态" << "工作\n状态" << "故障\n状态"; headerTextList << "ID" << "类型ID" << "类型名称" << "设备名称" << "编号" << "状态" << "通讯\n状态" << "工作\n状态" << "故障\n状态" << "--";
table = MyQUI::TableWidget(this, 10, y += 50, 700, 800); table = MyQUI::TableWidget(this, 10, y += 50, 700, 800);
// 设置为水平表头 // 设置为水平表头
@@ -73,7 +73,7 @@ QWMonitor::QWMonitor(QWidget* parent) : MyWidget(parent)
uiReg.scroll->setWidgetResizable(true); uiReg.scroll->setWidgetResizable(true);
std::string QSS_LISTVIEW = std::string QSS_LISTVIEW =
"QListView { background-color: transparent; color: white; }" "QListView { background-color: transparent; color: white; outline: 1px solid #409EFF;}"
"QListView::item { background-color: transparent; border-bottom: 0px solid gray; padding: 0px; height: 20px; }"; "QListView::item { background-color: transparent; border-bottom: 0px solid gray; padding: 0px; height: 20px; }";
uiReg.listReg = new QListWidget(groupStation.get()); uiReg.listReg = new QListWidget(groupStation.get());

View File

@@ -24,17 +24,17 @@ QWStatistics::QWStatistics(QWidget* parent) : MyWidget(parent)
headerTextList << "日期" << "日充电\n电量" << "日放电\n电量" headerTextList << "日期" << "日充电\n电量" << "日放电\n电量"
<< "日充电\n电量(尖)" << "日充电\n电量(峰)" << "日充电\n电量(平)" << "日充电\n电量(谷)" << "日充电\n电量(尖)" << "日充电\n电量(峰)" << "日充电\n电量(平)" << "日充电\n电量(谷)"
<< "日放电\n电量(尖)" << "日放电\n电量(峰)" << "日放电\n电量(平)" << "日放电\n电量(谷)" << "日放电\n电量(尖)" << "日放电\n电量(峰)" << "日放电\n电量(平)" << "日放电\n电量(谷)"
<< "日充电\n费用" << "日放电\n费用" << "日收益" ; << "日充电\n费用" << "日放电\n费用" << "日收益" << "--";
//<< "总充电\n电量" << "总放电\n电量" //<< "总充电\n电量" << "总放电\n电量"
//<< "总充电\n电量(尖)" << "总充电\n电量(峰)" << "总充电\n电量(平)" << "总充电\n电量(谷)" //<< "总充电\n电量(尖)" << "总充电\n电量(峰)" << "总充电\n电量(平)" << "总充电\n电量(谷)"
//<< "总放电\n电量(尖)" << "总放电\n电量(峰)" << "总放电\n电量(平)" << "总放电\n电量(谷)"; //<< "总放电\n电量(尖)" << "总放电\n电量(峰)" << "总放电\n电量(平)" << "总放电\n电量(谷)";
table = MyQUI::TableWidget(this, 10, 50, 1190, 800); table = MyQUI::TableWidget(this, 10, 50, 1350, 800);
table->horizontalHeader()->setDefaultSectionSize(80); table->horizontalHeader()->setDefaultSectionSize(80);
// 设置为水平表头 // 设置为水平表头
table->setColumnCount(headerTextList.size()); table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList); table->setHorizontalHeaderLabels(headerTextList);
table->setColumnWidth(0, 120); table->setColumnWidth(0, 100);
btnRefresh = make_shared<QPushButton>("刷新", this); btnRefresh = make_shared<QPushButton>("刷新", this);
btnRefresh->setGeometry(220, 10, 60, 30); btnRefresh->setGeometry(220, 10, 60, 30);

View File

@@ -283,7 +283,7 @@ QWSysmgr::QWSysmgr(QWidget* parent) : MyWidget(parent)
QStringList headerTextList; QStringList headerTextList;
//headerTextList << "ID" << "类型ID" << "类型名称" << "设备名称" << "编号" << "状态" << "通讯\n状态" << "工作\n状态" << "故障\n状态"; //headerTextList << "ID" << "类型ID" << "类型名称" << "设备名称" << "编号" << "状态" << "通讯\n状态" << "工作\n状态" << "故障\n状态";
table = MyQUI::TableWidget(this, 10, y += 100, 1190, 740); table = MyQUI::TableWidget(this, 10, y += 100, 1350, 740);
// 设置为水平表头 // 设置为水平表头
table->setColumnCount(headerTextList.size()); table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList); table->setHorizontalHeaderLabels(headerTextList);

View File

@@ -218,18 +218,18 @@ export const columnList = [
dataIndex: 'operation_date', dataIndex: 'operation_date',
key: 'operation_date' key: 'operation_date'
}, },
{ // {
title: '场站运行模式', // title: '场站运行模式',
dataIndex: 'work_mode', // dataIndex: 'work_mode',
key: 'work_mode', // key: 'work_mode',
scopedSlots: { customRender: 'work_mode' } // scopedSlots: { customRender: 'work_mode' }
}, // },
{ // {
title: '场站运行策略', // title: '场站运行策略',
dataIndex: 'policy_id', // dataIndex: 'policy_id',
key: 'policy_id', // key: 'policy_id',
scopedSlots: { customRender: 'policy_id' } // scopedSlots: { customRender: 'policy_id' }
}, // },
{ {
title: '操作', title: '操作',
dataIndex: 'operate', dataIndex: 'operate',

View File

@@ -18,6 +18,24 @@ const locale = ref(zhCN)
</script> </script>
<style lang="scss"> <style lang="scss">
*{
-webkit-touch-callout:none; /*系统默认菜单被禁用*/
-webkit-user-select:none; /*webkit浏览器*/
-khtml-user-select:none; /*早期浏览器*/
-moz-user-select:none;/*火狐*/
-ms-user-select:none; /*IE10*/
user-select:none;
}
input{
-webkit-user-select:auto; /*webkit浏览器*/
user-select:auto;
}
textarea{
-webkit-user-select:auto; /*webkit浏览器*/
user-select:auto;
}
#app { #app {
position: absolute; position: absolute;
top: 0; top: 0;

View File

@@ -1,12 +1,12 @@
<template> <template>
<div class="alarm"> <div class="alarm">
<div class="text_Cur"> <!-- <div class="text_Cur">
<div v-for="item in curList" :key="item.key"> <div v-for="item in curList" :key="item.key">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<span class="mark">{{ item.value ? item.value : 0 }}</span> <span class="mark">{{ item.value ? item.value : 0 }}</span>
<span class="d">{{ item.d }}</span> <span class="d">{{ item.d }}</span>
</div> </div>
</div> </div> -->
<div id="alarm-chart"></div> <div id="alarm-chart"></div>
</div> </div>
</template> </template>

View File

@@ -1,12 +1,12 @@
<template> <template>
<div class="charge"> <div class="charge">
<div class="text_Cur"> <!-- <div class="text_Cur">
<div v-for="item in curList" :key="item.key"> <div v-for="item in curList" :key="item.key">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<span class="mark">{{ item.value ? item.value : 0 }}</span> <span class="mark">{{ item.value ? item.value : 0 }}</span>
<span class="d">{{ item.d }}</span> <span class="d">{{ item.d }}</span>
</div> </div>
</div> </div> -->
<div id="charge-chart"></div> <div id="charge-chart"></div>
</div> </div>
</template> </template>
@@ -24,6 +24,10 @@ export default {
deviceInfo: { deviceInfo: {
type: Array, type: Array,
default: () => [] default: () => []
},
myData: {
type: Number,
default: () => -1
} }
}, },
data() { data() {
@@ -95,6 +99,10 @@ export default {
} }
}, },
deep: true // 确保深度比较 deep: true // 确保深度比较
},
myData: {
handler(newVal,oldVal) {
},
} }
}, },
mounted() {}, mounted() {},
@@ -122,34 +130,33 @@ export default {
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.chargeChartData.ydata[index] = { this.chargeChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: true, // smooth: true,
type: 'line', // type: 'line',
barWidth: 10, // barWidth: 10,
itemStyle: { // itemStyle: {
borderRadius: 10, // borderRadius: 10,
// color: item.lineColor
// },
// emphasis: {
// focus: 'series'
// },
// areaStyle: {
// global: false,
// color: {
// type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
// colorStops: [
// { offset: 0, color: JSON.parse(JSON.stringify(item)).colorStart }, // 顶部颜色
// { offset: 1, color: JSON.parse(JSON.stringify(item)).colorEnd } // 底部颜色
// ]
// }
// },
// global: false,
// showSymbol: false,
// yAxisIndex: index,
// data: result.values[index]
type: 'bar',
data: [18,25,39,17,37,41,62],
color: item.lineColor color: item.lineColor
},
emphasis: {
focus: 'series'
},
areaStyle: {
global: false,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: JSON.parse(JSON.stringify(item)).colorStart }, // 顶部颜色
{ offset: 1, color: JSON.parse(JSON.stringify(item)).colorEnd } // 底部颜色
]
}
},
global: false,
showSymbol: false,
yAxisIndex: index,
data: result.values[index]
} }
}) })
}, },
@@ -196,8 +203,9 @@ export default {
}, },
yAxis: [ yAxis: [
{ {
name: '充电电量(kW·h)', name: '充电电量(kWh)',
type: 'value', type: 'value',
splitNumber: 2,
nameTextStyle: { nameTextStyle: {
color: '#fff' // 绿色名称 color: '#fff' // 绿色名称
}, },
@@ -205,15 +213,16 @@ export default {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
axisLabel: { axisLabel: {
interval: 4, // interval: 2,
color: '#fff', color: '#fff',
fontSize:12 fontSize:12
}, },
// axisLine : {show: true, color: '#f00'}
}, },
{ {
name: '充电收益(元)', name: '充电收益(元)',
type: 'value', type: 'value',
splitNumber: 2,
splitLine: { splitLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -221,14 +230,18 @@ export default {
color: '#fff' // 绿色名称 color: '#fff' // 绿色名称
}, },
axisLabel: { axisLabel: {
interval: 4, // interval: 4,
color: '#fff', color: '#fff',
fontSize:12 fontSize:12
}, },
// axisLine : {show: true, lineStyle: { color: '#ff0000', width: 2 } }
}, },
], ],
series: this.chargeChartData.ydata series: this.chargeChartData.ydata
// serise: [
// { name: '2011', type: 'bar', data: [18, 23, 29, 10, 13, 63] }
// ]
} }
option && chargeChart.setOption(option) option && chargeChart.setOption(option)
this.setupResizeListener() this.setupResizeListener()
@@ -244,10 +257,10 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.charge { .charge {
height: calc(100% - 45px); height: calc(100% - 35px);
background-color: #50505050;
#charge-chart { #charge-chart {
height: calc(100% - 45px); height: calc(100% - 5px);
} }
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="energy"> <div class="energy">
<div class="text_Cur"> <!-- <div class="text_Cur">
<div v-for="item in curList" :key="item.key"> <div v-for="item in curList" :key="item.key">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<div> <div>
@@ -8,7 +8,7 @@
<span class="d">{{ item.d }}</span> <span class="d">{{ item.d }}</span>
</div> </div>
</div> </div>
</div> </div> -->
<div id="energy-chart"></div> <div id="energy-chart"></div>
</div> </div>
</template> </template>
@@ -104,19 +104,22 @@ export default {
arr.forEach((item, index) => { arr.forEach((item, index) => {
this.energyChartData.ydata[index] = { this.energyChartData.ydata[index] = {
name: item.name, name: item.name,
smooth: true, // type: 'line',
type: 'line', // smooth: true,
barWidth: 5, // barWidth: 5,
itemStyle: { // itemStyle: {
borderRadius: [5, 5, 0, 0], // borderRadius: [5, 5, 0, 0],
// color: item.lineColor
// },
// emphasis: {
// focus: 'series'
// },
// global: false,
// showSymbol: false,
// data: result.values[index]
type: 'bar',
data: [5,3,6,3,8,4,6],
color: item.lineColor color: item.lineColor
},
emphasis: {
focus: 'series'
},
global: false,
showSymbol: false,
data: result.values[index]
} }
}) })
}, },
@@ -164,6 +167,7 @@ export default {
name: '电量(kW·h)', name: '电量(kW·h)',
nameTextStyle: { color: '#fff' }, nameTextStyle: { color: '#fff' },
type: 'value', type: 'value',
splitNumber: 2,
splitLine: { splitLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -189,10 +193,10 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.energy { .energy {
height: calc(100% - 45px); height: calc(100% - 35px);
background-color: #50505030;
#energy-chart { #energy-chart {
height: calc(100% - 45px); height: calc(100% - 5px);
} }
} }

View File

@@ -15,7 +15,7 @@
:position="[marker.lon, marker.lat]" :position="[marker.lon, marker.lat]"
:key="marker.id" :key="marker.id"
:icon="marker.iconMap" :icon="marker.iconMap"
style="width: 20px;height: auto" style="height: auto"
@click="clickArrayMarker(marker)" @click="clickArrayMarker(marker)"
:title="marker.name" :title="marker.name"
> >
@@ -235,7 +235,8 @@ export default {
} }
:deep(.tdt-marker-icon){ :deep(.tdt-marker-icon){
height:auto!important; width: 40px !important;
height:auto !important;
} }
} }
</style> </style>

View File

@@ -1,27 +1,25 @@
<template> <template>
<div class="Home"> <div class="Home">
<div class="content-left"> <div class="content-left">
<div v-for="item in leftList" :key="item.componentId" :class="`grid-item ${item.class}`"> <div v-for="item in listLeft" :key="item.componentId" :class="`grid-item ${item.class}`">
<div class="tool"> <div class="tool">
<div class="title"> <div class="title">
<span class="linear-text">{{ item.title }}</span> <span class="linear-text">{{ item.title }}</span>
</div> </div>
</div> </div>
<component <component :is="item.componentId" :prop-key="item.infoKey"
:is="item.componentId" :prop-data="compData[item.infoKey]"
:props-info="modalInfo[item.infoKey]" :props-info="modalInfo[item.infoKey]"
:props-total=" :props-total="['prefab', 'envTotal'].includes(item.infoKey)
['prefab', 'envTotal'].includes(item.infoKey)
? item.infoKey == 'prefab' ? item.infoKey == 'prefab'
? modalInfo.prefabTotal ? modalInfo.prefabTotal
: modalInfo.envInfoTotal : modalInfo.envInfoTotal
: modalInfo.allTotal : modalInfo.allTotal
" "></component>
></component>
</div> </div>
</div> </div>
<div class="content-right"> <div class="content-right">
<div v-for="item in rightList" :key="item.componentId" :class="`grid-item ${item.class}`"> <div v-for="item in listRight" :key="item.componentId" :class="`grid-item ${item.class}`">
<div class="tool"> <div class="tool">
<div class="title"> <div class="title">
<span class="linear-text">{{ item.title }}</span> <span class="linear-text">{{ item.title }}</span>
@@ -43,12 +41,14 @@ import OperationalInfo from '@/components/Home/Modal/OperationalInfo.vue'
import StatisticalInfo from '@/components/Home/Modal/StatisticalInfo.vue' import StatisticalInfo from '@/components/Home/Modal/StatisticalInfo.vue'
import Revenue from '@/components/Home/Modal/Revenue.vue' import Revenue from '@/components/Home/Modal/Revenue.vue'
import Utilization from '@/components/Home/Modal/Utilization.vue' import Utilization from '@/components/Home/Modal/Utilization.vue'
import DisCharge from '@/components/Home/Modal/DisCharge.vue' // import DisCharge from '@/components/Home/Modal/DisCharge.vue'
import { getReq, postReq } from '@/request/api' import { getReq, postReq } from '@/request/api'
import { getRunDays, getDateDaysAgo } from '@/utils/dealWithData' import { getRunDays, getDateDaysAgo } from '@/utils/dealWithData'
import EnvInfo from './Modal/EnvInfo.vue' import EnvInfo from './Modal/EnvInfo.vue'
import { markRaw } from 'vue'; import { markRaw } from 'vue';
import StationVoltage from '@/components/Home/Modal/StationVoltage.vue'
import StationCurrent from '@/components/Home/Modal/StationCurrent.vue'
import StationPower from '@/components/Home/Modal/StationPower.vue'
export default { export default {
name: 'Home', name: 'Home',
components: {}, components: {},
@@ -63,62 +63,79 @@ export default {
refreshInterval:null, refreshInterval:null,
modalInfo: {}, modalInfo: {},
list: [ compData: {},
{
title: '预制舱信息',
class: '',
componentId: markRaw( PrefabCabin),
infoKey: 'prefab'
},
{
title: '储能充放电量',
class: 'stats-cards',
componentId:markRaw( DisCharge),
infoKey: 'energy'
},
{
title: '运行信息',
class: 'operation-status',
componentId:markRaw( OperationalInfo),
infoKey: 'envTotal'
},
{
title: '场站收益情况',
class: 'revenue',
componentId:markRaw( Revenue),
infoKey: 'energy'
},
{ listLeft: [
title: '统计信息', { title: '场站信息', class: '', componentId: markRaw( PrefabCabin), infoKey: 'prefab' },
class: 'statistical', { title: '储能运行信息', class: 'operation-status', componentId: markRaw(OperationalInfo), infoKey: 'storage' },
componentId:markRaw( StatisticalInfo), { title: '充电运行信息', class: 'operation-status', componentId: markRaw(OperationalInfo), infoKey: 'charge' },
infoKey: '' { title: '光伏运行信息', class: 'operation-status', componentId: markRaw(OperationalInfo), infoKey: 'pv' },
}, { title: '电网侧运行信息', class: 'operation-status', componentId: markRaw(OperationalInfo), infoKey: 'grid' },
{ { title: '环境信息', class: 'envInfo', componentId:markRaw( EnvInfo), infoKey: 'envTotal' }
title: '设备利用率',
class: '',
componentId:markRaw( Utilization),
infoKey: 'energy'
},
{
title: '环境信息',
class: 'envInfo',
componentId:markRaw( EnvInfo),
infoKey: 'envTotal'
}
], ],
listRight: [
{ title: '今日电压曲线', class: 'stats-cards', componentId:markRaw(StationVoltage), infoKey: 'voltage' },
{ title: '今日电流曲线', class: 'revenue', componentId:markRaw(StationCurrent), infoKey: 'current' },
{ title: '今日功率曲线', class: '', componentId:markRaw(StationPower), infoKey: 'power' },
],
// list: [
// {
// title: '场站信息',
// class: '',
// componentId: markRaw( PrefabCabin),
// infoKey: 'prefab'
// },
// {
// title: '储能充放电量',
// class: 'stats-cards',
// componentId:markRaw( DisCharge),
// infoKey: 'energy'
// },
// {
// title: '运行信息',
// class: 'operation-status',
// componentId:markRaw( OperationalInfo),
// infoKey: 'envTotal'
// },
// {
// title: '场站收益情况',
// class: 'revenue',
// componentId:markRaw( Revenue),
// infoKey: 'energy'
// },
// {
// title: '统计信息',
// class: 'statistical',
// componentId:markRaw( StatisticalInfo),
// infoKey: ''
// },
// {
// title: '设备利用率',
// class: '',
// componentId:markRaw( Utilization),
// infoKey: 'energy'
// },
// {
// title: '环境信息',
// class: 'envInfo',
// componentId:markRaw( EnvInfo),
// infoKey: 'envTotal'
// }
// ],
sysName: '', sysName: '',
user: JSON.parse(localStorage.getItem('permission')) || {} user: JSON.parse(localStorage.getItem('permission')) || {}
} }
}, },
computed: { computed: {
leftList() { // leftList() {
return this.list.filter((_, index) => index % 2 === 0).slice(0, 4) // 左列取前3个偶数索引 // return this.list.filter((_, index) => index % 2 === 0).slice(0, 4) // 左列取前3个偶数索引
}, // },
rightList() { // rightList() {
return this.list.filter((_, index) => index % 2 !== 0).slice(0, 3) // 右列取前3个奇数索引 // return this.list.filter((_, index) => index % 2 !== 0).slice(0, 3) // 右列取前3个奇数索引
} // }
}, },
beforeUnmount() { beforeUnmount() {
if(this.refreshInterval){ if(this.refreshInterval){
@@ -140,7 +157,9 @@ export default {
this.getStatTotalList(), this.getStatTotalList(),
this.queryStationInfo(), this.queryStationInfo(),
this.queryStationData(), this.queryStationData(),
this.getStatDayList(1) this.getStatDayList(1),
this.getStatDayList(2),
this.getStatDayList(3),
]) ])
}, },
// 查询系统累计统计信息 // 查询系统累计统计信息
@@ -157,10 +176,12 @@ export default {
} }
const res = await getReq('/queryStatTotal', query) const res = await getReq('/queryStatTotal', query)
if (res.errcode === 0) { if (res.errcode === 0) {
this.modalInfo.allTotal = res.data this.compData.prefab = { stats: res.data }
this.modalInfo.allTotal.runDays = getRunDays(res.data.launch_date) // this.compData.prefab.run_days = getRunDays(res.data.launch_date)
const { income_charge: incomeCharge, income_elect: incomeElect } = this.modalInfo.allTotal // this.modalInfo.allTotal = res.data
this.modalInfo.allTotal.incomeTotal = +incomeCharge + +incomeElect // this.modalInfo.allTotal.run_days = getRunDays(res.data.launch_date)
// const { income_charge: incomeCharge, income_elect: incomeElect } = this.modalInfo.allTotal
// this.modalInfo.allTotal.incomeTotal = +incomeCharge + +incomeElect
} else { } else {
throw res throw res
} }
@@ -171,37 +192,32 @@ export default {
// 查询场站实时数据 // 查询场站实时数据
async queryStationData() { async queryStationData() {
try { try {
// station_id场站ID const res = await getReq('/queryStationData', { station_id: this.stationId })
const query = {
station_id: this.stationId
}
const res = await getReq('/queryStationData', query)
if (res.errcode === 0) { if (res.errcode === 0) {
this.modalInfo.envInfoTotal = res.data // this.compData.prefab = { data: res.data }
this.compData.storage = res.data['storage']
this.compData.charge = res.data['charge']
this.compData.pv = res.data['pv']
this.compData.grid = res.data['grid']
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.modalInfo.envInfoTotal = {} this.compData.storage = this.compData.charge = this.compData.pv = this.compData.grid = {}
} }
}, },
// 查询场站信息 // 查询场站信息
async queryStationInfo() { async queryStationInfo() {
try { try {
// station_id场站ID const res = await getReq('/queryStationInfo', { station_id: this.stationId })
const query = {
station_id: this.stationId
}
const res = await getReq('/queryStationInfo', query)
if (res.errcode === 0) { if (res.errcode === 0) {
this.modalInfo.prefabTotal = res.data this.compData.prefab = { info: res.data }
this.compData.prefab.info.run_days = getRunDays(res.data.launch_date)
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.modalInfo.allTotal = {} this.compData.prefab = { info: {}}
} }
}, },
// 查询场站日统计信息 // 查询场站日统计信息
@@ -214,19 +230,27 @@ export default {
const query = { const query = {
station_id: this.stationId, station_id: this.stationId,
category, category,
start_date: getDateDaysAgo(7 - 1), // start_date: getDateDaysAgo(7 - 1),
end_date: getDateDaysAgo(0) // end_date: getDateDaysAgo(0)
} }
const categoryObj = { 1: 'energy' } // const res = await getReq('/queryStatDayList', query)
const res = await getReq('/queryStatDayList', query) const res = await getReq('/queryStationTodayU', query)
if (res.errcode === 0) { if (res.errcode === 0) {
this.modalInfo[categoryObj[category]] = res.data.map((item) => { if (category === 1) {
const { income_charge: incomeCharge, income_elect: incomeElect } = item this.modalInfo.voltage = [{ index: 0, data: res.data.U }]
return { this.modalInfo.current = [{ index: 0, data: res.data.I }]
...item, this.modalInfo.power = [{ index: 0, data: res.data.P }]
incomeTotal: +incomeCharge + +incomeElect }
else if (category === 2){
this.modalInfo.voltage = [{ index: 1, data: res.data.U }]
this.modalInfo.current = [{ index: 1, data: res.data.I }]
this.modalInfo.power = [{ index: 1, data: res.data.P }]
}
else if (category === 3){
this.modalInfo.voltage = [{ index: 2, data: res.data.U }]
this.modalInfo.current = [{ index: 2, data: res.data.I }]
this.modalInfo.power = [{ index: 2, data: res.data.P }]
} }
})
} else { } else {
throw res throw res
} }
@@ -284,7 +308,7 @@ export default {
-webkit-background-clip: text; -webkit-background-clip: text;
background-clip: text; background-clip: text;
font-size: 18px; font-size: 18px;
font-weight: 400; font-weight: 1000;
margin-left: 28px; margin-left: 28px;
} }
@@ -315,7 +339,7 @@ export default {
.text { .text {
margin-left: 20px; margin-left: 20px;
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 1000;
background: linear-gradient( background: linear-gradient(
90deg, 90deg,
rgba(0, 186, 173, 0.15) 0%, rgba(0, 186, 173, 0.15) 0%,
@@ -330,7 +354,7 @@ export default {
} }
} }
.operation-status { .operation-status {
height: calc(25% - 10px); height: calc(15% - 10px);
} }
.statistical { .statistical {
height: calc(18% - 10px); height: calc(18% - 10px);

View File

@@ -8,7 +8,7 @@
/> />
<div class="right"> <div class="right">
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
<span>{{ item.value }} {{ item.d }}</span> <span style="color: #a0f0a0; font-size: 16px;">{{ item.value }} {{ item.d }}</span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4,8 +4,11 @@
<div v-for="item in list" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in list" :key="item.key" :class="`item ${item.class}`">
<a-image :preview="false" :src="item.iconPath" :width="50" class="left"> </a-image> <a-image :preview="false" :src="item.iconPath" :width="50" class="left"> </a-image>
<div class="right"> <div class="right">
<span>{{ item.label }}</span> <span class="k">{{ item.label }}</span>
<span>{{ item.value }} {{ item.d }}</span> <div>
<span class="v">{{ item.value }}</span>
<span class="d">{{ item.d }}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -16,86 +19,48 @@
export default { export default {
name: '', name: '',
props: { props: {
propsTotal: { propKey: { type: String, default: '' },
type: Object, propData: { type: Object, default: () => { } },
default: () => {}
},
propsInfo: {
type: Array,
default: () => []
},
}, },
data() { data() {
return { return {
list: [ itemDef: {
// { U: { key: 'U', value: '--', d: 'V', label: '电压', class: 'item-3', iconPath: require('@/assets/home/dianya.png') },
// key: 'tianshu', I: { key: 'I', value: '--', d: 'A', label: '电流', class: 'item-4', iconPath: require('@/assets/home/dianliu.png') },
// value: 26, P: { key: 'P', value: '--', d: 'kW', label: '功率', class: 'item-5', iconPath: require('@/assets/home/gonglv.png') },
// d: '℃', // PF: { key: 'PF', value: '--', d: '', label: '功率因数', class: 'item-6', iconPath: require('@/assets/home/gonglv.png') }
// label: '舱内温度',
// class: 'item-1',
// iconPath: require('@/assets/home/wendu.png')
// },
// {
// key: 'shouyi',
// value: 25,
// d: '%',
// label: '舱内湿度',
// class: 'item-2',
// iconPath: require('@/assets/home/shidu.png')
// },
{
key: 'voltage',
value: 24,
d: 'V',
label: '电压',
class: 'item-3',
iconPath: require('@/assets/home/dianya.png')
}, },
{
key: 'current',
value: 26,
d: 'A',
label: '电流',
class: 'item-4',
iconPath: require('@/assets/home/dianliu.png')
},
{
key: 'power',
value: 20,
d: 'kW',
label: '功率',
class: 'item-5',
iconPath: require('@/assets/home/gonglv.png')
},
{
key: 'powerFactor',
value: 100,
d: '',
label: '功率因数',
class: 'item-6',
iconPath: require('@/assets/home/gonglv.png')
}
]
} }
}, },
computed: { computed: {
}, },
watch: { watch: {
propsTotal: { propKey: {
handler(newVal, oldVal) {
if (this.propKey === 'grid') {
this.list = [this.itemDef.P]
}
else if (this.propKey === 'pv') {
this.list = [this.itemDef.P]
}
else {
this.list = [this.itemDef.U, this.itemDef.I, this.itemDef.P]
}
},
immediate: true,
},
propData: {
handler(newVal, oldVal) { handler(newVal, oldVal) {
if (newVal !== oldVal) { if (newVal !== oldVal) {
this.list.forEach((item) => { this.list.forEach((item) => {
item.value = this.propsTotal[item.key]||0 item.value = this.propData[item.key] || 0
}) })
} }
}, }
} }
}, },
mounted() {}, mounted() { },
methods: {} methods: {}
} }
</script> </script>
@@ -104,44 +69,51 @@ export default {
.operationlInfo { .operationlInfo {
height: calc(100% - 45px); height: calc(100% - 45px);
display: flex; display: flex;
justify-content: center; // justify-content: center;
align-items: center; align-items: center;
width: 95%; width: 95%;
margin: auto; margin: auto;
} }
.content { .content {
flex-wrap: wrap; flex-wrap: wrap;
width: 90%; width: 100%;
display: flex; display: flex;
align-items: center; // align-items: center;
justify-content: space-around; // justify-content: space-around;
height: 100%; height: 100%;
padding-left: calc(10%);
.item { .item {
height: 50%; width: 30%;
width: 45%; height: 50px;
// height: 47px;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
align-items: center; // align-items: center;
// justify-content: center; // justify-content: center;
// text-align: center; // text-align: center;
& > span:nth-child(1) {
font-size: 12px;
margin-bottom: 10px;
}
.d {
margin-left: 1px;
font-size: 12px;
}
} }
.right { .right {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-left: 20px; margin-left: 10px;
.k {
color: #e0e0e0;
font-size: 12px;
}
.v {
color: #a0f0a0;
font-size: 16px;
}
.d {
margin-left: 8px;
font-size: 14px;
}
} }
} }
</style> </style>

View File

@@ -1,6 +1,18 @@
<template> <template>
<div class="prefabCabin"> <div class="prefabCabin">
<div class="content-left"> <div style="display: flex; flex-direction: row; flex-wrap: wrap;" >
<div v-for="item in [...myItemsInfo, ...myItemsStats]" :key="item.key" :class="`item ${item.class}`">
<div style="display: flex; flex-direction: column; justify-items: flex-start;">
<span style="color: #e0e0e0;">{{ item.label }}</span>
<div style="display: flex; justify-content: flex-end; line-height: 1;">
<span class="v">{{ item.value ? item.value : 0 }}</span>
<span class="d">{{ item.d }}</span>
</div>
</div>
</div>
</div>
<!-- <div class="content-left">
<div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`">
<div> <div>
<span>{{ item.value ? item.value : 0 }}</span <span>{{ item.value ? item.value : 0 }}</span
@@ -8,13 +20,13 @@
</div> </div>
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
</div> </div>
</div> </div> -->
<div style="text-align: center; font-weight: 500"> <!-- <div style="text-align: center; font-weight: 500">
<div class="prefabCabin-icon"></div> <div class="prefabCabin-icon"></div>
<span>{{ curStatus }}</span> <span>{{ curStatus }}</span>
</div> </div> -->
<div class="content-right"> <!-- <div class="content-right">
<div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`">
<div> <div>
<span>{{ item.value ? item.value : 0 }}</span <span>{{ item.value ? item.value : 0 }}</span
@@ -22,7 +34,7 @@
</div> </div>
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
</div> </div>
</div> </div> -->
</div> </div>
</template> </template>
@@ -30,6 +42,7 @@
export default { export default {
name: '', name: '',
props: { props: {
propData: { type: Object, default: () => {} },
propsTotal: { propsTotal: {
type: Object, type: Object,
default: () => {} default: () => {}
@@ -42,6 +55,24 @@ export default {
data() { data() {
return { return {
curStatus: '充电', curStatus: '充电',
myItemsInfo: [
{ key: 'capacity', value: '', label: '电池储能容量', d: 'kWh' },
{ key: 'voltage_rated', value: '', label: '电池额定总电压', d: 'V' },
{ key: 'cooling_type', value: '', label: '冷却方式', d: '' },
{ key: 'batttey_type', value: '', label: '电池类型', d: '' },
{ key: 'run_days', value: '', label: '场站运行天数', d: '天' },
],
myItemsStats: [
{ key: 'storage_device_num', value: '', label: '储能设备数量', d: '个' },
{ key: 'solar_device_num', value: '', label: '光伏设备数量', d: '个' },
{ key: 'charge_device_num', value: '', label: '充电设备数量', d: '个' },
{ key: 'solar_elect_grid', value: '', label: '上网总电量', d: 'kWh' },
{ key: 'storage_elect_in', value: '', label: '储能充电总电量', d: 'kWh' },
{ key: 'solar_elect_gen', value: '', label: '光伏发电总电量', d: 'kWh' },
{ key: 'charge_elect', value: '', label: '充电桩充电总电量', d: 'kWh' },
{ key: 'income_elect', value: '', label: '收益总金额', d: '元' },
{ key: 'storage_elect_out', value: '', label: '储能放电总电量', d: 'kWh' },
],
list: [ list: [
{ {
key: 'batttey_type', key: 'batttey_type',
@@ -123,20 +154,41 @@ export default {
} }
}, },
watch: { watch: {
propData: {
handler(newVal, oldVal) {
if (newVal !== oldVal) {
if (this.propData.stats) {
this.myItemsStats.forEach((item) => {
item.value = this.propData.stats[item.key] != undefined ? this.propData.stats[item.key] : '--'
});
}
if (this.propData.info) {
this.myItemsInfo.forEach((item) => {
item.value = this.propData.info[item.key] != undefined ? this.propData.info[item.key] : '--'
});
}
}
}
},
propsTotal: { propsTotal: {
handler(newVal, oldVal) { handler(newVal, oldVal) {
if (newVal !== oldVal) { if (newVal !== oldVal) {
// 0正常 1故障 // 0正常 1故障
this.curStatus=['故障','正常'][this.propsTotal.status] this.curStatus=['故障','正常'][this.propsTotal.status]
this.list.forEach((item) => { // this.list.forEach((item) => {
if(item.key=='work_mode'){ // if(item.key=='work_mode'){
item.value = ['手动','峰谷套利','配网增容','应急供电','并网保电','自定时段'][this.propsTotal[item.key]] // item.value = ['手动','峰谷套利','配网增容','应急供电','并网保电','自定时段'][this.propsTotal[item.key]]
// console.log(item.list.map((item)=>this.propsTotal[item.key]==item.value)[0].label,"145",item.list.map((item)=>this.propsTotal[item.key]==item.value)) // // console.log(item.list.map((item)=>this.propsTotal[item.key]==item.value)[0].label,"145",item.list.map((item)=>this.propsTotal[item.key]==item.value))
// item.value =item.list.map((item)=>==item.value)[0].label // // item.value =item.list.map((item)=>==item.value)[0].label
}else { // }else {
item.value = this.propsTotal[item.key] // item.value = this.propsTotal[item.key]
} // }
}) // })
} }
} }
} }
@@ -152,29 +204,48 @@ export default {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-left: 10px;
margin-right: 10px;
} }
.item { .item {
height: 57px; height: 40px;
background: linear-gradient( width: calc(25% - 5px);
180deg, margin-right: 5px;
rgba(15, 227, 255, 0.3) 0%, margin-bottom: 5px;
rgba(15, 227, 255, 0.09) 45.6%, background: url('@/assets/home/onLineBg.png');
rgba(15, 227, 255, 0.3) 100% background-size: contain;
); background-size: 100% 100%;
padding: 10px 8px; background-repeat: no-repeat;
// background: linear-gradient(
// 180deg,
// rgba(15, 227, 255, 0.3) 0%,
// rgba(15, 227, 255, 0.09) 45.6%,
// rgba(15, 227, 255, 0.3) 100%
// );
// padding: 10px 8px;
min-width: 115px; min-width: 115px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
text-align: center; text-align: center;
& > span:nth-child(1) { & > span:nth-child(1) {
padding: 0;
margin: 0;
font-size: 12px; font-size: 12px;
margin-bottom: 10px; margin-bottom: 10px;
} }
.v {
color: #a0f0a0;
line-height: 1;
}
.d { .d {
margin-left: 1px; display: block;
text-align: left;
margin-left: 5px;
font-size: 12px; font-size: 12px;
min-width: 40px;
height: 16px;
} }
} }

View File

@@ -0,0 +1,177 @@
<template>
<div class="mychart">
<div id="chart-current"></div>
</div>
</template>
<script>
import {processData} from '@/utils/dealWithData'
export default {
name: '',
props: {
propsInfo: {
type: Array,
default: () => []
}
},
data() {
return {
curList: [
{
name: '储能设备',
key: 'storage_elect_in',
lineColor: '#9BD801',
value: 0,
d: 'kW·h'
},
{
name: '充电设备',
key: 'storage_elect_out',
lineColor: '#3DFEFA',
value: 0,
d: 'kW·h'
}
],
myChart: null,
chartData: {
ydata: [],
xdata: []
}
}
},
watch: {
propsInfo: {
handler(newVal, oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.$nextTick(() => {
this.updateChart()
})
}
},
deep: true // 确保深度比较
}
},
mounted() {},
beforeUnmount() {
window.removeEventListener('resize', this.handleResize)
if (this.myChart) {
this.myChart.dispose()
this.myChart = null
}
},
methods: {
handleResize() {
if (this.myChart) {
this.myChart.resize()
}
},
createChartXData()
{
const timeArray = [];
const dateZero = new Date();
dateZero.setHours(0, 0, 0, 0); // 重置为当天0点
for (let i=0; i<144; ++i)
{
// 累加10分钟
const currentTime = new Date(dateZero.getTime() + i * 600 * 1000);
// 格式化为 HH:mm
const hours = currentTime.getHours().toString().padStart(2, '0');
const minutes = currentTime.getMinutes().toString().padStart(2, '0');
timeArray.push(`${hours}:${minutes}`);
}
return timeArray
},
initChart() {
const chartDom = document.getElementById('chart-current')
if (!chartDom) return
if (this.myChart) this.myChart.dispose()
this.myChart = this.$echarts.init(chartDom)
const xdata = this.createChartXData();
const option = {
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
legend: { top: 0, textStyle: { color: '#fff' } },
grid: { left: '3%', right: '4%', top: '40px', bottom: '5%', },
xAxis: {
type: 'category',
data: xdata,
axisLine: { lineStyle: { type: 'dashed', color: '#435463' } },
axisLabel: { color: '#fff' }
},
yAxis: {
name: "电流(A)",
type: 'value',
nameTextStyle: { color: '#fff' },
splitLine: {
lineStyle: { type: 'dashed', color: '#435463' }
},
axisLabel: { color: '#fff', fontSize: 12 },
},
series: []
}
this.curList.forEach((item, index) => {
option.series.push({
name: item.name,
index: index,
smooth: true,
type: 'line',
barWidth: 10,
itemStyle: { borderRadius: 10, color: item.lineColor },
emphasis: { focus: 'series' },
global: false,
showSymbol: false,
data: []
})
})
option && this.myChart.setOption(option)
},
updateChart(activeKey) {
if (!this.myChart) {
this.initChart()
}
if (this.propsInfo) {
let series = []
this.propsInfo.forEach((item)=> {
if (item.index != undefined && item.index < this.curList.length) {
series.push({
name: this.curList[item.index].name,
data: item.data
})
}
})
if (series.length > 0) {
this.myChart.setOption({
xAxis: { data: this.createChartXData() },
series: series
});
this.setupResizeListener()
}
}
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize)
}
}
}
</script>
<style lang="scss" scoped>
.mychart {
height: calc(100% - 35px);
#chart-current {
height: calc(100% - 5px);
}
}
</style>

View File

@@ -0,0 +1,191 @@
<template>
<div class="mychart">
<div id="chart-power"></div>
</div>
</template>
<script>
import {processData} from '@/utils/dealWithData'
export default {
name: '',
props: {
propsInfo: {
type: Array,
default: () => []
}
},
data() {
return {
curList: [
{
name: '储能设备',
key: 'storage_elect_in',
lineColor: '#9BD801',
value: 0,
d: 'kW·h'
},
{
name: '充电设备',
key: 'storage_elect_out',
lineColor: '#3DFEFA',
value: 0,
d: 'kW·h'
},
{
name: '光伏设备',
key: 'storage_elect_out',
lineColor: '#3DFEFA',
value: 0,
d: 'kW·h'
},
{
name: '电网侧',
key: 'storage_elect_out',
lineColor: '#3DFEFA',
value: 0,
d: 'kW·h'
}
],
myChart: null,
chartData: {
ydata: [],
xdata: []
}
}
},
watch: {
propsInfo: {
handler(newVal, oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.$nextTick(() => {
this.updateChart()
})
}
},
deep: true // 确保深度比较
}
},
mounted() {},
beforeUnmount() {
window.removeEventListener('resize', this.handleResize)
if (this.myChart) {
this.myChart.dispose()
this.myChart = null
}
},
methods: {
handleResize() {
if (this.myChart) {
this.myChart.resize()
}
},
createChartXData()
{
const timeArray = [];
const dateZero = new Date();
dateZero.setHours(0, 0, 0, 0); // 重置为当天0点
for (let i=0; i<144; ++i)
{
// 累加10分钟
const currentTime = new Date(dateZero.getTime() + i * 600 * 1000);
// 格式化为 HH:mm
const hours = currentTime.getHours().toString().padStart(2, '0');
const minutes = currentTime.getMinutes().toString().padStart(2, '0');
timeArray.push(`${hours}:${minutes}`);
}
return timeArray
},
initChart() {
const chartDom = document.getElementById('chart-power')
if (!chartDom) return
if (this.myChart) this.myChart.dispose()
this.myChart = this.$echarts.init(chartDom)
const xdata = this.createChartXData();
const option = {
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
legend: { top: 0, textStyle: { color: '#fff' } },
grid: { left: '3%', right: '4%', top: '40px', bottom: '5%', },
xAxis: {
type: 'category',
data: xdata,
axisLine: { lineStyle: { type: 'dashed', color: '#435463' } },
axisLabel: { color: '#fff' }
},
yAxis: {
name: "功率(kW)",
type: 'value',
nameTextStyle: { color: '#fff' },
splitLine: {
lineStyle: { type: 'dashed', color: '#435463' }
},
axisLabel: { color: '#fff', fontSize: 12 },
},
series: []
}
this.curList.forEach((item, index) => {
option.series.push({
name: item.name,
index: index,
smooth: true,
type: 'line',
barWidth: 10,
itemStyle: { borderRadius: 10, color: item.lineColor },
emphasis: { focus: 'series' },
global: false,
showSymbol: false,
data: []
})
})
option && this.myChart.setOption(option)
},
updateChart(activeKey) {
if (!this.myChart) {
this.initChart()
}
if (this.propsInfo) {
let series = []
this.propsInfo.forEach((item)=> {
if (item.index != undefined && item.index < this.curList.length) {
series.push({
name: this.curList[item.index].name,
data: item.data
})
}
})
if (series.length > 0) {
this.myChart.setOption({
xAxis: { data: this.createChartXData() },
series: series
});
this.setupResizeListener()
}
}
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize)
}
}
}
</script>
<style lang="scss" scoped>
.mychart {
height: calc(100% - 35px);
#chart-power {
height: calc(100% - 5px);
}
}
</style>

View File

@@ -0,0 +1,178 @@
<template>
<div class="mychart">
<div id="chart-voltage"></div>
</div>
</template>
<script>
import {processData} from '@/utils/dealWithData'
export default {
name: '',
props: {
propsInfo: {
type: Array,
default: () => []
}
},
data() {
return {
curList: [
{
name: '储能设备',
key: 'storage_elect_in',
lineColor: '#9BD801',
value: 0,
d: 'kW·h'
},
{
name: '充电设备',
key: 'storage_elect_out',
lineColor: '#3DFEFA',
value: 0,
d: 'kW·h'
}
],
myChart: null,
chartData: {
ydata: [],
xdata: []
}
}
},
watch: {
propsInfo: {
handler(newVal, oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.$nextTick(() => {
this.updateChart()
})
}
},
deep: true // 确保深度比较
}
},
mounted() {},
beforeUnmount() {
window.removeEventListener('resize', this.handleResize)
if (this.myChart) {
this.myChart.dispose()
this.myChart = null
}
},
methods: {
handleResize() {
if (this.myChart) {
this.myChart.resize()
}
},
createChartXData()
{
const timeArray = [];
const dateZero = new Date();
dateZero.setHours(0, 0, 0, 0); // 重置为当天0点
for (let i=0; i<144; ++i)
{
// 累加10分钟
const currentTime = new Date(dateZero.getTime() + i * 600 * 1000);
// 格式化为 HH:mm
const hours = currentTime.getHours().toString().padStart(2, '0');
const minutes = currentTime.getMinutes().toString().padStart(2, '0');
timeArray.push(`${hours}:${minutes}`);
}
return timeArray
},
initChart() {
const chartDom = document.getElementById('chart-voltage')
if (!chartDom) return
if (this.myChart) this.myChart.dispose()
this.myChart = this.$echarts.init(chartDom)
const xdata = this.createChartXData();
const option = {
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
legend: { top: 0, textStyle: { color: '#fff' } },
grid: { left: '3%', right: '4%', top: '40px', bottom: '5%', },
xAxis: {
type: 'category',
data: xdata,
axisLine: { lineStyle: { type: 'dashed', color: '#435463' } },
axisLabel: { color: '#fff' }
},
yAxis: {
name: '电压(V)',
type: 'value',
nameTextStyle: { color: '#fff' },
splitLine: {
lineStyle: { type: 'dashed', color: '#435463' }
},
axisLabel: { color: '#fff', fontSize: 12 },
},
series: []
}
this.curList.forEach((item, index) => {
option.series.push({
name: item.name,
index: index,
smooth: true,
type: 'line',
barWidth: 10,
itemStyle: { borderRadius: 10, color: item.lineColor },
emphasis: { focus: 'series' },
global: false,
showSymbol: false,
data: []
})
})
option && this.myChart.setOption(option)
},
updateChart(activeKey) {
if (!this.myChart) {
this.initChart()
}
if (this.propsInfo) {
let series = []
this.propsInfo.forEach((item)=> {
if (item.index != undefined && item.index < this.curList.length) {
series.push({
name: this.curList[item.index].name,
data: item.data
})
}
})
if (series.length > 0) {
this.myChart.setOption({
xAxis: { data: this.createChartXData() },
series: series
});
this.setupResizeListener()
}
}
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize)
window.addEventListener('resize', this.handleResize)
}
}
}
</script>
<style lang="scss" scoped>
.mychart {
height: calc(100% - 35px);
#chart-voltage {
height: calc(100% - 5px);
}
}
</style>

View File

@@ -0,0 +1,173 @@
<template>
<div class="mychart">
<!-- <div class="text_Cur">
<div v-for="item in curList" :key="item.key">
<div>{{ item.name }}</div>
<span class="mark">{{ item.value ? item.value : 0 }}</span>
<span class="d">{{ item.d }}</span>
</div>
</div> -->
<div :id="myChartId" class="mychart"></div>
</div>
</template>
<script>
import { processData } from '@/utils/dealWithData'
export default {
name: '',
props: {
propKey: { type: String, default: '' },
propData: { type: Array, default: () => [] },
propOption: { type: Object, default: { series: [] } }
},
data() {
return {
myChartId: 'mychart' + Math.floor(Math.random() * 9999),
myEchart: null,
xData: [], // EChart的 x 轴 option
yData: [], // EChart的 y 轴 option
}
},
watch: {
propData: {
handler(newVal, oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.$nextTick(() => {
this.drawLineChart()
})
}
},
immediate: true, // 初始化时更新
deep: true // 确保深度比较
},
propOption: {
handler(newVal, oldVal) {
},
immediate: true,
}
},
mounted() { },
beforeUnmount() {
window.removeEventListener('resize', this.handleResize)
if (this.myEchart) {
this.myEchart.dispose()
this.myEchart = null
}
},
methods: {
handleResize() {
if (this.myEchart) {
this.myEchart.resize()
}
},
getChartData() {
const keyList = this.propOption.series.map((item) => item.key)
const result = processData(this.propData, keyList)
this.xData = result.dates
this.yData = result.values
if (this.xData.length == 0) {
const today = new Date();
for (let i = 6; i >= 0; i--) {
const date = new Date(today); // 每次创建新日期实例(避免修改原日期)
date.setDate(today.getDate() - i); // 往前推 i 天
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份 0-11需 +1
const day = String(date.getDate()).padStart(2, '0');
this.xData.push(`${month}-${day}`);
for (let j = 0; j < keyList.length; j++) {
if (j == 0) this.yData.push([])
else this.yData[j].push(0)
}
}
}
},
drawLineChart(activeKey) {
this.getChartData(activeKey)
if (this.myEchart) {
this.myEchart.dispose()
}
const chartDom = document.getElementById(this.myChartId)
if (!chartDom) return;
let myEchart = this.$echarts.init(chartDom)
this.myEchart = myEchart
let option = {
animation: false,
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
legend: { top: 10, textStyle: { color: '#fff' } },
grid: { left: '3%', right: '4%', bottom: '1%', top: '32%' },
xAxis: {
type: 'category',
data: this.xData,
axisLine: { lineStyle: { type: 'dashed', color: '#435463' } },
axisLabel: { color: '#fff' }
},
yAxis: [],
series: []
}
const yAxisItem = {
name: '',
type: 'value',
min: 0,
max: 2,
//interval: 1, // 强制步长
splitNumber: 2, // 分段数
nameTextStyle: { color: '#fff' },
splitLine: { lineStyle: { type: 'dashed', color: '#435463' } },
axisLabel: { color: '#fff', fontSize: 12 },
}
if (this.propOption.yAxis) {
this.propOption.yAxis.forEach((item, index) => {
const maxVal = Math.max(...this.yData[index]);
if (maxVal && maxVal > 0) {
yAxisItem.min = undefined
yAxisItem.max = maxVal
}
yAxisItem.name = item
option.yAxis.push(yAxisItem)
})
}
if (this.propOption.series) {
this.propOption.series.forEach((item, index) => {
option.series.push({
name: item.name,
type: 'bar',
color: item.color,
data: this.yData[index],
barWidth: '20%'
})
})
}
if (option.yAxis.length == 0) { option.yAxis.push(yAxisItem) }
option && myEchart.setOption(option)
this.setupResizeListener()
},
setupResizeListener() {
window.removeEventListener('resize', this.handleResize);
window.addEventListener('resize', this.handleResize)
}
}
}
</script>
<style lang="scss" scoped>
.mychart {
height: calc(100% - 35px);
background-color: #80808010;
.mychart {
height: calc(100% - 5px);
}
}
</style>

View File

@@ -166,6 +166,7 @@ export default {
{ {
name: '收益(元)', name: '收益(元)',
type: 'value', type: 'value',
splitNumber: 2,
splitLine: { splitLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -173,7 +174,7 @@ export default {
color: '#fff' // 绿色名称 color: '#fff' // 绿色名称
}, },
axisLabel: { axisLabel: {
interval: 4, // interval: 4,
color: '#fff', color: '#fff',
fontSize:12 fontSize:12
@@ -182,6 +183,7 @@ export default {
{ {
name: '利用率(%)', name: '利用率(%)',
type: 'value', type: 'value',
splitNumber: 2,
nameTextStyle: { nameTextStyle: {
color: '#fff' // 绿色名称 color: '#fff' // 绿色名称
}, },
@@ -189,10 +191,9 @@ export default {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
axisLabel: { axisLabel: {
interval: 4, // interval: 4,
color: '#fff', color: '#fff',
fontSize:12 fontSize:12
}, },
}, },
], ],
@@ -212,7 +213,7 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.operational { .operational {
height: calc(100% - 45px); height: calc(100% - 45px);
background-color: #50505030;
#operational-chart { #operational-chart {
height: 100%; height: 100%;

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="pv"> <div class="pv">
<div class="text_Cur"> <!-- <div class="text_Cur">
<div v-for="item in curList" :key="item.key"> <div v-for="item in curList" :key="item.key">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<div> <div>
@@ -8,7 +8,7 @@
<span class="d">{{ item.d }}</span> <span class="d">{{ item.d }}</span>
</div> </div>
</div> </div>
</div> </div> -->
<div id="pv-chart"></div> <div id="pv-chart"></div>
</div> </div>
</template> </template>
@@ -37,13 +37,13 @@ export default {
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
}, },
{ // {
name: '入网电量', // name: '入网电量',
key: 'solar_elect_grid', // key: 'solar_elect_grid',
lineColor: '#0E68E4', // lineColor: '#0E68E4',
value: 0, // value: 0,
d: 'kW·h' // d: 'kW·h'
} // }
], ],
pvChart: null, pvChart: null,
pvChartData: { pvChartData: {
@@ -164,6 +164,7 @@ export default {
name: '电量(kW·h)', name: '电量(kW·h)',
nameTextStyle: { color: '#fff' }, nameTextStyle: { color: '#fff' },
type: 'value', type: 'value',
splitNumber: 2,
splitLine: { splitLine: {
lineStyle: { type: 'dashed', color: '#435463' } lineStyle: { type: 'dashed', color: '#435463' }
}, },
@@ -189,10 +190,10 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.pv { .pv {
height: calc(100% - 45px); height: calc(100% - 35px);
background-color: #50505050;
#pv-chart { #pv-chart {
height: calc(100% - 45px); height: calc(100% - 5px);
} }
} }

View File

@@ -0,0 +1,177 @@
<template>
<div class="total-station">
<div class="content-my">
<div v-for="item in myItems" :key="item.key" :class="`item ${item.class}`" >
<span style="color:#d0d0d0; margin: 0 0 0 0">{{ item.label }}</span>
<div style="margin-left: 20%;">
<span :style="{ 'color': item.color, 'font-size':'16px', 'font-weight':600}">{{ item.value ? item.value : (item.d ? 0 : '--') }}</span>
<span style="font-size:16px; margin-left: 8px;">{{ item.d }}</span>
</div>
</div>
</div>
<!-- <div class="content-left">
<div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`">
<span>{{ item.label }}</span>
<div>
<span>{{ item.value ? item.value : 0 }}</span
><span class="d">{{ item.d }}</span>
</div>
</div>
</div> -->
<!-- <div class="online-icon"></div> -->
<!-- <div class="content-right">
<div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`">
<span>{{ item.label }}</span>
<div>
<span>{{ item.value ? item.value : 0 }}</span
><span class="d">{{ item.d }}</span>
</div>
</div>
</div> -->
</div>
</template>
<script>
export default {
name: '',
props: {
propKey: {
type: String,
default: ''
},
propData: {
type: Object,
default: () => {}
},
deviceInfo: {
type: Array,
default: () => []
}
},
data() {
return {
myItems: [
{ color:'#a0f0a0', key: 'runDays', value: 0, label:'场站运行天数', d:'天'},
// { color:'#a0f0a0', key: 'storage_device_num', value: 0, label:'储能设备数量', d:'个'},
// { color:'#a0f0a0', key: 'charge_device_num', value: 0, label:'充电设备数量', d:'个'},
// { color:'#a0f0a0', key: 'solar_device_num', value: 0, label:'光伏设备数量', d:'个'},
// { color:'#a0f0a0', key: 'solar_elect_grid', value: 0, label:'上网总电量', d:'kWh'},
{ color:'#a0f0a0', key: 'storage_elect_in', value: 0, label:'累计储能总电量', d:'kWh'},
// { color:'#a0f0a0', key: 'charge_elect_out', value: 0, label:'充电桩充电总电量', d:'kWh'},
// { color:'#a0f0a0', key: 'solar_elect_gen', value: 0, label:'光伏发电总电量', d:'kWh'},
{ color:'#a0f0a0', key: 'income_elect', value: 0, label:'累计收益总金额', d:'元'},
// { color:'#a0f0a0', key: 'storage_elect_out', value: 0, label:'储能放电总电量', d:'kWh'},
{ color:'#a0f0a0', key: 'storage_status', value: '空闲', label:'储能状态'},
{ color:'#a0f0a0', key: 'charge_status', value: '空闲', label:'充电状态'},
{ color:'#a0f0a0', key: 'pv_status', value: '离线', label:'光伏状态'},
],
}
},
computed: {
},
watch: {
propKey: {
handler(newVal, oldVal) {
// if (this.propKey === 'totalStation') this.myItems[0].label = '场站运行天数'
},
immediate: true,
},
propData: {
handler(newVal, oldVal) {
if (newVal && newVal !== oldVal) {
this.myItems.forEach((item) => {
item.value = newVal[item.key] || (item.d ? 0 : '')
if (item.value === '离线' || item.value === '故障') item.color = '#f08080'
else if (item.value === '空闲') item.color = '#f0f0a0'
else if (item.value === '充电' || item.value === '放电' || item.value === '发电') item.color = '#f0f0a0'
})
}
},
immediate: true,
deep: true
}
},
mounted() {},
methods: {}
}
</script>
<style lang="scss" scoped>
.total-station {
height: calc(100% - 45px);
display: flex;
justify-content: center;
align-items: center;
padding-left: 0px;
}
.item {
height: calc(50% - 10px);
background: url('../../assets//home/onLineBg.png');
background-size: contain;
background-size: 100% 100%;
background-repeat: no-repeat;
padding: 8px 3px;
min-width: 115px;
display: flex;
flex-direction: column;
background-color: #072d42;
& > span:nth-child(1) {
font-size: 12px;
margin-bottom: 10px;
}
.d {
margin-left: 1px;
font-size: 12px;
}
}
.content-my {
// background-color: chocolate;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
// align-items: center;
justify-content: flex-start;
height: 100%;
.item {
width: calc(33% - 6px);
margin-left: 3px;
margin-right: 3px;
margin-top: 8px;
}
}
.content-left,
.content-right {
width: 40%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
height: 100%;
.item {
align-items: flex-start;
justify-content: center;
}
}
.online-icon {
width: 20%;
height: 130px;
background-image: url('@/assets/home/onLineIcon.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.item-3 {
margin-right: auto;
}
.item-4 {
margin-left: auto;
}
</style>

View File

@@ -1,6 +1,16 @@
<template> <template>
<div class="onLine"> <div class="onLine">
<div class="content-left"> <div class="content-my">
<div v-for="item in myItems" :key="item.key" :class="`item ${item.class}`" >
<span style="height: 50%; color:#d0d0d0; margin:0 0 0 0">{{ item.label }}</span>
<div style="height: 50%; margin-left: 20%;">
<span style="color:#a0f0a0; font-size:16px; font-weight:600;">{{ item.value ? item.value : 0 }}</span>
<span style="font-size:16px; margin-left: 8px;">{{ item.d }}</span>
</div>
</div>
</div>
<!-- <div class="content-left">
<div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in leftList" :key="item.key" :class="`item ${item.class}`">
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
<div> <div>
@@ -8,9 +18,9 @@
><span class="d">{{ item.d }}</span> ><span class="d">{{ item.d }}</span>
</div> </div>
</div> </div>
</div> </div> -->
<div class="online-icon"></div> <!-- <div class="online-icon"></div> -->
<div class="content-right"> <!-- <div class="content-right">
<div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`"> <div v-for="item in rightList" :key="item.key" :class="`item ${item.class}`">
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
<div> <div>
@@ -18,7 +28,7 @@
><span class="d">{{ item.d }}</span> ><span class="d">{{ item.d }}</span>
</div> </div>
</div> </div>
</div> </div> -->
</div> </div>
</template> </template>
@@ -26,11 +36,11 @@
export default { export default {
name: '', name: '',
props: { props: {
infoKey: { propKey: {
type: String, type: String,
default: '' default: ''
}, },
total: { propData: {
type: Object, type: Object,
default: () => {} default: () => {}
}, },
@@ -41,13 +51,26 @@ export default {
}, },
data() { data() {
return { return {
myItems: [
{ key: 'runDays', value: 0, label:'系统运行天数', d:'天'},
{ key: 'storage_device_num', value: 0, label:'储能设备数量', d:'个'},
{ key: 'charge_device_num', value: 0, label:'充电设备数量', d:'个'},
{ key: 'solar_device_num', value: 0, label:'光伏设备数量', d:'个'},
{ key: 'solar_elect_grid', value: 0, label:'上网总电量', d:'kWh'},
{ key: 'storage_elect_in', value: 0, label:'储能充电总电量', d:'kWh'},
{ key: 'charge_elect_out', value: 0, label:'充电桩充电总电量', d:'kWh'},
{ key: 'solar_elect_gen', value: 0, label:'光伏发电总电量', d:'kWh'},
{ key: 'income_elect', value: 0, label:'累计收益总金额', d:'元'},
{ key: 'storage_elect_out', value: 0, label:'储能放电总电量', d:'kWh'},
],
curList: [ curList: [
{ {
key: 'runDays', //根据launch_date字段计算得出 key: 'runDays', //根据launch_date字段计算得出
value: 20, value: 20,
d: '天', d: '天',
label: '系统运行天数', label: '系统运行天数',
class: 'item-1' class: 'item-2'
}, },
{ {
key: 'income_total', key: 'income_total',
@@ -97,10 +120,16 @@ export default {
}, },
watch: { watch: {
total: { propKey: {
handler(newVal, oldVal) {
if (this.propKey === 'totalStation') this.myItems[0].label = '场站运行天数'
},
immediate: true,
},
propData: {
handler(newVal, oldVal) { handler(newVal, oldVal) {
if (newVal && newVal !== oldVal) { if (newVal && newVal !== oldVal) {
this.curList.forEach((item) => { this.myItems.forEach((item) => {
item.value = newVal[item.key] || 0 item.value = newVal[item.key] || 0
}) })
} }
@@ -128,8 +157,8 @@ export default {
background-size: contain; background-size: contain;
background-size: 100% 100%; background-size: 100% 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
padding: 10px 8px; padding: 3px 3px;
min-width: 115px; // min-width: 100px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background-color: #072d42; background-color: #072d42;
@@ -143,6 +172,22 @@ export default {
font-size: 12px; font-size: 12px;
} }
} }
.content-my {
// background-color: chocolate;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
// align-items: center;
justify-content: flex-start;
height: 100%;
.item {
width: calc(25% - 6px);
margin-left: 3px;
margin-right: 3px;
margin-top: 8px;
}
}
.content-left, .content-left,
.content-right { .content-right {

View File

@@ -1,6 +1,11 @@
<template> <template>
<div class="device" ref="device"> <div class="device" ref="device" :style="{ width: systemType==2 ? '420px': '100%'}">
<div class="device-item" v-for="item in deviceList" :key="item"> <div class="device-item"
v-for="item in deviceList" :key="item.device_id"
@click="chooseItem(item)"
:class="systemType==2 && selectedDeviceId==item.device_id ? 'active' : ''"
:style="{minWidth: systemType==2 ? '420px' : '380px'}"
>
<div class="item-header"> <div class="item-header">
<div style="display: flex; width: 50%"> <div style="display: flex; width: 50%">
<div class="icon-bg"> <div class="icon-bg">
@@ -9,7 +14,7 @@
<div class="title"> <div class="title">
<span class="number type">{{ item.typename }}</span> <span class="number type">{{ item.typename }}</span>
<span class="name" :title="item.name">{{ item.name }}</span> <span class="name" :title="item.name">{{ item.name }}</span>
<span class="number">{{ item.device_id }}</span> <span class="number"></span>
</div> </div>
</div> </div>
@@ -18,60 +23,31 @@
<a-tag :color="item.is_online == 1 ? 'green' : 'red'">{{ <a-tag :color="item.is_online == 1 ? 'green' : 'red'">{{
['离线', '在线'][item.is_online] ['离线', '在线'][item.is_online]
}}</a-tag> }}</a-tag>
<span class="text">在线状态</span> <!-- <span class="text">在线状态</span> -->
</div>
<div class="status-item">
<a-tag :color="item.is_error == 0 ? 'green' : 'red'">{{
['正常', '错误'][item.is_error]
}}</a-tag>
<span class="text">故障状态</span>
</div> </div>
<div class="status-item"> <div class="status-item">
<a-tag :color="item.is_running == 0 ? 'orange' : 'green'">{{ <a-tag :color="item.is_running == 0 ? 'orange' : 'green'">{{
['空闲', '工作'][item.is_running] ['空闲', '工作'][item.is_running]
}}</a-tag> }}</a-tag>
<!-- <span class="text">工作状态</span> -->
</div>
<div class="status-item">
<a-tag :color="item.is_error == 0 ? 'green' : 'red'">{{
['正常', '故障'][item.is_error]
}}</a-tag>
<!-- <span class="text">故障状态</span> -->
</div>
<span class="text">工作状态</span>
</div> </div>
</div> </div>
</div>
<div class="item-gun" v-if="item.type == 106">
<div class="gun">
<div class="header">
<div class="verline"></div>
<span>1</span>
</div>
<div class="gun-content">
<div v-for="info in item.params" :key="info.k" class="gun-info">
<span class="text">{{ info.k }}</span>
<span class="value">{{ info.v }}</span> <div class="item-content" v-if="systemType!=2">
</div>
</div>
</div>
<div class="gun">
<div class="header">
<div class="verline"></div>
<span>2</span>
</div>
<div class="gun-content">
<div v-for="info in item.params1" :key="info.k" class="gun-info">
<span class="text">{{ info.k }}</span>
<span class="value">{{ info.v }}</span>
</div>
</div>
</div>
</div>
<div class="item-content" v-else>
<div v-for="info in item.params" :key="info.k" class="item-info"> <div v-for="info in item.params" :key="info.k" class="item-info">
<span class="text">{{ info.k }}</span> <span class="text">{{ info.k }}</span>
<span class="value">{{ info.v }}</span> <span class="value">{{ info.v }}</span>
</div> </div>
</div> </div>
<div class="item-button"> <div class="item-button" v-if="systemType!=2">
<div v-if="item.view == 1"> <div v-if="item.view == 1">
<span class="text">实时数据</span> <span class="text">实时数据</span>
<a-button type="primary" size="small" @click="openModal(item, 1)">查看</a-button> <a-button type="primary" size="small" @click="openModal(item, 1)">查看</a-button>
@@ -82,6 +58,35 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div style="width: calc(100% - 500px);" v-if="systemType==2">
<div class="item-gun" >
<div class="gun">
<div class="header">
<div class="verline"></div>
<span style="font-size: 16px; font-weight: 1000; color: #5bcdd1">1</span>
</div>
<div class="gun-content">
<div v-for="info in (selectedItem ? selectedItem.params : [])" :key="info.k" class="gun-info">
<span class="text">{{ info.k }}</span>
<span class="value">{{ info.v }}</span>
</div>
</div>
</div>
<div class="gun">
<div class="header">
<div class="verline"></div>
<span style="font-size: 16px; font-weight: 1000; color: #5bcdd1">2</span>
</div>
<div class="gun-content">
<div v-for="info in (selectedItem ? selectedItem.params1 : [])" :key="info.k" class="gun-info">
<span class="text">{{ info.k }}</span>
<span class="value">{{ info.v }}</span>
</div>
</div>
</div>
</div>
</div>
<a-modal <a-modal
v-model:open="modalOpen" v-model:open="modalOpen"
@ok="handleOk" @ok="handleOk"
@@ -129,7 +134,6 @@
</a-table> </a-table>
</div> </div>
</a-modal> </a-modal>
</div>
</template> </template>
<script> <script>
@@ -147,13 +151,15 @@ export default {
systemType: { systemType: {
type: Number, type: Number,
default: 1 default: 1
} },
propType: { type: Number, default: 1 }
}, },
data() { data() {
return { return {
modalOpen: false, modalOpen: false,
deviceList: [], deviceList: [],
selectedDeviceId: undefined,
selectedItem: undefined,
chartOptions: [ chartOptions: [
{ {
type: 'line', type: 'line',
@@ -270,11 +276,16 @@ export default {
// 监听父组件数据变化 // 监听父组件数据变化
stationId(newVal) { stationId(newVal) {
if (newVal) { if (newVal) {
this.selectedItem = undefined
this.selectedDeviceId = undefined
this.getDeviceList() this.getDeviceList()
} }
}, },
systemType(newVal, oldVal) { systemType(newVal, oldVal) {
if (newVal !== oldVal) { if (newVal !== oldVal) {
this.selectedItem = undefined
this.selectedDeviceId = undefined
this.deviceList = []
this.getDeviceList() this.getDeviceList()
} }
} }
@@ -282,7 +293,7 @@ export default {
mounted() { mounted() {
this.getDeviceList() this.getDeviceList()
this.timer=setInterval(() => { this.timer=setInterval(() => {
this.getDeviceList() // this.getDeviceList()
}, 20000) }, 20000)
}, },
@@ -291,6 +302,10 @@ export default {
}, },
methods: { methods: {
chooseItem(item) {
this.selectedItem = item
this.selectedDeviceId = item.device_id
},
handlePagesizeChange(pageOption) { handlePagesizeChange(pageOption) {
this.pageOption.pageSize = pageOption.pageSize this.pageOption.pageSize = pageOption.pageSize
this.pageOption.page = pageOption.page this.pageOption.page = pageOption.page
@@ -313,7 +328,6 @@ export default {
// 格式化小时和分钟,确保两位数 // 格式化小时和分钟,确保两位数
const formattedHour = hour.toString().padStart(2, '0') const formattedHour = hour.toString().padStart(2, '0')
const formattedMinute = minute.toString().padStart(2, '0') const formattedMinute = minute.toString().padStart(2, '0')
timePoints.push(`${formattedHour}:${formattedMinute}`) timePoints.push(`${formattedHour}:${formattedMinute}`)
} }
} }
@@ -363,11 +377,17 @@ export default {
//请求运行监控系统设备信息 //请求运行监控系统设备信息
async getDeviceList() { async getDeviceList() {
try { try {
const res = await getReq('/queryDevicByCategory', { const res = await getReq('/queryDevicByCategory', {
station_id: this.stationId, station_id: this.stationId,
category: this.systemType category: this.systemType
}) })
if (this.selectedDeviceId == undefined) {
if (res.data.length > 0) {
this.selectedItem = res.data[0]
this.selectedDeviceId = this.selectedItem.device_id
}
}
this.deviceList = res.data this.deviceList = res.data
this.$emit('updateGatewayData', res.gateway); this.$emit('updateGatewayData', res.gateway);
@@ -395,12 +415,13 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.device { .device {
// background-color: #08a5ff;
width: 100%; width: 100%;
height: 100%; height: 100%;
margin-left: 20px; margin-left: 20px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
grid-gap: 20px; grid-gap: 15px;
overflow-y: auto; overflow-y: auto;
align-content: flex-start; align-content: flex-start;
// grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); // grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
@@ -408,10 +429,16 @@ export default {
border-radius: 15px; border-radius: 15px;
background: $bg2-color; background: $bg2-color;
padding: 15px; padding: 15px;
min-width: 390px; min-width: 380px;
max-width: 450px; max-width: 450px;
width: calc(25% - 15px);
// height: 260px; // height: 260px;
flex: 1; // flex: 1;
cursor: pointer;
&:hover {
border: 1px solid #aaa;
}
.item-header { .item-header {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -491,11 +518,51 @@ export default {
height: 24px; height: 24px;
} }
} }
.item-gun { .item-button {
display: grid;
grid-template-columns: 1fr 1fr;
color: #fff;
margin-bottom: 3px;
padding: 0 5px;
// div {
// width: calc(50% - 10px);
// }
}
.text {
color: $text-color;
font-size: 13px;
}
.video {
margin-top: 10px;
}
}
.active {
// background: #012036;
border: 1px solid #aaa;
}
.content-table {
height: 700px;
margin-top: 40px;
:deep(.ant-table-header tr th) {
background: $table-border !important;
color: #fff;
}
:deep(.ant-table-body tr td, .ant-table-cell) {
background: $table-bg !important;
color: #fff;
}
}
}
.item-gun {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
gap: 20px; gap: 20px;
width: 100%; width: 100%;
height: 100%;
.gun { .gun {
border: 1px solid #37d6d970; border: 1px solid #37d6d970;
border-radius: 5px; border-radius: 5px;
@@ -524,46 +591,25 @@ export default {
.gun-content { .gun-content {
display: grid; display: grid;
grid-template-columns: 1fr; grid-template-columns: 1fr;
height: 120px; height: 200px;
padding: 0 5px; padding: 0 5px;
overflow-y: auto; overflow-y: auto;
.gun-info { .gun-info {
height: 30px; height: 30px;
}
}
}
.item-button {
display: grid;
grid-template-columns: 1fr 1fr;
color: #fff;
margin-bottom: 3px;
padding: 0 5px;
// div {
// width: calc(50% - 10px);
// }
}
.text {
color: $text-color;
font-size: 13px;
}
.video {
margin-top: 10px;
}
}
.content-table {
height: 700px;
margin-top: 40px;
:deep(.ant-table-header tr th) { .text {
background: $table-border !important; margin-left: 20px;
color: #fff; color: $text-color;
font-size: 14px;
}
.value {
font-weight: 700;
font-size: 16px;
} }
:deep(.ant-table-body tr td, .ant-table-cell) {
background: $table-bg !important;
color: #fff;
} }
} }
} }
.environment { .environment {
width: 200px; width: 200px;
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="videosPage" id="videosPage"> <!-- <div class="videosPage" id="videosPage">
<div <div
class="content" class="content"
:class="videosPageWidth < 900 ? 'con-w2' : 'con-w1'" :class="videosPageWidth < 900 ? 'con-w2' : 'con-w1'"
@@ -8,9 +8,29 @@
> >
<haikang :index="index" :item="item" class="video"></haikang> <haikang :index="index" :item="item" class="video"></haikang>
</div> </div>
</div> </div> -->
<div class="environment"> <div class="environment">
<div class="tab-header"> <!-- <div style="display: flex; flex-direction: row;"> -->
<!-- <div style="background-color: chocolate; width: 24%; height: 100px; margin: 5px 5px 5px 5px;"> </div>
<div style="background-color: chocolate; width: 24%; height: 100px; margin: 5px 5px 5px 5px;"> </div>
<div style="background-color: chocolate; width: 24%; height: 100px; margin: 5px 5px 5px 5px;"> </div>
<div style="background-color: chocolate; width: 24%; height: 100px; margin: 5px 5px 5px 5px;"> </div> -->
<div class="env-content">
<div v-for="item in tabList" :key="item.key" class="env-item">
<div class="tab">
<span :class="['uactived']" @click="activeTab = item.key">{{ item.name
}}</span>
</div>
<div class="table-content">
<ComTable :columns="columns[item.key]" :table-data="tableDatas[item.key]" ref="comTable"
:table-option="{ page: false, select: false }">
</ComTable>
</div>
</div>
</div>
<!-- </div> -->
<!-- <div class="tab-header">
<div v-for="item in tabList" :key="item.key" class="tab"> <div v-for="item in tabList" :key="item.key" class="tab">
<span <span
:class="[activeTab == item.key ? 'actived' : 'uactived']" :class="[activeTab == item.key ? 'actived' : 'uactived']"
@@ -27,7 +47,7 @@
:table-option="{ page: false, select: false }" :table-option="{ page: false, select: false }"
> >
</ComTable> </ComTable>
</div> </div> -->
</div> </div>
</template> </template>
@@ -128,15 +148,14 @@ export default {
key: 'cooling', key: 'cooling',
name: '冷机信息' name: '冷机信息'
}, },
{
key: 'fire40',
name: '消防信息'
},
{ {
key: 'airc', key: 'airc',
name: '空调信息' name: '空调信息'
}, },
{
key: 'fire40',
name: '消防信息'
}
], ],
tableDatas: {}, tableDatas: {},
@@ -161,9 +180,9 @@ export default {
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
const div = document.getElementById('videosPage') // const div = document.getElementById('videosPage')
const width = div.offsetWidth // const width = div.offsetWidth
this.videosPageWidth = width // this.videosPageWidth = width
}) })
this.getEnvironment() this.getEnvironment()
@@ -233,10 +252,42 @@ export default {
} }
} }
.environment { .environment {
width: 430px; width: 100%; //430px;
margin-left: 20px; margin-left: 20px;
color: #fff; color: #fff;
.env-content {
width: 100%;
height: 100%;
display: flex;
.env-item {
width: 24%;
.tab {
&>span {
font-size: 14px;
margin-right: 15px;
display: inline-block;
padding: 10px;
// cursor: pointer;
border: 1px solid $tab-border;
border-radius: 4px;
text-align: center;
width: 50%;
}
}
.actived {
color: #ffffff;
background-color: $green;
}
.uactived {
color: #a6b8dd;
background-color: $bg2-color;
}
}
}
.title { .title {
font-size: 24px; font-size: 24px;
font-weight: 700; font-weight: 700;
@@ -291,6 +342,7 @@ export default {
} }
.table-content { .table-content {
margin-top: 20px; margin-top: 20px;
margin-right: 10px;
height: calc(100% - 60px); height: calc(100% - 60px);
:deep(.ant-table) { :deep(.ant-table) {
border-radius: 10px 10px 0 0 !important; border-radius: 10px 10px 0 0 !important;

View File

@@ -128,6 +128,7 @@ export default {
getCommonOption(option, dataKeys, isLineChart = false) { getCommonOption(option, dataKeys, isLineChart = false) {
console.log(option,"ooooooooooooo") console.log(option,"ooooooooooooo")
return { return {
animation: false,
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { type: 'shadow' }, axisPointer: { type: 'shadow' },
@@ -197,9 +198,9 @@ export default {
series: option.infoKeys.map((info, i) => ({ series: option.infoKeys.map((info, i) => ({
name: info.label, name: info.label,
type: 'bar', type: 'bar',
barWidth: 10, barWidth: '20%',
itemStyle: { itemStyle: {
borderRadius: [10, 10, 0, 0], borderRadius: [0, 0, 0, 0],
color: info.lineColor, color: info.lineColor,
}, },
index:option.yAxisOption&&option.yAxisOption.length?i:1, index:option.yAxisOption&&option.yAxisOption.length?i:1,

View File

@@ -8,9 +8,9 @@ export function getRunDays(date) {
return daysRun return daysRun
} }
export function processData(data, keys) { export function processData(data, keys) {
data.sort((a, b) => { // data.sort((a, b) => {
return new Date(a.dt) - new Date(b.dt) // return new Date(a.dt) - new Date(b.dt)
}) // })
const dates = data.map((item) => item.dt) const dates = data.map((item) => item.dt)
const values = [] const values = []
keys.forEach((item, index) => { keys.forEach((item, index) => {

View File

@@ -9,9 +9,9 @@
>{{ station.name }} >{{ station.name }}
</a-select-option> </a-select-option>
</a-select> </a-select>
<a-button type="primary" @click="handleMessage" style="margin-left: 20px">查看预制舱参数</a-button> <a-button type="primary" @click="handleMessage" style="margin-left: 20px">运行参数查看</a-button>
<a-button type="primary" @click="openDispatchModeModal" style="margin-left: 20px">模式设置</a-button> <a-button type="primary" @click="openDispatchModeModal" style="margin-left: 20px">运行模式设置</a-button>
<a-button type="primary" @click="openDispatchParamModal" style="margin-left: 20px">参数设置</a-button> <a-button type="primary" @click="openDispatchParamModal" style="margin-left: 20px">运行参数设置</a-button>
</div> </div>
</div> </div>
<!-- <div class="right"> <!-- <div class="right">
@@ -133,11 +133,11 @@ export default {
msgModal: false, msgModal: false,
systems: [ systems: [
{ {
name: '储能系统', name: '储能设备',
titles: [ titles: [
{ v: '运行模式', key: 'workmode' }, // { v: '运行模式', key: 'workmode' },
{ v: '储能EMU状态', key: 'emu' }, // { v: '储能EMU状态', key: 'emu' },
{ v: '充电桩状态', key: 'cdz' } // { v: '充电桩状态', key: 'cdz' }
//{ v: '总有功功率(台区)', key: 'power', sufix: 'kW' } //{ v: '总有功功率(台区)', key: 'power', sufix: 'kW' }
], ],
power: 60, power: 60,
@@ -145,33 +145,33 @@ export default {
systemType: 1 systemType: 1
}, },
{ {
name: '充电系统', name: '充电设备',
power: 60, power: 60,
num: 62, num: 62,
systemType: 2, systemType: 2,
titles: [ titles: [
//{ v: '总功率', key: 'power', sufix: 'kW' }, //{ v: '总功率', key: 'power', sufix: 'kW' },
{ v: '数量', key: 'num' } // { v: '数量', key: 'num' }
] ]
}, },
{ {
name: '光伏系统', name: '光伏设备',
power: 60, power: 60,
num: 62, num: 62,
systemType: 3, systemType: 3,
titles: [ titles: [
//{ v: '总功率', key: 'power', sufix: 'kW' }, //{ v: '总功率', key: 'power', sufix: 'kW' },
{ v: '数量', key: 'num' } // { v: '数量', key: 'num' }
] ]
}, },
{ {
name: '安防系统', name: '辅助设备',
power: 60, power: 60,
num: 62, num: 62,
systemType: 4, systemType: 4,
titles: [ titles: [
// { v: '总功率', key: 'power', sufix: 'kW' }, // { v: '总功率', key: 'power', sufix: 'kW' },
{ v: '数量', key: 'num' } // { v: '数量', key: 'num' }
] ]
} }
// { // {
@@ -203,7 +203,7 @@ export default {
}, },
{ {
value: 5, value: 5,
label: '自定时段' label: '运营支撑'
} }
], ],
deviceGroup: [], deviceGroup: [],
@@ -224,7 +224,7 @@ export default {
{ value: '2', label: '配网增容' }, { value: '2', label: '配网增容' },
{ value: '3', label: '应急供电' }, { value: '3', label: '应急供电' },
{ value: '4', label: '并网保电' }, { value: '4', label: '并网保电' },
{ value: '5', label: '自定时段' } { value: '5', label: '运营支撑' }
], ],
options: { label: 'label', value: 'value' } options: { label: 'label', value: 'value' }
} }
@@ -509,7 +509,6 @@ export default {
chooseStation(system) { chooseStation(system) {
console.log(system, 'system') console.log(system, 'system')
this.systemType = system.systemType this.systemType = system.systemType
} }
} }
@@ -551,40 +550,43 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.stations { .stations {
display: grid; display: flex;
flex-direction: column;
//grid-template-rows: repeat(auto-fit, minmax(140px, 4fr));
border-radius: 12px; border-radius: 12px;
background: $bg2-color; background: $bg2-color;
padding-top: 15px; padding-top: 15px;
grid-template-rows: repeat(auto-fit, minmax(140px, 4fr));
.station-item { .station-item {
flex: 1; // flex: 1;
margin: 0 15px 15px 15px; margin: 0 15px 15px 15px;
border-radius: 12px; border-radius: 10px;
width: 180px; width: 180px;
height: 50px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
color: #fff; // color: #fff;
padding: 10px 10px; // padding: 10px 10px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: $table-bg; background: $table-bg;
} }
.name { .name {
padding-left: 20px;
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
line-height: 50px; line-height: 50px;
} }
.des { // .des {
font-size: 14px; // font-size: 14px;
font-weight: 600; // font-weight: 600;
line-height: 30px; // line-height: 30px;
display: inline-block; // display: inline-block;
max-width: 160px; // max-width: 160px;
white-space: nowrap; // white-space: nowrap;
overflow: hidden; // overflow: hidden;
text-overflow: ellipsis; // text-overflow: ellipsis;
} // }
} }
.active { .active {
background: $bg3-color; background: $bg3-color;

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="Home"> <div class="Home">
<div class="content-left"> <div class="content-left">
<div v-for="item in leftList" :key="item.componentId" :class="`grid-item ${item.class}`"> <div v-for="item in listLeft" :key="item.componentId" :class="`grid-item ${item.class}`">
<div class="tool"> <div class="tool">
<div class="title"> <div class="title">
<i class="iconfont icon-hebing linear-text"></i> <i class="iconfont icon-hebing linear-text"></i>
@@ -9,30 +9,32 @@
</div> </div>
</div> </div>
<component <component :is="item.componentId" :prop-key="item.infoKey" :prop-option="compInfo[item.infoKey]"
:is="item.componentId" :prop-data="compData[item.infoKey]">
:info-key="item.infoKey" </component>
:device-info="deviceInfo[item.infoKey]"
:total="item.infoKey === 'onLineTotal' ? deviceInfo.onLine : deviceInfo.allTotal"
></component>
</div> </div>
</div> </div>
<div class="tianditu"> <div class="tianditu">
<Map @changeStation="getCurrentStation"></Map> <Map @changeStation="getCurrentStation"></Map>
</div> </div>
<div class="content-right"> <div class="content-right">
<div v-for="item in rightList" :key="item.componentId" :class="`grid-item ${item.class}`"> <div style="width:100%; height:32px;">
<span style="width:120px">场站选择</span>
<a-select v-model:value="selectStationId" style="margin-left: 10px; width: 200px;" @change="getStationChange">
<a-select-option v-for="station in stationList" :value="station['station_id']">{{ station.name }}
</a-select-option>
</a-select>
</div>
<div v-for="item in listRight" :key="item.componentId" :class="`grid-item ${item.class}`">
<div class="tool"> <div class="tool">
<div class="title"> <div class="title">
<i class="iconfont icon-hebing linear-text"></i> <i class="iconfont icon-hebing linear-text"></i>
<span class="linear-text">{{ item.title }}</span> <span class="linear-text">{{ item.title }}</span>
</div> </div>
</div> </div>
<component <component :is="item.componentId" :prop-key="item.infoKey" :prop-option="compInfo[item.infoKey]"
:is="item.componentId" :prop-data="compDataStation[item.infoKey]">
:device-info="deviceInfo[item.infoKey]" </component>
:total="item.infoKey === 'onLineTotal' ? deviceInfo.onLine : deviceInfo.allTotal"
></component>
</div> </div>
</div> </div>
</div> </div>
@@ -40,12 +42,14 @@
<script> <script>
import onLine from '@/components/Home/onLine.vue' import onLine from '@/components/Home/onLine.vue'
import TotalStation from '@/components/Home/TotalStation.vue'
import Operational from '@/components/Home/Operational.vue' import Operational from '@/components/Home/Operational.vue'
import Energy from '@/components/Home/Energy.vue' import Energy from '@/components/Home/Energy.vue'
import Charge from '@/components/Home/Charge.vue' import Charge from '@/components/Home/Charge.vue'
import Pv from '@/components/Home/Pv.vue' import Pv from '@/components/Home/Pv.vue'
import Alarm from '@/components/Home/Alarm.vue' import Alarm from '@/components/Home/Alarm.vue'
import Map from '@/components/Home/Map.vue' import Map from '@/components/Home/Map.vue'
import MyChartBar from '@/components/Home/MyChartBar.vue'
import { getReq, postReq } from '@/request/api' import { getReq, postReq } from '@/request/api'
import { getRunDays, getDateDaysAgo } from '@/utils/dealWithData' import { getRunDays, getDateDaysAgo } from '@/utils/dealWithData'
import { markRaw } from 'vue' import { markRaw } from 'vue'
@@ -54,13 +58,70 @@ export default {
components: { Map }, components: { Map },
data() { data() {
return { return {
refreshInterval:null, refreshInterval: null,
showFlag: false, showFlag: false,
stationId: null, stationId: null,
deviceInfo: {}, compData: {
total: {},
energy: [],
charge: [],
pv: [],
stateGrid: [],
},
compDataStation: {
totalStation: {},
energy: [],
charge: [],
pv: [],
stateGrid: [],
},
compInfo: {
total: {},
energy: {
yAxis: ['电量(kWh)'],
series: [
{ name: '日充电电量', key: 'storage_elect_in', color: '#22E4FF' },
{ name: '日放电电量', key: 'storage_elect_out', color: '#0E68E4' },
]
},
pv: {
yAxis: ['电量(kWh)'],
series: [
{ name: '日发电电量', key: 'solar_elect_gen', color: '#22E4FF' },
]
},
charge: {
yAxis: ['电量(kWh)'],
series: [
{ name: '日充电电量', key: 'charge_elect', color: '#22E4FF' },
]
},
stateGrid: {
yAxis: ['电量(kWh)'],
series: [
{ name: '日上网电量', key: 'solar_elect_grid', color: '#22E4FF' },
]
}
},
listLeft: [
{ title: '系统运行统计', class: 'online-status', componentId: markRaw(onLine), infoKey: 'total' },
{ title: '储能设备', class: 'energy-status', componentId: markRaw(MyChartBar), infoKey: 'energy' },
{ title: '充电设备', class: 'charge-analysis', componentId: markRaw(MyChartBar), infoKey: 'charge' },
{ title: '光伏设备', class: 'work-order', componentId: markRaw(MyChartBar), infoKey: 'pv' },
{ title: '电网侧', class: 'work-order', componentId: markRaw(MyChartBar), infoKey: 'stateGrid' },
],
listRight: [
{ title: '场站运行统计', class: 'online-status', componentId: markRaw(TotalStation), infoKey: 'totalStation' },
{ title: '储能设备', class: 'energy-status', componentId: markRaw(MyChartBar), infoKey: 'energy' },
{ title: '充电设备', class: 'charge-analysis', componentId: markRaw(MyChartBar), infoKey: 'charge' },
{ title: '光伏设备', class: 'work-order', componentId: markRaw(MyChartBar), infoKey: 'pv' },
{ title: '电网侧', class: 'work-order', componentId: markRaw(MyChartBar), infoKey: 'stateGrid' },
],
stationList: [],
selectStationId: '',
list: [ list: [
{ {
title: '运行状态', title: '系统运行统计',
class: 'online-status', class: 'online-status',
componentId: markRaw(onLine), componentId: markRaw(onLine),
infoKey: 'onLineTotal' infoKey: 'onLineTotal'
@@ -83,7 +144,6 @@ export default {
componentId: markRaw(Charge), componentId: markRaw(Charge),
infoKey: 'charge' infoKey: 'charge'
}, },
{ {
title: '光伏设备', title: '光伏设备',
class: 'work-order', class: 'work-order',
@@ -104,93 +164,96 @@ export default {
}, },
computed: { computed: {
leftList() { leftList() {
return this.list.filter((_, index) => index % 2 === 0).slice(0, 3) // 左列取前3个偶数索引 return {} //this.list.filter((_, index) => index % 2 === 0).slice(0, 3) // 左列取前3个偶数索引
}, },
rightList() { rightList() {
return this.list.filter((_, index) => index % 2 !== 0).slice(0, 3) // 右列取前3个奇数索引 return {} //this.list.filter((_, index) => index % 2 !== 0).slice(0, 3) // 右列取前3个奇数索引
} }
}, },
beforeUnmount() { beforeUnmount() {
if(this.refreshInterval){ if (this.refreshInterval) {
clearInterval(this.refreshInterval) clearInterval(this.refreshInterval)
this.refreshInterval=null this.refreshInterval = null
} }
}, },
async mounted() { async mounted() {
await this.getStationList()
await this.loadAllData() await this.loadAllData()
this.refreshInterval=setInterval(async()=>{ this.refreshInterval = setInterval(async () => {
await this.loadAllData() await this.loadAllData()
},30000) //30s刷新一次 }, 30000) //30s刷新一次
}, },
methods: { methods: {
async loadAllData(){ async loadAllData() {
await Promise.all([ await Promise.all([
this.getOnLineList(), this.queryStatTotal(),
this.getStatTotalList(), this.queryStatTotal(this.selectStationId),
this.getOperTotalList(), // this.getOperTotalList(),
this.getStatDayList(1), this.getStatDayList(),
this.getStatDayList(2), this.getStatDayList(this.selectStationId),
this.getStatDayList(3) // this.getStatDayList(1),
// this.getStatDayList(2),
// this.getStatDayList(3)
]).then((r) => { ]).then((r) => {
if ( // if (
this.deviceInfo.energy && // this.compData.energy &&
this.deviceInfo.charge && // this.compData.charge &&
this.deviceInfo.pv // this.compData.pv
) { // ) {
const newArr = this.mergedArray( // const newArr = this.mergedArray(
this.deviceInfo.energy, // this.compData.energy,
this.deviceInfo.charge, // this.compData.charge,
this.deviceInfo.pv // this.compData.pv
) // )
this.deviceInfo.alarm = newArr // this.compData.alarm = newArr
} // }
}) })
}, },
getCurrentStation(e) { getCurrentStation(e) {
this.stationId = e this.stationId = e
}, },
// 查询系统统计信息 // 查询系统的场站列表
async getOnLineList() { async getStationList() {
try { try {
// token: 用户TOKEN const res = await getReq('/queryStationList', { page: 0, page_size: 100 })
const res = await getReq('/queryStatSystem')
if (res.errcode === 0) { if (res.errcode === 0) {
this.deviceInfo.onLine = JSON.parse(JSON.stringify(res.data)) // 设置场站下拉列表,默认选中第一项
this.deviceInfo.onLine.runDays = getRunDays(res.data.launch_date) this.stationList = res.data
this.selectStationId = this.stationList[0]['station_id']
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.deviceInfo.onLine = {} this.stationList = []
this.selectStationId = ''
} }
}, },
// 查询系统累计统计信息, 不传参数 curStationId 时查询所有场站数据
async queryStatTotal(curStationId) {
// 查询系统累计统计信息
async getStatTotalList() {
try { try {
// token: 用户TOKEN const res = await getReq('/queryStatTotal', { station_id: curStationId })
// date:日期
// station_id:场站ID为0或不传查询所有场站总计
// category:类别1:储能设备,2:充电设备,3:光伏设备,为0或不传查询所有类别总计
const query = {
date: getDateDaysAgo(0),
station_id: this.stationId,
category: 0
}
const res = await getReq('/queryStatTotal', query)
if (res.errcode === 0) { if (res.errcode === 0) {
this.deviceInfo.allTotal = res.data // this.compData.total = res.data
const { income_charge: incomeCharge, income_elect: incomeElect } = // const { income_charge: incomeCharge, income_elect: incomeElect } =
this.deviceInfo.allTotal // this.compData.total
this.deviceInfo.allTotal.incomeTotal = +incomeCharge + +incomeElect // this.compData.total.incomeTotal = +incomeCharge + +incomeElect
// this.compData.total.runDays = getRunDays(res.data.launch_date)
if (curStationId === undefined) {
this.compData.total = res.data
this.compData.total.runDays = getRunDays(res.data.launch_date)
} else {
this.compDataStation.totalStation = res.data
this.compDataStation.totalStation.runDays = getRunDays(res.data.launch_date)
}
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.deviceInfo.allTotal = {} this.compData.total = {}
this.deviceInfo.allTotal.incomeTotal = 0 this.compData.total.incomeTotal = 0
} }
}, },
// 运行分析 联调 // 运行分析 联调
@@ -198,35 +261,56 @@ export default {
try { try {
const res = await getReq('/queryStatStation', {}) const res = await getReq('/queryStatStation', {})
if (res.errcode === 0) { if (res.errcode === 0) {
this.deviceInfo.operationTotal = res.data this.compData.operationTotal = res.data
} else { } else {
throw res throw res
} }
} catch (error) { } catch (error) {
this.deviceInfo.operationTotal = [ ] this.compData.operationTotal = []
} }
}, },
// 示例获取7天前的日期
// 查询场站日统计信息 // 查询近7日的统计信息
async getStatDayList(category) { async getStatDayList(curStationId) {
try { try {
if (curStationId === '') {
return
}
// station_id: 场站ID // station_id: 场站ID
// category: 类别: 1储能设备,2:充电设备,3:光伏设备 // category: 类别: 1储能设备,2:充电设备,3:光伏设备
// start_date开始日期格式yyyy-mm-dd // start_date开始日期格式yyyy-mm-dd
// end_date结束日期格式yyyy-mm-dd // end_date结束日期格式yyyy-mm-dd
const query = { let query = {
station_id: this.stationId, //station_id: this.stationId,
category, // category,
start_date: getDateDaysAgo(7 - 1), start_date: getDateDaysAgo(7 - 1),
end_date: getDateDaysAgo(0) end_date: getDateDaysAgo(0)
} }
const arr = { 1: 'energy', 2: 'charge', 3: 'pv' } if (curStationId) {
query.station_id = curStationId
}
//const arr = { 1: 'energy', 2: 'charge', 3: 'pv' }
const res = await getReq('/queryStatDayList', query) const res = await getReq('/queryStatDayList', query)
if (res.errcode === 0) { if (res.errcode === 0) {
this.list.forEach((item) => { if (curStationId) {
this.deviceInfo[arr[category]] = res.data this.compDataStation.energy
}) = this.compDataStation.charge
= this.compDataStation.pv
= this.compDataStation.stateGrid
= res.data
} else {
this.compData.energy
= this.compData.pv
= this.compData.stateGrid
= this.compData.charge
= res.data
}
// this.list.forEach((item) => {
// //this.compData[arr[category]] = res.data
// alert(JSON.stringify(item))
// return
// })
} else { } else {
throw res throw res
} }
@@ -251,6 +335,10 @@ export default {
}) })
}) })
return newArr return newArr
},
getStationChange() {
this.queryStatTotal(this.selectStationId),
this.getStatDayList(this.selectStationId)
} }
} }
} }
@@ -278,13 +366,13 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: space-between; justify-content: flex-start;
} }
.grid-item { .grid-item {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
height: calc(33% - 10px); height: calc(25% - 10px);
z-index: 20; z-index: 20;
.tool { .tool {
@@ -295,7 +383,7 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
height: 45px; height: 32px;
.linear-text { .linear-text {
background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(40, 235, 231, 1) 100%); background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(40, 235, 231, 1) 100%);
@@ -335,12 +423,10 @@ export default {
margin-left: 20px; margin-left: 20px;
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
background: linear-gradient( background: linear-gradient(90deg,
90deg,
rgba(0, 186, 173, 0.15) 0%, rgba(0, 186, 173, 0.15) 0%,
rgba(61, 254, 250, 0.15) 49.2%, rgba(61, 254, 250, 0.15) 49.2%,
rgba(61, 254, 250, 0) 100% rgba(61, 254, 250, 0) 100%);
);
-webkit-background-clip: text; -webkit-background-clip: text;
display: inline-block; display: inline-block;
background-clip: text; background-clip: text;

View File

@@ -2,6 +2,13 @@
<div class="device"> <div class="device">
<searchBox :btn-option-list="btnOptionList" @operateForm="operateForm"></searchBox> <searchBox :btn-option-list="btnOptionList" @operateForm="operateForm"></searchBox>
<div style="display: flex; height: calc(100% - 40px); ">
<div style="display: block; min-width:200px; width: 200px; height: 100%; overflow-y: auto; background-color: #08365c; border-radius: 5px; padding-top: 10px;">
<a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys"
v-model:checkedKeys="checkedKeys" :tree-data="stationTreeData" @select="onSelectStation">
</a-tree>
</div>
<div class="content-table"> <div class="content-table">
<ComTable <ComTable
:columns="columns" :columns="columns"
@@ -27,6 +34,7 @@
</template> </template>
</ComTable> </ComTable>
</div> </div>
</div>
<a-modal v-model:open="formModal" width="750px" style="top: 80px" :footer="null"> <a-modal v-model:open="formModal" width="750px" style="top: 80px" :footer="null">
<!-- action:edit add --> <!-- action:edit add -->
<EditCom <EditCom
@@ -75,7 +83,9 @@ export default {
paramsDate: {}, paramsDate: {},
tableData: [], tableData: [],
tableOption: {}, tableOption: {},
stations: [] //场站列表 stations: [], //场站列表
stationTreeData: [],
selectedStationId: undefined
} }
}, },
computed: {}, computed: {},
@@ -93,8 +103,8 @@ export default {
mounted() { mounted() {
this.operateList = this.$getBtns(['查看', '修改', '删除']) this.operateList = this.$getBtns(['查看', '修改', '删除'])
this.btnOptionList = this.$getBtns(['新增']) this.btnOptionList = this.$getBtns(['新增'])
this.getList()
this.getStations() this.getStations()
//this.getList()
}, },
methods: { methods: {
@@ -103,8 +113,11 @@ export default {
this.stations = [] this.stations = []
try { try {
const res = await getReq('/queryStationList', { page: 0, page_size: 10000 }) const res = await getReq('/queryStationList', { page: 0, page_size: 10000 })
this.stations = res.data this.stations = res.data
this.stationTreeData = []
res.data.forEach((item)=>{
this.stationTreeData.push( { title: item.name, key: item.station_id})
})
} catch (error) { } catch (error) {
this.stations = [] this.stations = []
} }
@@ -122,6 +135,7 @@ export default {
const { page, pageSize } = this.pageOption const { page, pageSize } = this.pageOption
const params = { const params = {
station_id: this.selectedStationId,
...this.paramsDate, ...this.paramsDate,
page_size: pageSize, page_size: pageSize,
page page
@@ -216,6 +230,10 @@ export default {
this.pageOption.pageSize = pageOption.pageSize this.pageOption.pageSize = pageOption.pageSize
this.pageOption.page = pageOption.page this.pageOption.page = pageOption.page
this.getList() this.getList()
},
onSelectStation(selectedKey, ) {
this.selectedStationId = selectedKey
this.getList()
} }
} }
} }
@@ -229,6 +247,26 @@ export default {
.content-table { .content-table {
width: 100%; width: 100%;
height: calc(100% - 52px); height: calc(100% - 52px);
margin-left: 20px;
} }
} }
:deep(.ant-tree-list) {
background-color: #08365c;
font-size: 16px;
color: white;
}
:deep(.ant-tree-treenode ) {
width: 100%;
height: 30px;
}
:deep(.ant-tree-node-content-wrapper) {
width: calc(100% - 34px);
height: 30px;
}
:deep(.ant-tree-node-selected) {
background-color: #27a188 !important;
border-radius: 5px !important;
}
</style> </style>